Highlighting symbols automatically in Emacs - 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.

Related

difference between calling command directly and using keybinding

I'm new to elisp, so please forgive me if the following approach is totally clumsy.
In the team I'm currently working with, there is an usual convention of closing python blocks with a pass statement (if they aren't ended by closing keywords like else or except or such). While unusual, this has the advantage that one can always recover the original indentation of the program if it is unintentionally changed (using emacs indent-region).
To get existing code in line with this convention, I wrote a small elisp function:
(defun python-check-indent ()
"Check if automatic indentation changes current indent, insert pass keyword if it does."
(interactive)
(move-beginning-of-line 1)
(skip-chars-forward " ")
(if
(< 0
(let (original)
(setq original (point))
(indent-for-tab-command)
(- (point) original)
)
)
(progn
(insert "pass")
(newline)
(indent-for-tab-command)
)
)
(next-line)
)
(global-set-key (kbd "C-`") 'python-check-indent)
The idea is simply to test whether hitting TAB would change the indentation, and insert a pass statement in that case. To facilitate processing longer blocks of code, it then advances to the next line.
When I run it using M-x python-check-indent, it does what I want (except that it moves around empty lines slightly), also when running it repeatedly to process several lines. However, when I run it repeatedly using the C-` keybinding, it starts messing up the code from the second invocation on.
So here are my questions: What is the difference between invoking a command with M-x ... and using its keybinding? And how could I change the function to be not affected by this difference?
emacs-version: GNU Emacs 23.3.1 (x86_64-apple-darwin, NS apple-appkit-1038.35) of 2011-03-10 on black.porkrind.org
(edit) current workaround: I'm now wrapping it inside a keyboard-macro, so it's "bound" to C-x e, and behaves properly.
The general rule is that it is best to avoid complex interactive
commands in your functions because they could be affected by all sorts
of options.
(defun python-check-indent ()
"Check if automatic indentation changes current indent, insert pass keyword if it does."
(interactive)
(goto-char (line-beginning-position))
(skip-chars-forward " ")
(when (< 0
(let (original)
(setq original (point))
(python-indent-line)
(- (point) original)))
(insert "pass\n")
(python-indent-line))
(forward-line))
However, even this is probably not good because python-indent-line's behavior depends on last-command and python-indent-trigger-commands. I think it would be best if you replaced the first invocation of python-indent-line with the code which computes the target indentation instead of actually indenting, something like (nth python-indent-current-level python-indent-levels).
PS. If you still have problems, I suggest that you use edebug and step through the function.

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: highlighting TODO *only* in comments

This question is related to another one, Emacs :TODO indicator at left side. I recently came across a minor mode I like a lot called FixmeMode. It supports auto highlighting of TODO marks, and navigating between them. However, I think it makes more sense to recognize the "TODO" strings only in comments, rather than polluting the whole file. Is it possible?
Check out the library fic-mode.el, it has been verified in C++ and Emacs-Lisp.
It was written specifically to answer this question.
The installation is like any standard package:
(require 'fic-mode)
(add-hook 'c++-mode-hook 'turn-on-fic-mode)
Though Wei Hu did ask for an easy way to add it to multiple modes, so here goes:
(defun add-something-to-mode-hooks (mode-list something)
"helper function to add a callback to multiple hooks"
(dolist (mode mode-list)
(add-hook (intern (concat (symbol-name mode) "-mode-hook")) something)))
(add-something-to-mode-hooks '(c++ tcl emacs-lisp) 'turn-on-fic-mode)
It's possible but quite a bit trickier. Fixme mode uses font-lock to do its highlighting, so it works on an as-you-type basis to highlight the keywords. Font-lock hooks in at a very low level, basically running after every change is made to the buffer's contents. It is highly optimized, though, which allows it to appear instantaneous on modern computers.
The TODO indicator in the left fringe is static. Execute the function and all current TODO's are highlighted; change the buffer (adding or removing TODO's) does not change the fringe indicator; that's only changed when the function runs again.
Your approach would have to get into syntax tables, determining first when you're in a comment and then looking for the keywords. The tricky part comes in doing this interactively (i.e. as you type). You should be able to hook into the font-lock constructs to do this, but the function you provide to search for the comment syntax table and then for the keywords better be very efficient, as it will be run each and every time a buffer changes (though it will only run on the changed region, I think). You would want to stuff all of this in font-lock-syntactic-keywords rather than font-lock-keywords because the syntactic-keyword pass happens before the syntactic pass (which happens before the keyword pass), and you need to set TODO inside comments before comments themselves are set.
Sorry it's not a full working-code answer.....
Maybe this will help: there's a fn c-in-literal in
cc-mode, and a similar csharp-in-literal in csharp mode. The
return value is c if in a C-style comment, c++ if in a C++
style comment. You could add that to the code at
Emacs :TODO indicator at left side
to get what you want.
(defun annotate-todo ()
"put fringe marker on TODO: lines in the curent buffer"
(interactive)
(let (lit)
(save-excursion
(goto-char (point-min))
(while (re-search-forward "TODO:" nil t)
(progn
(setq lit (c-in-literal)) ;; or csharp-in-literal
(if (or (eq lit 'c) (eq lit 'c++))
(let ((overlay (make-overlay (- (point) 5) (point))))
(overlay-put overlay 'before-string
(propertize "A"
'display
'(left-fringe ;; right
horizontal-bar
better-fringes-important-bitmap))))))))))
https://github.com/tarsius/hl-todo seems to do exactly what you want. I just tried it and love it.

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)

How to automatically evaluate certain lisp code after starting an emacsclient?

When starting Emacs, init.el (or .emacs.el) is evaluated. However, when starting emacsclient, no similar lisp code is evaluated.
How can I get a lisp file to be evaluated every time I open a new emacsclient?
(This would be handy for frame specific customizations.)
I assume the answer is to use some hook, but I can't seem to find the correct hook to use.
I look forward to your answers.
You can add a function to the hook 'server-visit-hook, which is run every time the server is called (every time you call emacsclient).
I use the following code to automatically change the behavior of server buffers. I use it especially with the Firefox extension It's All Text. In that extension, buffers are named according to the domain name, so you can figure out which rule to apply by using string-match to match the name of the file.
(defun server-edit-presets ()
(cond
;; When editing mail, set the goal-column to 72.
((string-match "mail\\.google\\.com\\.[0-9a-z]+\\.txt" (buffer-name))
(longlines-mode-off)
(auto-fill-mode 1)
(set-fill-column 72)
(save-excursion
;; Don't know if this is necessary, but it seems to help.
(set-buffer (buffer-name))
(goto-char (point-min))
;; Replace non-breaking strange space characters
(while (search-forward (char-to-string 160) nil t)
(replace-match " "))))))
(add-hook 'server-visit-hook 'server-edit-presets)
(add-hook 'server-visit-hook '(lambda () (longlines-mode 1)))
If you really want new frame customizations, there's create-frame-hook which takes one arg (the new frame)...
If you mean gnuclient, you can use the command-line option "-eval" to evaluate something (and then just make an alias to always eval your customizations).
#LSW:
Try 'window-setup-hook. This addresses the annoyance since it is called even if emacsclient is not passed a file.
It seems that those hooks are no more, so here's the new version.
(add-hook 'server-after-make-frame-hook 'consult-recent-file)