From: James Bunton Date: Wed, 27 Jul 2016 15:11:05 +0000 (+1000) Subject: more text utility functions with key bindings X-Git-Url: https://code.delx.au/dotemacs/commitdiff_plain/62793a8c6ae0a061f2d34324a0defabd8b075c25 more text utility functions with key bindings * Copy line (yy in vim) * Duplicate line (yy, p in vim) * Kill whole line (dd in vim) * Substitute line (S in vim) * comment-dwim improved handling of regions * Moved frame titles to my-gui.el * Made all text utilities take arguments --- diff --git a/README.md b/README.md index a44cf99..c591ab6 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ M-m Jump back to start of indentatio M-r Jump to window top/bottom/middle M-g Tab Jump to column M-g M-j Jump to charactor +M-g M-l Jump to charactor on current line M-g M-w Jump to word by first character M-g M-g Jump to visible line or any line C-a Beginning of line @@ -118,6 +119,9 @@ C-j Newline and maybe indent M-^ Join to previous line M-j New line with comment C-q Quoted insert +C-M-\ Indent region +C-c c Copy line +C-c d Duplicate line M-x comment-box Wrap region in comment box ``` @@ -145,8 +149,8 @@ M-_ Select current line M-z Kill until C-k Kill to end of line M-0 C-k Kill to beginning of line -C-a C-k C-k Kill current line -C-S-Backspace Kill current line +C-c k Kill whole line +C-c s Copy line C-d Delete next character M-d Delete next word M-Backspace Delete previous word diff --git a/lisp/my-defuns.el b/lisp/my-defuns.el index 176da08..2232e79 100644 --- a/lisp/my-defuns.el +++ b/lisp/my-defuns.el @@ -1,83 +1,55 @@ ;;; -*- lexical-binding: t -*- -(require 'cl-lib) +(defun my/comment-dwim (arg) + "Toggles the comment on for the active region if present or the current line otherwise." + (interactive "*p") + (cond + ((and mark-active transient-mark-mode) + (let ((start (save-excursion (goto-char (region-beginning)) (line-beginning-position))) + (end (save-excursion (goto-char (region-end)) (line-end-position)))) + (comment-or-uncomment-region start end))) + (t + (comment-or-uncomment-region (line-beginning-position) (line-end-position arg)) + (forward-line arg)))) (defun my/copy-line (arg) - "Copy lines in the kill ring" - (interactive "p") - (kill-ring-save (line-beginning-position) + "Copy the current line into the kill ring. With ARG copies that many lines." + (interactive "*p") + (kill-ring-save (line-beginning-position 1) (line-beginning-position (+ 1 arg))) - (message "%d line%s copied" arg (if (= 1 arg) "" "s"))) - -(defun my/generate-frame-title () - (if (buffer-file-name) - (concat - (file-name-nondirectory (buffer-file-name)) - (if (buffer-modified-p) - " +") - " (" - (abbreviate-file-name (substring (file-name-directory (buffer-file-name)) 0 -1)) - ") - Emacs" - ) - (concat - (buffer-name) - (if (buffer-modified-p) - " +") - " - Emacs"))) + (message "Copied %d lines" arg)) -(defun my/frame-initial-frame-p (frame) - "Returns true if the given frame is the magic 'initial frame' that always exists in GUI emacs sessions" - (equal "initial_terminal" (terminal-name frame))) - -(defun my/frame-list-ignoring-initial-frame () - (filtered-frame-list (lambda (frame) (not (my/frame-initial-frame-p frame))))) +(defun my/duplicate-line (arg) + "Duplicate current line, leaving point in lower line. With ARG duplicates the line that many lines." + (interactive "*p") + (kill-ring-save (line-beginning-position 1) + (line-beginning-position 2)) + (forward-line) + (dotimes (ignored arg) + (yank)) + (forward-line (- arg)) + (back-to-indentation)) (defun my/git-reset-buffer () + "Runs git-reset to unstage all changes on the current file. Then updates the git-gutter." (interactive) (call-process "git" nil nil nil "reset" (buffer-file-name)) - (git-gutter)) - -(defun my/kill-buffer-safely (buffer) - "Kill the buffer if it is not special or modified" - (if (and - (not (string-match "^ " (buffer-name buffer))) - (not (equal "*Messages*" (buffer-name buffer))) - (or - (not (buffer-modified-p buffer)) - (null (buffer-file-name buffer)))) - (kill-buffer buffer))) - -(defun my/kill-buffers-if-deleting-last-frame (frame) - "Kill all buffers when closing the last frame" - (when (equal (list frame) (my/frame-list-ignoring-initial-frame)) - (dolist (buffer (buffer-list)) - (my/kill-buffer-safely buffer)))) - -(defun my/kill-buffers-not-in-frame () - "Kill buffers which are not loaded into some frame" - (interactive) - (let ((kill-count 0)) - (dolist (buffer (buffer-list)) - (let* ((window (get-buffer-window buffer t)) - (frame (window-frame window))) - (if (or (null frame) (not (window-live-p window)) (my/frame-initial-frame-p frame)) - (if (my/kill-buffer-safely buffer) - (cl-incf kill-count))))) - (message "Killed %d buffers" kill-count))) + (git-gutter) + (message "Finished git reset")) -(defun my/open-line-above () - "Open a new line above point with indentation" - (interactive) +(defun my/open-line-above (arg) + "Open a new line above point with indentation. With ARG insert that many lines." + (interactive "*p") (beginning-of-line) - (newline) - (forward-line -1) + (newline arg) + (forward-line (- arg)) (indent-for-tab-command)) -(defun my/open-line-below () - "Open a new line below point with indentation" - (interactive) +(defun my/open-line-below (arg) + "Open a new line below point with indentation. With ARG insert that many lines." + (interactive "*p") (end-of-line) - (newline) + (newline arg) (indent-for-tab-command)) (defun my/scratch-buffer () @@ -92,18 +64,11 @@ (setq n (1+ n)) (get-buffer bufname))) (switch-to-buffer (get-buffer-create bufname)) - (emacs-lisp-mode) - )) + (emacs-lisp-mode))) -(defun my/toggle-comment-on-line () - "Toggles the comment on for the active region if present or the current line otherwise." - (interactive) - (if (and mark-active transient-mark-mode) - (comment-or-uncomment-region (region-beginning) (region-end)) - (comment-or-uncomment-region (line-beginning-position) (line-end-position))) - (forward-line)) - -(defun my/terminal-update-title () - "If using a terminal frame then sends the escape codes to update the title." - (if (terminal-parameter (frame-terminal) 'terminal-initted) - (send-string-to-terminal (concat "\033]0;" (my/generate-frame-title) "\007")))) +(defun my/substitute-line (arg) + "Kill the current line and leave point at correct indentation level. With ARG kill that many lines first." + (interactive "*p") + (beginning-of-line) + (kill-line arg) + (indent-for-tab-command)) diff --git a/lisp/my-gui.el b/lisp/my-gui.el index 7376d1b..3ee0900 100644 --- a/lisp/my-gui.el +++ b/lisp/my-gui.el @@ -30,3 +30,62 @@ (add-to-list 'post-command-hook #'my/terminal-update-title) (defalias 'yes-or-no-p 'y-or-n-p) + + +(defun my/frame-initial-frame-p (frame) + "Returns true if the given frame is the magic 'initial frame' that always exists in GUI emacs sessions" + (equal "initial_terminal" (terminal-name frame))) + +(defun my/frame-list-ignoring-initial-frame () + "Returns all frames except the magic 'initial frame' that always exists in GUI emacs sessions" + (filtered-frame-list (lambda (frame) (not (my/frame-initial-frame-p frame))))) + +(defun my/generate-frame-title () + "Returns a string like 'filename (dirname) - Emacs'" + (if (buffer-file-name) + (concat + (file-name-nondirectory (buffer-file-name)) + (if (buffer-modified-p) + " +") + " (" + (abbreviate-file-name (substring (file-name-directory (buffer-file-name)) 0 -1)) + ") - Emacs" + ) + (concat + (buffer-name) + (if (buffer-modified-p) + " +") + " - Emacs"))) + +(defun my/kill-buffer-safely (buffer) + "Kill the buffer if it is not special or modified" + (if (and + (not (string-match "^ " (buffer-name buffer))) + (not (equal "*Messages*" (buffer-name buffer))) + (or + (not (buffer-modified-p buffer)) + (null (buffer-file-name buffer)))) + (kill-buffer buffer))) + +(defun my/kill-buffers-if-deleting-last-frame (frame) + "Kill all buffers when closing the last frame" + (when (equal (list frame) (my/frame-list-ignoring-initial-frame)) + (dolist (buffer (buffer-list)) + (my/kill-buffer-safely buffer)))) + +(defun my/kill-buffers-not-in-frame () + "Kill buffers which are not loaded into some frame" + (interactive) + (let ((kill-count 0)) + (dolist (buffer (buffer-list)) + (let* ((window (get-buffer-window buffer t)) + (frame (window-frame window))) + (if (or (null frame) (not (window-live-p window)) (my/frame-initial-frame-p frame)) + (if (my/kill-buffer-safely buffer) + (cl-incf kill-count))))) + (message "Killed %d buffers" kill-count))) + +(defun my/terminal-update-title () + "If using a terminal frame then sends the escape codes to update the title." + (if (terminal-parameter (frame-terminal) 'terminal-initted) + (send-string-to-terminal (concat "\033]0;" (my/generate-frame-title) "\007")))) diff --git a/lisp/my-keys.el b/lisp/my-keys.el index fb33ded..5fbef90 100644 --- a/lisp/my-keys.el +++ b/lisp/my-keys.el @@ -32,15 +32,18 @@ ;; Movement (global-set-key (kbd "M-g M-j") 'avy-goto-char-timer) +(global-set-key (kbd "M-g M-l") 'avy-goto-char-in-line) (global-set-key (kbd "M-g M-w") 'avy-goto-word-1) (global-set-key (kbd "M-g M-g") 'avy-goto-line) ;; Text formatting (global-set-key (kbd "M-/") 'hippie-expand) -(global-set-key (kbd "M-;") 'my/toggle-comment-on-line) +(global-set-key (kbd "M-;") 'my/comment-dwim) (global-set-key (kbd "M-i") 'change-inner) (global-set-key (kbd "C-o") 'my/open-line-above) (global-set-key (kbd "M-o") 'my/open-line-below) +(global-set-key (kbd "C-c c") 'my/copy-line) +(global-set-key (kbd "C-c d") 'my/duplicate-line) ;; Marking (global-set-key (kbd "C-=") 'er/expand-region) @@ -49,8 +52,9 @@ ;; Killing and deleting (global-set-key (kbd "M-y") 'counsel-yank-pop) -(global-set-key (kbd "M-_") 'my/copy-line) (global-set-key (kbd "M-z") 'zap-up-to-char) +(global-set-key (kbd "C-c k") 'kill-whole-line) +(global-set-key (kbd "C-c s") 'my/substitute-line) ;; Mode switching (global-set-key (kbd "C-x C-j") 'direx-project:jump-to-project-root-other-window)