smartparens icon indicating copy to clipboard operation
smartparens copied to clipboard

Fixing regex literals in Clojure

Open nsaritzky opened this issue 4 years ago • 0 comments

Expected behavior

#| Typing a quotation mark after # should generate a matching mark #""|

Actual behavior

Instead, no matching mark is inserted. #"| Then, when you add a second mark, a third is inserted #"""| If you follow this with a backspace to get down to two marks, instead you're brought to one as smartparens tries to delete the matching pair #"| So you end up having to do this: #"""| (left 1 character) #""|" (backspace) #"|"

This becomes bothersome if you're adding a lot of regexps.

Cause

I tracked down the cause to this predicate:

(defun sp-point-after-word-p (id action _context)
  "Return t if point is after a word, nil otherwise.
This predicate is only tested on \"insert\" action."
  ;; TODO: remove condition with sp-defpair
  (when (memq action '(insert escape))
    (sp--looking-back-p (concat "\\(\\sw\\|\\s_\\)" (regexp-quote id)))))

being used in default definition for the quotation mark pair:

(:open "\"" :close "\"" :actions
  (wrap insert autoskip navigate)
  :unless
    (sp-point-before-word-p sp-point-after-word-p sp-point-before-same-p)

The regex-part \\s_ matches a symbol in the current syntax table, denoted by '_'. In Clojure, # maps to the descriptor _ p, as listed in the table (roughly, "_ followed by stuff"). Therefore the predicate matches with the initial #, canceling the auto-insert.

I figure the solution would be to override that regex for Clojure to include all symbols except #. But I don't know how to say "Show me everything matching the '_' syntax descriptor" to emacs in order to do this. Another way might be to take advantage of the p part of _ p to exclude cases where point immediately follows the #, but I definitely don't know how to do that.

nsaritzky avatar Dec 15 '21 02:12 nsaritzky