Kungsgeten / yankpad

Paste snippets from an org-mode file

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mimicking Org easy templates results in unnecessary "<" and indenting

novoid opened this issue · comments

Hi Erik,

(After using yankpad for a looong time, I re-visited your README and found tons of interesting things that got added: therefore a very big THANKS to you.)

When testing yankpad for replacing Org mode easy templates (that got changed with Org 9.2) or yasnippet (which does have some minor issues on my side), I noticed that yankpad is not able to replace easy templates exactly like they used to work in Org <9.2.

I defined this template in my yankpad.org file:

** <x: block emacs-lisp

#+BEGIN_SRC emacs-lisp
$0
#+END_SRC

When I enter <x and invoke M-x yankpad-expand, this results in:

<
 #+BEGIN_SRC emacs-lisp

 #+END_SRC

I would have expected:

#+BEGIN_SRC emacs-lisp

#+END_SRC

Therefore, the < does not get replaced and there is an additional space in-front of the last three lines. I've got the impression that this might be a bug which can be fixed.

If this issue is caused by me not knowing how to use your delightful package, please do help me fixing me.

Thanks!

You're welcome! I'm glad that you like the package and I appreciate that you mention it on your blog, in Reddit posts, etc.

yankpad-expand uses symbol-at-point to find the "expand word". It seems like org-mode doesn't recognize < as part of the symbol. Maybe there's a better way to find out what is at point.

Good things need to be mentioned ;-)

If this is hard to fix, don't worry. I was not sure if it is a minor change or not. I'm happy without any fix as well but I thought that this very same use-case might apply for more people and not just me. Close it this issue you like.

Hi!

I really like Yankpad a lot but I had had this same annoyance, so with a little time on my hands I tried to fix it. Keep in mind that I have very little experience with elisp and I haven't tested it very much, so feel free to criticize anything below :)

Using the emacs-wiki about thing-at-point I replaced the symbol-at-point function with (thing-at-point 'exp) which matches any sequence of graphical characters.

(defun bounds-of-exp-at-point ()
    "Return the start and end points of a symbol at point.
The symbol is any expression of graphical symbols (ie. not whitespace)."
  (save-excursion
    (skip-chars-backward "[:graph:]")
    (if (looking-at "[[:graph:]]+")
      (cons (point) (match-end 0))
      nil)))

(put 'exp 'bounds-of-thing-at-point
     'bounds-of-exp-at-point)

The only changes necessary were to replace this function in yankpad-expand. However, to my surprise, while this expanded, and correctly replaced <s to an org-source-block, s (without the <) did as well. This I fixed by changing regex matcher for the expand keyword. I marked the changes I made below.

(defun yankpad-expand (&optional _first)
  "Replace symbol at point with a snippet.
Only works if the symbol is found in the first matching group of
`yankpad-expand-keyword-regex'.

This function can be added to `hippie-expand-try-functions-list'."
  (interactive)
  (when (and (called-interactively-p 'any)
             (not yankpad-category))
    (yankpad-set-category))
  (let* ((symbol (thing-at-point 'exp)) ;; Replaced to include symbols like < and :
         (bounds (bounds-of-thing-at-point 'exp)) ;; Replaced Idem
         (snippet-prefix (concat symbol yankpad-expand-separator))
         (case-fold-search nil))
    (when (and symbol yankpad-category)
      (catch 'loop
        (mapc
         (lambda (snippet)
           ;; See if there's an expand regex
           (if-let ((regex (cdr (assoc "YP_EXPAND_REGEX" (nth 4 snippet)))))
               (when (string-match (concat "\\b" regex "\\b") symbol)
                 (let ((match (cddr (match-data)))
                       (snippet (copy-sequence snippet))
                       strings)
                   (while match
                     (push (substring symbol (pop match) (pop match)) strings))
                   (setf (nth 3 snippet)
                         (apply #'format (nth 3 snippet) (reverse strings)))
                   (delete-region (car bounds) (cdr bounds))
                   (yankpad--run-snippet snippet)
                   (throw 'loop snippet)))
             ;; Otherwise look for expand keyword
             (when (string-match-p (concat "\\(^\\|" yankpad-expand-separator "\\)" snippet-prefix) ;; Replaced so "s" does not match "<s"
                                   (car (split-string (car snippet) " ")))
               (delete-region (car bounds) (cdr bounds))
               (yankpad--run-snippet snippet)
               (throw 'loop snippet))))
         (yankpad-active-snippets))
        nil))))

If you think this would work well, I'd be happy to make a pull-request as soon as I figure out how that works!

@bramboomen Hi! I'm glad you like Yankpad. I haven't tried your suggestion, but if it works then I'd like to include it for sure. Is this exp thing something you've defined yourself? I can't see it in the documentation of bounds-of-thing-at-point.

Yes, exp was defined by me but this could be named anything, maybe graph for "graphical symbol" would be better. 'exp just provides a replacement for 'symbol, so (symbol-at-point) (which is shorthand for (thing-at-point 'symbol) becomes (thing-at-point 'exp). I followed the approach of this example, which defines the bounds for (thing-at-point 'integer).