summaryrefslogtreecommitdiffstats
path: root/lisp/ravi-init-navigation.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/ravi-init-navigation.el')
-rw-r--r--lisp/ravi-init-navigation.el350
1 files changed, 350 insertions, 0 deletions
diff --git a/lisp/ravi-init-navigation.el b/lisp/ravi-init-navigation.el
new file mode 100644
index 0000000..5a6054d
--- /dev/null
+++ b/lisp/ravi-init-navigation.el
@@ -0,0 +1,350 @@
+;;; ravi-init-navigation.el --- navigation utilities
+
+;; Copyright (C) 2013
+
+;; Author: <ravi@nero.lan>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Buffer navigation utilities
+
+;;; Code:
+
+(use-package region-bindings-mode
+ :config
+ (progn
+ (region-bindings-mode-enable)
+ (bind-key "f" 'forward-word region-bindings-mode-map)
+ (bind-key "b" 'backward-word region-bindings-mode-map)
+
+ ;; HJKL cluster to replace arrow keys
+ (bind-key "h" 'backward-char region-bindings-mode-map)
+ (bind-key "l" 'forward-char region-bindings-mode-map)
+ (bind-key "k" 'previous-line region-bindings-mode-map)
+ (bind-key "j" 'next-line region-bindings-mode-map)
+
+ ;; Most of the time, we mark regions to copy
+ (bind-key "w" 'kill-ring-save region-bindings-mode-map)
+ )
+ :ensure t
+ )
+
+(use-package ace-jump-mode
+ :bind (("M-h" . ace-jump-mode)
+ ("M-H" . ace-jump-line-mode))
+ :ensure t
+ )
+
+(use-package ace-isearch
+ :config
+ (progn
+ (setq ace-isearch-use-ace-jump nil) ; prefer dedicated key for ace-jump
+ (global-ace-isearch-mode +1))
+ :ensure t)
+
+(use-package jump-char
+ :bind (("M-m" . jump-char-forward))
+ :ensure t
+ )
+
+(use-package imenu-anywhere
+ :bind ("s-." . imenu-anywhere)
+ :ensure t
+ )
+
+(use-package expand-region
+ :config
+ (progn
+ (bind-key "C-=" 'er/expand-region))
+ :ensure t
+ )
+
+(use-package multiple-cursors
+ :bind (("C-S-c C-S-c" . mc/edit-lines)
+
+ ("C->" . mc/mark-next-like-this)
+ ("C-<" . mc/mark-previous-like-this)
+ ("C-c C-<" . mc/mark-all-like-this))
+ :config
+ (progn
+ (setq mc/list-file (ravi/emacs-file "past/mc-lists.el"))
+ (bind-key "a" 'mc/mark-all-like-this region-bindings-mode-map)
+ (bind-key "p" 'mc/mark-previous-like-this region-bindings-mode-map)
+ (bind-key "n" 'mc/mark-next-like-this region-bindings-mode-map)
+ (bind-key "m" 'mc/mark-more-like-this-extended region-bindings-mode-map)
+ )
+ :ensure t
+ )
+
+(use-package fold-this
+ :commands fold-this
+ :config
+ (progn
+ (bind-key "t" 'fold-this region-bindings-mode-map))
+ :ensure t
+ )
+
+(use-package indirect
+ :commands indirect-region
+ :config
+ (progn
+ (bind-key "I" 'indirect-region region-bindings-mode-map))
+ )
+
+(use-package visual-regexp
+ :bind (("C-c r" . vr/replace)
+ ("C-c q" . vr/query-replace)
+ ("C-c m" . vr/mc-mark))
+ :ensure t
+ )
+
+(use-package god-mode
+ :bind (("<escape>" . god-local-mode))
+ :disabled t ; less useful than I thought
+ :ensure t
+ )
+
+(bind-key "<M-f6>" 'ff-find-other-file)
+
+(setq compilation-scroll-output 'first-error)
+
+(use-package smartparens
+ :commands (smartparens-mode show-smartparens-mode)
+ :init
+ (show-smartparens-global-mode 1)
+ :config
+ (progn
+ (require 'smartparens-config)
+ (add-hook 'emacs-lisp-mode-hook 'smartparens-mode)
+ (add-hook 'emacs-lisp-mode-hook 'sp-use-smartparens-bindings)
+ (use-package minor-mode-hack :ensure t)
+ (raise-minor-mode-map-alist 'region-bindings-mode)
+ )
+ :ensure t
+ )
+
+;; Marking and moving lines
+
+(defun ravi/pull-up-a-line()
+ "Pull up the next line"
+ (interactive)
+ (join-line -1)
+ )
+
+(bind-key "M-j" 'ravi/pull-up-a-line)
+
+(use-package move-lines
+ :bind (("<S-down>" . move-lines-down)
+ ("<S-up>" . move-lines-up)
+ )
+ )
+
+;; From Kyle Sherman's comment at
+;; http://emacs-fu.blogspot.com/2010/01/duplicating-lines-and-commenting-them.html
+;; \todo Make this work someday with regions too.
+(defun ravi/kyle-sherman-duplicate-line (&optional comment line)
+ "Duplicate the line containing the point.
+\nIf COMMENT is non-nil, also comment out the original line.
+ If LINE is non-nil, duplicate that line instead."
+ (interactive "P")
+ (let ((col (current-column)))
+ (save-excursion
+ (when line
+ (goto-line line))
+ (let ((line (buffer-substring (point-at-bol) (point-at-eol))))
+ (when comment
+ (comment-region (point-at-bol) (point-at-eol)))
+ (goto-char (point-at-eol))
+ (if (eobp)
+ (newline)
+ (forward-line 1))
+ (open-line 1)
+ (insert line)))
+ (forward-line 1)
+ (move-to-column col)))
+
+;; C-: duplicates line, C-u C-: comments first line
+(bind-key "C-:" 'ravi/kyle-sherman-duplicate-line)
+
+(defun ravi/back-to-indentation-or-beginning () (interactive)
+ (if (bolp) (back-to-indentation)
+ (beginning-of-line)))
+(bind-key "C-a" 'ravi/back-to-indentation-or-beginning)
+
+(defun ravi/Fuco-point-in-comment ()
+ "Determine if the point is inside a comment"
+ (interactive)
+ (let ((syn (syntax-ppss)))
+ (and (nth 8 syn)
+ (not (nth 3 syn)))))
+
+(defun ravi/Fuco-end-of-code-or-line+ (arg)
+ "Move to the end of line. If already there, move to the end of code.
+
+ Comments are recognized in any mode that sets syntax-ppss properly."
+ (interactive "P")
+ (let ((eoc (save-excursion
+ (move-end-of-line arg)
+ (while (ravi/Fuco-point-in-comment)
+ (backward-char))
+ (skip-chars-backward " \t")
+ (point))))
+ (cond ((eolp)
+ (move-end-of-line arg)
+ (while (ravi/Fuco-point-in-comment)
+ (backward-char))
+ (skip-chars-backward " \t"))
+ (t
+ (move-end-of-line arg)))))
+(bind-key "C-e" 'ravi/Fuco-end-of-code-or-line+)
+
+;; Use current line for region-based commands if no region selected
+(use-package whole-line-or-region
+ :config
+ (progn
+ (defun turn-on-whole-line-or-region-mode()
+ (interactive)
+ (whole-line-or-region-mode 1)
+ )
+ (add-hook 'prog-mode-hook 'turn-on-whole-line-or-region-mode)
+ )
+ :diminish whole-line-or-region-mode
+ )
+
+;; grep and friends
+
+(use-package wgrep
+ :ensure t
+ )
+
+(if (executable-find "ag")
+ ;; Prefer the silver-searcher if available
+ (use-package ag
+ :bind (("H-g" . ag)
+ ("H-G" . ag-files))
+ :config
+ (progn
+ (setq ag-highlight-search t)
+ (setq ag-reuse-buffers t)
+ (use-package wgrep-ag
+ :ensure t))
+ :ensure t)
+ ;; Use grep if ag is not available on the system
+ (use-package grep
+ :bind (("H-g" . grep))))
+
+(use-package highlight-symbol
+ :bind (("H-n" . ravi/highlight-symbol-next)
+ ("H-N" . highlight-symbol-prev)
+ ("H-s" . highlight-symbol-query-replace))
+ :commands highlight-symbol-next
+ :config
+ (progn
+ (defvar ravi/highlight-symbol-overlay-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "j") 'highlight-symbol-prev)
+ (define-key map (kbd "k") 'highlight-symbol-next)
+ (define-key map (kbd "s") 'highlight-symbol-query-replace)
+ (define-key map (kbd "o") 'highlight-symbol-occur)
+ map))
+ (defun ravi/highlight-symbol-next ()
+ (interactive)
+ (highlight-symbol-next)
+ (set-temporary-overlay-map ravi/highlight-symbol-overlay-map t))
+ )
+ :ensure t
+ )
+
+(let ((ad-redefinition-action 'accept))
+ (use-package color-moccur
+ :commands (isearch-moccur isearch-all)
+ :bind ("M-s O" . moccur)
+ :init
+ (progn
+ (bind-key "M-o" 'isearch-moccur isearch-mode-map)
+ (bind-key "M-O" 'isearch-moccur-all isearch-mode-map))
+
+ :config
+ (use-package moccur-edit)
+
+ :ensure t
+ )
+ )
+
+;; Delete via isearch
+(defun zap-to-isearch (rbeg rend)
+ "Kill the region between the mark and the closest portion of
+ the isearch match string. The behaviour is meant to be analogous
+ to zap-to-char; let's call it zap-to-isearch. The deleted region
+ does not include the isearch word. This is meant to be bound only
+ in isearch mode.
+
+ The point of this function is that oftentimes you want to delete
+ some portion of text, one end of which happens to be an active
+ isearch word. The observation to make is that if you use isearch
+ a lot to move the cursor around (as you should, it is much more
+ efficient than using the arrows), it happens a lot that you could
+ just delete the active region between the mark and the point, not
+ include the isearch word."
+ (interactive "r")
+ (when (not mark-active)
+ (error "Mark is not active"))
+ (let* ((isearch-bounds (list isearch-other-end (point)))
+ (ismin (apply 'min isearch-bounds))
+ (ismax (apply 'max isearch-bounds))
+ )
+ (if (< (mark) ismin)
+ (kill-region (mark) ismin)
+ (if (> (mark) ismax)
+ (kill-region ismax (mark))
+ (error "Internal error in isearch kill function.")))
+ (isearch-exit)
+ ))
+(bind-key "M-z" 'zap-to-isearch isearch-mode-map)
+
+;; Exit isearch at the beginning
+(defun isearch-exit-other-end (rbeg rend)
+ "Exit isearch, but at the other end of the search string.
+ This is useful when followed by an immediate kill."
+ (interactive "r")
+ (isearch-exit)
+ (goto-char isearch-other-end))
+(bind-key "<C-return>" 'isearch-exit-other-end isearch-mode-map)
+
+;; Search the web
+(use-package webjump
+ :bind ("C-x g" . webjump)
+ :config
+ (progn
+ ;; Suggest word at point if possible
+ (defun webjump-read-string (prompt)
+ (let* ((prompt (concat prompt (if (word-at-point) (concat " (default: " (word-at-point) ")")) ": "))
+ (input (read-string prompt)))
+ (if (webjump-null-or-blank-string-p input) (word-at-point) input)))
+
+ ;; C++ reference
+ (add-to-list 'webjump-sites
+ '("cpp" . [simple-query "en.cppreference.com"
+ "http://en.cppreference.com/mwiki/index.php?title=Special:Search&search="
+ ""]))
+ )
+ )
+
+;; to do: add zeal-at-point
+
+(provide 'ravi-init-navigation)
+;;; ravi-init-navigation.el ends here