]> code.delx.au - gnu-emacs-elpa/blobdiff - easy-kill.el
For #14: Treat strings like lists
[gnu-emacs-elpa] / easy-kill.el
index 002c094ab815f671717803d7dfd118bdd5c87c22..0407a466c996a407ba38814339bdfe691fdb5711 100644 (file)
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2013-2014  Free Software Foundation, Inc.
 
 ;; Author: Leo Liu <sdl.web@gmail.com>
-;; Version: 0.9.2
+;; Version: 0.9.3
 ;; Package-Requires: ((emacs "24") (cl-lib "0.5"))
 ;; Keywords: killing, convenience
 ;; Created: 2013-08-12
         (add-hook 'pre-command-hook clearfunsym)
         (push alist emulation-mode-map-alists))))))
 
-(defcustom easy-kill-alist
-  '((?w word     " ")
-    (?s sexp     "\n")
-    (?l list     "\n")
-    (?f filename "\n")
-    (?d defun    "\n\n")
-    (?e line     "\n")
-    (?b buffer-file-name))
+(defcustom easy-kill-alist '((?w word     " ")
+                             (?s sexp     "\n")
+                             (?l list     "\n")
+                             (?f filename "\n")
+                             (?d defun    "\n\n")
+                             (?e line     "\n")
+                             (?b buffer-file-name))
   "A list of (CHAR THING APPEND).
 CHAR is used immediately following `easy-kill' to select THING.
 APPEND is optional and if non-nil specifies the separator (a
@@ -113,6 +112,8 @@ deprecated."
     (define-key map "+" 'easy-kill-expand)
     (define-key map "=" 'easy-kill-expand)
     (define-key map "@" 'easy-kill-append)
+    ;; Note: didn't pick C-h because it is a very useful prefix key.
+    (define-key map "?" 'easy-kill-help)
     (define-key map [remap set-mark-command] 'easy-kill-mark-region)
     (define-key map [remap kill-region] 'easy-kill-region)
     (define-key map [remap keyboard-quit] 'easy-kill-abort)
@@ -121,16 +122,6 @@ deprecated."
           (number-sequence 0 9))
     map))
 
-(defun easy-kill-map ()
-  "Build the keymap according to `easy-kill-alist'."
-  (let ((map (make-sparse-keymap)))
-    (set-keymap-parent map easy-kill-base-map)
-    (mapc (lambda (c)
-            ;; (define-key map (vector meta-prefix-char c) 'easy-kill-select)
-            (define-key map (char-to-string c) 'easy-kill-thing))
-          (mapcar 'car easy-kill-alist))
-    map))
-
 (defvar easy-kill-inhibit-message nil)
 
 (defun easy-kill-echo (format-string &rest args)
@@ -168,6 +159,51 @@ The value is the function's symbol if non-nil."
        (not (equal text ""))
        (funcall interprogram-cut-function text)))
 
+(defun easy-kill-map ()
+  "Build the keymap according to `easy-kill-alist'."
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map easy-kill-base-map)
+    (mapc (lambda (c)
+            ;; (define-key map (vector meta-prefix-char c) 'easy-kill-select)
+            (define-key map (char-to-string c) 'easy-kill-thing))
+          (mapcar 'car easy-kill-alist))
+    map))
+
+(defun easy-kill--fmt (x y &optional z)
+  (cl-etypecase x
+    (character (easy-kill--fmt
+                (single-key-description x)
+                (symbol-name y)
+                (and z (let ((print-escape-newlines t))
+                         (prin1-to-string z)))))
+    (string (with-output-to-string
+              (princ x)
+              (princ (make-string (- 16 (mod (length x) 16)) ?\s))
+              (princ y)
+              (when z
+                (princ (make-string (- 16 (mod (length y) 16)) ?\s))
+                (princ z))))))
+
+(defun easy-kill-help ()
+  (interactive)
+  (help-setup-xref '(easy-kill-help) (called-interactively-p 'any))
+  (with-help-window (help-buffer)
+    (princ (concat (make-string 15 ?=) " "))
+    (princ "Easy Kill/Mark Key Bindings ")
+    (princ (concat (make-string 15 ?=) "\n\n"))
+    (princ (easy-kill--fmt "Key" "Thing" "Separator"))
+    (princ "\n")
+    (princ (easy-kill--fmt "---" "-----" "---------"))
+    (princ "\n\n")
+    (princ (mapconcat (lambda (x) (pcase x
+                                    (`(,c ,thing ,sep)
+                                     (easy-kill--fmt c thing sep))
+                                    ((or `(,c ,thing) `(,c . ,thing))
+                                     (easy-kill--fmt c thing))))
+                      easy-kill-alist "\n"))
+    (princ "\n\n")
+    (princ (substitute-command-keys "\\{easy-kill-base-map}"))))
+
 (defvar easy-kill-candidate nil)
 (defvar easy-kill-append nil)
 (defvar easy-kill-mark nil)
@@ -257,9 +293,10 @@ Otherwise, it is the value of the overlay's candidate property."
                          ;; Allow describe-PROP to provide customised
                          ;; description.
                          for dk = (intern-soft (format "describe-%s" k))
-                         for v = (or (plist-get all dk) (plist-get all k))
-                         when v collect (format "%s:\t%s" k
-                                                (if (functionp v) (funcall v) v))))
+                         for dv = (and dk (plist-get all dk))
+                         for v = (or (if (functionp dv) (funcall dv) dv)
+                                     (plist-get all k))
+                         when v collect (format "%s:\t%s" k v)))
          (txt (mapconcat #'identity props "\n")))
     (format "cmd:\t%s\n%s" (if easy-kill-mark "easy-mark" "easy-kill") txt)))
 
@@ -348,8 +385,15 @@ candidate property instead."
            (new-front (save-excursion
                         (goto-char front)
                         (with-demoted-errors
-                          (cl-dotimes (_ (abs n))
-                            (forward-thing thing step)))
+                          (cl-labels ((forward-defun (s)
+                                                     (pcase s
+                                                       (`-1 (beginning-of-defun 1))
+                                                       (`+1 (end-of-defun 1)))))
+                            (dotimes (_ (abs n))
+                              ;; Work around http://debbugs.gnu.org/17247
+                              (if (eq thing 'defun)
+                                  (forward-defun step)
+                                (forward-thing thing step)))))
                         (point))))
       (pcase (and (/= front new-front)
                   (sort (cons new-front bounds1) #'<))
@@ -475,6 +519,7 @@ Temporally activate additional key bindings as follows:
   0..9    => expand selection by that number;
   +,=/-   => expand or shrink selection;
   @       => append selection to previous kill;
+  ?       => help;
   C-w     => kill selection;
   C-SPC   => turn selection into an active region;
   C-g     => abort;
@@ -600,7 +645,20 @@ inspected."
      (pcase (easy-kill-bounds-of-list n)
        (`(,beg . ,end)
         (easy-kill-adjust-candidate 'list beg end))))
-    (_ (easy-kill-thing 'list n t))))
+    (_ (pcase (easy-kill-get thing)
+         (`list (easy-kill-thing 'list n t))
+         (_ (let ((bounds (bounds-of-thing-at-point 'list)))
+              (cond ((and bounds (or (/= (car bounds) (point))
+                                     (not (nth 3 (syntax-ppss)))))
+                     (setf (easy-kill-get thing) 'list
+                           (easy-kill-get bounds) bounds))
+                    ((nth 3 (syntax-ppss))
+                     (save-excursion
+                       (easy-kill-backward-up)
+                       (setf (easy-kill-get thing) 'list)
+                       (setf (easy-kill-get bounds)
+                             (bounds-of-thing-at-point 'sexp))))
+                    (t (easy-kill-echo "No `list' at point")))))))))
 
 (defun easy-kill-on-sexp (n)
   (pcase n