From 8c7318f30936b8700ba06fdd09dded174644970b Mon Sep 17 00:00:00 2001 From: Kyle Meyer Date: Sat, 14 Feb 2015 18:15:54 -0500 Subject: Don't use words as unit for slurping and barfing Using words as the unit for slurping can give confusing results. For example, slurping forward with The [http://orgmode.org] Org-mode site results in The [[http://orgmode.org][Org]]-mode site This is somewhat inconvenient because the intended slurp here is most likely 'Org-mode'. However, given that the command clearly says that it works at the level of words, this shouldn't be too surprising. The problem is that, unless the user is displaying the full link (e.g., using org-toggle-link-display), the entire text 'Org-mode' is highlighted as though it's part of the link. If the user then tried to slurp again to get 'site', '-mode' would actually be slurped, and it would appear like nothing happened. Instead of words, make blocks of non-whitespace characters, referred to as blobs, the unit for slurping and barfing. When slurping forward, don't consider trailing punctuation as part of a blob. --- org-link-edit.el | 131 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 48 deletions(-) (limited to 'org-link-edit.el') diff --git a/org-link-edit.el b/org-link-edit.el index f99dac3..a303adf 100644 --- a/org-link-edit.el +++ b/org-link-edit.el @@ -29,10 +29,10 @@ ;; There are four commands, all which operate when point is on an Org ;; link. ;; -;; - org-link-edit-forward-slurp-word -;; - org-link-edit-backward-slurp-word -;; - org-link-edit-forward-barf-word -;; - org-link-edit-backward-barf-word +;; - org-link-edit-forward-slurp +;; - org-link-edit-backward-slurp +;; - org-link-edit-forward-barf +;; - org-link-edit-backward-barf ;; ;; Org Link Edit doesn't bind these commands to any keys. Finding ;; good keys for these commands is difficult because, while it's @@ -47,10 +47,10 @@ ;; (define-key org-mode-map YOUR-KEY ;; (defhydra hydra-org-link-edit () ;; "Org Link Edit" -;; ("j" org-link-edit-forward-slurp-word "forward slurp") -;; ("k" org-link-edit-forward-barf-word "forward barf") -;; ("u" org-link-edit-backward-slurp-word "backward slurp") -;; ("i" org-link-edit-backward-barf-word "backward barf") +;; ("j" org-link-edit-forward-slurp "forward slurp") +;; ("k" org-link-edit-forward-barf "forward barf") +;; ("u" org-link-edit-backward-slurp "backward slurp") +;; ("i" org-link-edit-backward-barf "backward barf") ;; ("q" nil "cancel"))) ;; ;; [1] https://github.com/abo-abo/hydra @@ -96,9 +96,35 @@ The list includes (t (error "What am I looking at?")))))) +(defun org-link-edit--forward-blob (n &optional no-punctuation) + "Move forward N blobs (backward if N is negative). + +A block of non-whitespace characters is a blob. If +NO-PUNCTUATION is non-nil, trailing punctuation characters are +not considered part of the blob when going in the forward +direction. + +If the edge of the buffer is reached before completing the +movement, return nil. Otherwise, return t." + (let* ((forward-p (> n 0)) + (nblobs (abs n)) + (skip-func (if forward-p 'skip-syntax-forward 'skip-syntax-backward)) + skip-func-retval) + (while (/= nblobs 0) + (funcall skip-func " ") + (setq skip-func-retval (funcall skip-func "^ ")) + (setq nblobs (1- nblobs))) + (when (and forward-p no-punctuation) + (let ((punc-tail-offset (save-excursion (skip-syntax-backward ".")))) + ;; Don't consider trailing punctuation as part of the blob + ;; unless the whole blob consists of punctuation. + (unless (= skip-func-retval (- punc-tail-offset)) + (goto-char (+ (point) punc-tail-offset))))) + (/= skip-func-retval 0))) + ;;;###autoload -(defun org-link-edit-forward-slurp-word (&optional n) - "Slurp N trailing words into link's description. +(defun org-link-edit-forward-slurp (&optional n) + "Slurp N trailing blobs into link's description. The \[\[http://orgmode.org/\]\[Org mode\]\] site @@ -107,22 +133,26 @@ The list includes The \[\[http://orgmode.org/\]\[Org mode site\]\] +A blob is a block of non-whitespace characters. When slurping +forward, trailing punctuation characters are not considered part +of a blob. + After slurping, return the slurped text and move point to the beginning of the link. -If N is negative, slurp leading words instead of trailing words." +If N is negative, slurp leading blobs instead of trailing blobs." (interactive "p") (setq n (or n 1)) (cond ((= n 0)) ((< n 0) - (org-link-edit-backward-slurp-word (- n))) + (org-link-edit-backward-slurp (- n))) (t (cl-multiple-value-bind (beg end link desc) (org-link-edit--get-link-data) (goto-char (save-excursion (goto-char end) - (or (forward-word n) - (user-error "Not enough words after the link")) + (or (org-link-edit--forward-blob n 'no-punctuation) + (user-error "Not enough blobs after the link")) (point))) (let ((slurped (buffer-substring-no-properties end (point)))) (setq slurped (replace-regexp-in-string "\n" " " slurped)) @@ -137,8 +167,8 @@ If N is negative, slurp leading words instead of trailing words." slurped))))) ;;;###autoload -(defun org-link-edit-backward-slurp-word (&optional n) - "Slurp N leading words into link's description. +(defun org-link-edit-backward-slurp (&optional n) + "Slurp N leading blobs into link's description. The \[\[http://orgmode.org/\]\[Org mode\]\] site @@ -147,23 +177,24 @@ If N is negative, slurp leading words instead of trailing words." \[\[http://orgmode.org/\]\[The Org mode\]\] site +A blob is a block of non-whitespace characters. + After slurping, return the slurped text and move point to the beginning of the link. -If N is negative, slurp trailing words instead of leading -words." +If N is negative, slurp trailing blobs instead of leading blobs." (interactive "p") (setq n (or n 1)) (cond ((= n 0)) ((< n 0) - (org-link-edit-forward-slurp-word (- n))) + (org-link-edit-forward-slurp (- n))) (t (cl-multiple-value-bind (beg end link desc) (org-link-edit--get-link-data) (goto-char (save-excursion (goto-char beg) - (or (forward-word (- n)) - (user-error "Not enough words before the link")) + (or (org-link-edit--forward-blob (- n)) + (user-error "Not enough blobs before the link")) (point))) (let ((slurped (buffer-substring-no-properties (point) beg))) (when (and (= (length desc) 0) @@ -177,43 +208,43 @@ words." (goto-char beg) slurped))))) -(defun org-link-edit--split-first-words (string n) - "Split STRING into (N first words . other) cons cell. -'N first words' contains all text from the start of STRING up to -the start of the N+1 word. 'other' includes the remaining text -of STRING. If the number of words in STRING is fewer than N, +(defun org-link-edit--split-first-blobs (string n) + "Split STRING into (N first blobs . other) cons cell. +'N first blobs' contains all text from the start of STRING up to +the start of the N+1 blob. 'other' includes the remaining text +of STRING. If the number of blobs in STRING is fewer than N, 'other' is nil." (when (< n 0) (user-error "N cannot be negative")) (with-temp-buffer (insert string) (goto-char (point-min)) (with-syntax-table org-mode-syntax-table - (let ((within-bound (forward-word n))) - (skip-syntax-forward "^w") + (let ((within-bound (org-link-edit--forward-blob n))) + (skip-syntax-forward " ") (cons (buffer-substring 1 (point)) (and within-bound (buffer-substring (point) (point-max)))))))) -(defun org-link-edit--split-last-words (string n) - "Split STRING into (other . N last words) cons cell. -'N last words' contains all text from the end of STRING back to -the end of the N+1 last word. 'other' includes the remaining text -of STRING. If the number of words in STRING is fewer than N, -'other' is nil." +(defun org-link-edit--split-last-blobs (string n) + "Split STRING into (other . N last blobs) cons cell. +'N last blobs' contains all text from the end of STRING back to +the end of the N+1 last blob. 'other' includes the remaining +text of STRING. If the number of blobs in STRING is fewer than +N, 'other' is nil." (when (< n 0) (user-error "N cannot be negative")) (with-temp-buffer (insert string) (goto-char (point-max)) (with-syntax-table org-mode-syntax-table - (let ((within-bound (forward-word (- n)))) - (skip-syntax-backward "^w") + (let ((within-bound (org-link-edit--forward-blob (- n)))) + (skip-syntax-backward " ") (cons (and within-bound (buffer-substring 1 (point))) (buffer-substring (point) (point-max))))))) ;;;###autoload -(defun org-link-edit-forward-barf-word (&optional n) - "Barf N trailing words from link's description. +(defun org-link-edit-forward-barf (&optional n) + "Barf N trailing blobs from link's description. The \[\[http://orgmode.org/\]\[Org mode\]\] site @@ -222,23 +253,25 @@ of STRING. If the number of words in STRING is fewer than N, The \[\[http://orgmode.org/\]\[Org\]\] mode site +A blob is a block of non-whitespace characters. + After barfing, return the barfed text and move point to the beginning of the link. -If N is negative, barf leading words instead of trailing words." +If N is negative, barf leading blobs instead of trailing blobs." (interactive "p") (setq n (or n 1)) (cond ((= n 0)) ((< n 0) - (org-link-edit-backward-barf-word (- n))) + (org-link-edit-backward-barf (- n))) (t (cl-multiple-value-bind (beg end link desc) (org-link-edit--get-link-data) (when (= (length desc) 0) (user-error "Link has no description")) - (pcase-let ((`(,new-desc . ,barfed) (org-link-edit--split-last-words + (pcase-let ((`(,new-desc . ,barfed) (org-link-edit--split-last-blobs desc n))) - (unless new-desc (user-error "Not enough words in description")) + (unless new-desc (user-error "Not enough blobs in description")) (delete-region beg end) (insert (org-make-link-string link new-desc)) (if (string= new-desc "") @@ -252,8 +285,8 @@ If N is negative, barf leading words instead of trailing words." barfed))))) ;;;###autoload -(defun org-link-edit-backward-barf-word (&optional n) - "Barf N leading words from link's description. +(defun org-link-edit-backward-barf (&optional n) + "Barf N leading blobs from link's description. The \[\[http://orgmode.org/\]\[Org mode\]\] site @@ -262,23 +295,25 @@ If N is negative, barf leading words instead of trailing words." The Org \[\[http://orgmode.org/\]\[mode\]\] site +A blob is a block of non-whitespace characters. + After barfing, return the barfed text and move point to the beginning of the link. -If N is negative, barf trailing words instead of leading words." +If N is negative, barf trailing blobs instead of leading blobs." (interactive "p") (setq n (or n 1)) (cond ((= n 0)) ((< n 0) - (org-link-edit-forward-barf-word (- n))) + (org-link-edit-forward-barf (- n))) (t (cl-multiple-value-bind (beg end link desc) (org-link-edit--get-link-data) (when (= (length desc) 0) (user-error "Link has no description")) - (pcase-let ((`(,barfed . ,new-desc) (org-link-edit--split-first-words + (pcase-let ((`(,barfed . ,new-desc) (org-link-edit--split-first-blobs desc n))) - (unless new-desc (user-error "Not enough words in description")) + (unless new-desc (user-error "Not enough blobs in description")) (delete-region beg end) (insert (org-make-link-string link new-desc)) (when (string= new-desc "") -- cgit v1.2.3