Emacs-lisp: prettify-symbols-mode for LaTeX - emacs

I was trying to port over the "pretty entities" behaviour from org-mode to latex-mode using the Emacs builtin prettify-symbols-mode. This mode uses font-lock-mode to display character sequences in a buffer as a single (unicode) character. By default for instance emacs-lisp code
(lambda () t)
becomes
(λ () t)
It does however seem to require the character sequences to be separated by some characters, e.g. white-spaces. For instance in my setup, the replacement
\alpha \beta -> α β`
will work, but it will fail when the strings are not separated, e.g.
\alpha\beta -> \alphaβ
This is an issue specifically, because I wanted to use this prettification to make quantum mechanical equations more readable, where I e.g. the replacement like
|\psi\rangle -> |ψ⟩
Is it possible to avoid this delimiter-issue using prettify-symbols-mode? And if it is not, is it possible by using font-lock-mode on a lower level?

Here's the code that should do what you want:
(defvar pretty-alist
(cl-pairlis '("alpha" "beta" "gamma" "delta" "epsilon" "zeta" "eta"
"theta" "iota" "kappa" "lambda" "mu" "nu" "xi"
"omicron" "pi" "rho" "sigma_final" "sigma" "tau"
"upsilon" "phi" "chi" "psi" "omega")
(mapcar
(lambda (x) (make-char 'greek-iso8859-7 x))
(number-sequence 97 121))))
(add-to-list 'pretty-alist '("rangle" . ?\⟩))
(defun pretty-things ()
(mapc
(lambda (x)
(let ((word (car x))
(char (cdr x)))
(font-lock-add-keywords
nil
`((,(concat "\\(^\\|[^a-zA-Z0-9]\\)\\(" word "\\)[a-zA-Z]")
(0 (progn
(decompose-region (match-beginning 2) (match-end 2))
nil)))))
(font-lock-add-keywords
nil
`((,(concat "\\(^\\|[^a-zA-Z0-9]\\)\\(" word "\\)[^a-zA-Z]")
(0 (progn
(compose-region (1- (match-beginning 2)) (match-end 2)
,char)
nil)))))))
pretty-alist))
As you can see above, pretty-alist starts out with greek chars. Then I add
\rangle just to demonstrate how to add new things.
To enable it automatically, add it to the hook:
(add-hook 'LaTeX-mode-hook 'pretty-things)
I used the code from here as a starting
point, you can look there for a reference.

The code of prettify-symbols-mode derives from code developped for languages like Haskell and a few others, which don't use something like TeX's \. So you may indeed be in trouble. I suggest you M-x report-emacs-bug requesting prettify-symbol-mode be improved to support TeX-style syntax.
In the mean time, you'll have to "do it by hand" along the lines of what abo-abo suggests.
One note, tho: back in the days of Emacs-21, I ported X-Symbol to work on Emacs, specifically because I wanted to see such pretty things in LaTeX. Yet, I discovered that it was mostly useless to me. And I think it's even more the case now. Here's why:
You can just use an actual ψ character in your LaTeX code instead of \psi nowadays. So you don't need display tricks for it to look "right".
Rather than repeating |\psi\rangle I much prefer defining macros and then use \Qr{\Vangle} (where \Vangle turns into \psi ("V" stands for "metaVariable"), and \Qr wraps it in a braket) so I can easily tweak those macros and know that the document will stay consistent. At that point, pretty-display of \psi and \rangle is of no importance.

Related

difference between two ways of specifying emacs lisp macro indent style

What is the difference or pros/cons between the two popular ways of specifying an indentation style for an Emacs Lisp macro I define?
The declare way:
(defmacro my-dotimes-1 (num &rest body)
(declare (indent 1)) ; <---
`(let ((it 0))
(while (< it ,num)
,#body
(setq it (1+ it)))))
The put way:
(defmacro my-dotimes-2 (num &rest body)
`(let ((it 0))
(while (< it ,num)
,#body
(setq it (1+ it)))))
(put 'my-dotimes-2 'lisp-indent-function 1) ; <---
(The name it is not a gensym because the example is copied from the --dotimes macro of dash.el which is intended as an anaphoric macro.)
The only difference I know of is that declare only works for Emacs Lisp, whereas the put method works for other languages as well (that is, if they use a similar technique for managing their indentation).
For instance, you can do things like
(put 'match 'clojure-indent-function 2)
To control how clojure-mode indents particular forms.
It's also worth noting that while indentation levels are most often specified for macros it also works with functions.
In addition to what jbm said, declare is not part of Emacs Lisp before version 22 (or it might be 21). So if you want your code to be usable also with older Emacs versions then do not use declare.
The first expands to the second, so there is no technical difference. Nowadays, the first is the recommended one, while the second is the underlying implementation.

Highlighting symbols automatically in Emacs

I am looking for a way to highlight symbols automatically, possibly using the package highlight-symbol.el (link).
I was wondering, is there a way so that, the first argument of all (setq ) will get automatically highlighted?
(setq thisshouldbehighlighted 1)
..and all the subsequent times when that symbol has been used / will be used.
First of all, the following code is based on version 1.2 of highlight-symbol. Older versions lack the function highlight-symbol-add-symbol.
The basic approach is to search the buffer for "(setq ". The actual regular expression is a bit more complex, as it allows whitespace and handles defvar and defcustom.
(defun highlight-all-symbols ()
(interactive)
(save-excursion
(highlight-symbol-mode 1)
(goto-char (point-min))
(while (re-search-forward (concat "([ \t\n]*"
"\\_<\\(?:"
"setq\\|defvar\\|defcustom"
"\\)\\_>[ \t\n]*"
"\\(\\_<\\(?:\\sw\\|\\s_\\)+\\_>\\)")
nil t)
(highlight-symbol-add-symbol (concat "\\_<"
(regexp-quote (match-string 1))
"\\_>")))))
You'll probably want to include the code in a mode hook
(add-hook 'emacs-lisp-mode-hook 'highlight-all-symbols)
Of course, simply highlighting all symbols set with setq can't be a perfect solution, as it ignores variable namespaces. Handling this correctly is a much bigger task, though, as it requires parsing the code. If you want to go down that rabbit hole, this might give you an idea, but I'm afraid it's not particularly documented.

How to make the tilde overwrite a space in Emacs?

I'd like (in TeX-related modes) the tilde key to insert itself as usual if point is on anything (in particular a line end), but if a point is on space, I'd like the tilde to overwrite it. (This would be a quite useful feature after pasting something into TeX source file.) I hacked something like this:
(defun electric-tie ()
"Inserts a tilde at point unless the point is at a space
character, in which case it deletes the space first."
(interactive)
(while (equal (char-after) 32) (delete-char 1))
(while (equal (char-before) 32) (delete-char -1))
(insert "~"))
(add-hook 'TeX-mode-hook (lambda () (local-set-key "~" 'electric-tie)))
My questions are simple: is it correct (it seems to work) and can it be done better? (I assume that if the answer to the first question is in the affirmative, the latter is a question of style.)
As mentioned, it's better to use a "character" literal than a number literal. You have the choice between ? , ?\ , and ?\s where the last one is only supported since Emacs-22 but is otherwise the recommended way, since it's (as you say) "more easily visible" and also there' no risk that the space char will be turned into something else (or removed) by things like fill-paragraph or whitespace trimming.
You can indeed use eq instead of equal, but the difference is not important.
Finally, I'd call (call-interactively 'self-insert-command) rather than insert by hand, but the difference is not that important (e.g. it'll let you insert 3 tildes with C-u ~).
Some points:
Instead of 32 use ?  (question-mark space) to express character literal.
Instead of defining keys in the major-mode hooks, do it in an eval-after-load block. The difference is that major-mode hook runs every time you use the major-mode, but there is only one keymap per major-mode. So there is no point in repeatedly redefining a key in it.
see: https://stackoverflow.com/a/8139587/903943
It looks like this command should not take a numeric argument, but it's worth understanding interactive specs to know how other commands you write can be made to be more flexible by taking numeric arguments into consideration.
One more note about your new modifications:
Your way to clear spaces around point is not wrong, but I'd do this:
(defun foo ()
(interactive)
(skip-chars-forward " ")
(delete-region (point) (+ (point) (skip-chars-backward " "))))

emacs: how do I use edebug on code that is defined in a macro?

I don't even know the proper terminology for this lisp syntax, so I don't know if the words I'm using to ask the question, make sense. But the question makes sense, I'm sure.
So let me just show you. cc-mode (cc-fonts.el) has things called "matchers" which are bits of code that run to decide how to fontify a region of code. That sounds simple enough, but the matcher code is in a form I don't completely understand, with backticks and comma-atsign and just comma and so on, and furthermore it is embedded in a c-lang-defcost, which itself is a macro. I don't know what to call all that, but I want to run edebug on that code.
Look:
(c-lang-defconst c-basic-matchers-after
"Font lock matchers for various things that should be fontified after
generic casts and declarations are fontified. Used on level 2 and
higher."
t `(;; Fontify the identifiers inside enum lists. (The enum type
;; name is handled by `c-simple-decl-matchers' or
;; `c-complex-decl-matchers' below.
,#(when (c-lang-const c-brace-id-list-kwds)
`((,(c-make-font-lock-search-function
(concat
"\\<\\("
(c-make-keywords-re nil (c-lang-const c-brace-id-list-kwds))
"\\)\\>"
;; Disallow various common punctuation chars that can't come
;; before the '{' of the enum list, to avoid searching too far.
"[^\]\[{}();,/#=]*"
"{")
'((c-font-lock-declarators limit t nil)
(save-match-data
(goto-char (match-end 0))
(c-put-char-property (1- (point)) 'c-type
'c-decl-id-start)
(c-forward-syntactic-ws))
(goto-char (match-end 0)))))))
I am reading up on lisp syntax to figure out what those things are and what to call them, but aside from that, how can I run edebug on the code that follows the comment that reads ;; Fontify the identifiers inside enum lists. ?
I know how to run edebug on a defun - just invoke edebug-defun within the function's definition, and off I go. Is there a corresponding thing I need to do to edebug the cc-mode matcher code forms?
What does def-edebug-spec do, and would I use it here? If so, how?
According to (elisp)Top > Debugging > Edebug > Edebug and Macros you have to tell Edebug how to debug a macro by defining it with debug statements or by using def-edebug-spec. This tells it what parameters should be evaluated and which shouldn't. So it can be done. In fact it looks as if c-lang-defconst already been fitted for edebug. Here is the definition in case you were interested:
(def-edebug-spec c-lang-defconst
(&define name [&optional stringp] [&rest sexp def-form]))
However, if you just want to see what the body evaluates to, then the way to do that is to use something like macro-expand-last-sexp below to see the result. Position your cursor after the sexp you want expanded (as you would for C-x C-e) and run M-x macro-expand-last-sexp RET. This will show you what it gets expanded to. You may run into troubles if you try to expand something like ,(....) so you may have to copy that sexp somewhere else and delete the , or ,#.
(defun macro-expand-last-sexp (p)
"Macro expand the previous sexp. With a prefix argument
insert the result into the current buffer and pretty print it."
(interactive "P")
(let*
((sexp (preceding-sexp))
(expanded (macroexpand sexp)))
(cond ((eq sexp expanded)
(message "No changes were found when macro expanding"))
(p
(insert (format "%S" expanded))
(save-excursion
(backward-sexp)
(indent-pp-sexp 1)
(indent-pp-sexp)))
(t
(message "%S" expanded)))))
I guess it depends on exactly what you are trying to do.
Use macroexpand or macroexpand-all to turn it into macro-free code and debug as usual?
Backticks &co may be best illustrated by an example:
(let ((a 1)
(b (list 2 3)))
`(a ,a ,b ,#b))
-> (a 1 (2 3) 2 3)
A backtick (or backquote`) is similar to a quote(') in that it prevents evaluation, except its effect can be selectively undone with a comma(,); and ,# is like ,, except that its argument, which must be a list, is spliced into the resulting list.

Changing Paredit Formatting

When using paredit in programming modes such as C, typing ( will insert a space before the paren when I'm trying to call a function, leaving me with:
foo ()
Is there a way to disable the insertion of the space without changing paredit's source?
Well, the way paredit appears to work is that it checks the syntax tables to see if you're inserting a pair right after a word/symbol/etc., in which case it forces a space to be inserted. You need to override that functionality - which can be done a number of different ways: advice, redefine the function determining space, changing the syntax table, etc.
I'd try the straight forward:
(defun paredit-space-for-delimiter-p (endp delimiter)
(and (not (if endp (eobp) (bobp)))
(memq (char-syntax (if endp (char-after) (char-before)))
(list ?\" ;; REMOVED ?w ?_
(let ((matching (matching-paren delimiter)))
(and matching (char-syntax matching)))))))
This will obviously apply to all places where you use paredit. If you want something more mode specific, you can add some conditions to that and statement (e.g. (and ... (memq major-mode '(c-mode lisp-mode)))).
So... I guess I did change the "source", but you can do the same thing with a piece of defadvice ... it's all elisp, so the difference is minimal. There doesn't appear to be a setting to control this type of behavior.
See paredit-space-for-delimiter-predicates
Well, Paredit is ideal for editing languages built of S-expressions. If you just like how it automatically inserts the closing paren, use feature skeleton-pair.
(setq skeleton-pair t)
(global-set-key "(" 'skeleton-pair-insert-maybe)