Smart parens behavior inside word
Hi @Fuco1,
I'm using smartparens and I would like to set a even more smart behavior. I've tried to set a behavior that is put enclosing pair in a word when the point is inside it. I read the smartparens wiki and searches in the internet and I almost got it. Below is the code (that I spent hours modifying and reevaluating).
When hit the quote mark, for example, o would like this Do What I Mean:
- If point is before or inside a word, surround the word with the pair.
- If point is after, close the pair (or complete if the opening is missing, why not?).
- If the point is surround by white space (newlines, spaces, line beginning, don't touching a word), insert the pair (as usual);
- If region is active, surround the region with the pair (as usual);
In my tries, I got something partial. I got put pair when before a word, but I lost insert pair when region is active. I also got put pair when inside a word, but the opening stayed at the point, not at word beginning.
Below is the code I'm using. In the comments, the pipe (|) indicates the point when I hit double quotes. The greater/less signs indicates direction of region mark.
This settings, if possible, could be part of the tips and thicks section. Thanks in advance for any help.
;;-------------------------------------------
;; Smart Parenthesis
;; https://github.com/Fuco1/smartparens.
(require 'smartparens)
(smartparens-global-mode 1)
;; To mark the current word.
(defun mark-whole-word (id action context)
(interactive)
(when (eq action 'insert)
(skip-chars-backward "[[:alnum:]]._")
(set-mark (point))
(skip-chars-forward "[[:alnum:]]._")
))
;; Return t if the point is inside or touching a word.
(defun string-at-point-p (id action context)
"Test if the point is in a word."
(if (stringp (thing-at-point 'word)) t nil))
;;-------------------------------------------
;; Do Waht I Mean, example with quotes.
;; this is a |short word => this is a "short" word
;; this is a sh|ort word => this is a "short" word
;; >this is a short word> => "this is a short word"
;; <this is a short word< => "this is a short word"
;; this is a "short| word => this is a "short" word
;; this is a short| word => this is a "short" word (why not?)
;;-------------------------------------------
(sp-with-modes
'(markdown-mode gfm-mode rst-mode)
;; Don't put a pair when after a word.
(sp-local-pair "\"" nil
:unless '(sp-point-after-word-p))
(sp-local-pair "\"" nil
;; :when '(sp-point-before-word-p)
:when '(string-at-point-p)
:pre-handlers '(mark-whole-word)
:actions '(insert))
)
;; Using this, I got:
;; this is a |short word => this is a "short" word
;; this is a sh|ort word => this is a sh"ort word
;; >this is a short word> => "
;; <this is a short word< => "
;;-------------------------------------------
(sp-with-modes
'(markdown-mode gfm-mode rst-mode)
(sp-local-pair "\"" nil
:when '(string-at-point-p)
:pre-handlers '(mark-whole-word)
:actions '(insert)))
;; Using this, I got all the same, except:
;; this is a sh|ort word => this is a sh"ort" word
These are pretty cool ideas, I like it!
We will probably need to implement it on lower level than the hooks, although I'm not exactly sure.