How to highlight region enclosed by parentheses in vim? - vim

Is there a way to automatically highlight the region enclosed by parentheses when the cursor goes over that region?
Take the following text as an example:
(define (example x)
(cond ((string? x) (display x))
(else (error "Bad" x))))
when the cursor goes above the cond, this particular region should be immediately highlighted (i.e. there should be no need to press any keys to achieve highlighting):
(cond ((string? x) (display x))
(else (error "Bad" x))))
Useful screenshot from something similar in emacs: https://www.emacswiki.org/emacs/HighlightSexps
I believe this highlighting feature will make reading s-expressions (basically Racket, Scheme, Clojure, Common Lisp code) a lot easier.
How can this highlighting be achieved in vim?

You can use va( (start visual mode, select from the previous opening ( to the corresponding closing ), including (with i(: excluding) the parentheses themselves). To remove the highlighting and go back to where you were, use <Esc>``.
I know that this is only a partial solution, but this is what you can get with built-in functions. More than that would require a plugin, but I don't know whether such exists.

Related

Selecting multiple text spots with visual mode?

I'm doing some markdown editing in vim on a file. I'm trying to convert it to markdown with code highlighting, etc.
- Arithmetic operators:`+,−,*, /`
- Constants: `e`, `pi`
- Functions: (abs x), (max x y... ), (ceiling x) (expt x y), (exp x),
(cos x), ...
I want to select only the things that are in parantheses (including the parantheses) in the following using visual mode (so they would be disjoint by the commas):
(abs x), (max x y... ), (ceiling x) (expt x y), (exp x),
(cos x), ...
And then do S` to surround the each piece of text with backticks. How can I do this without selcting each one, then doing S` repeatedly?
How can I do this without selcting each one, then doing S` repeatedly?
This is actually what works best in Vim. With a bit of help from macros:
Interactive version:
/(.\{-})<CR>
qqysa)`nnq
#q
##
##
... till you do them all and wrap around to where you started.
Non-interactive "just do it" version:
:set nows<CR>
gg
/(.\{-})<CR>
qqqqqysa)`nn#qq#q
You'll probably want to go back to :set ns afterwards.
Of course, if you know that there are no nested parentheses, then the simplest answer is using :s, like the other answerer suggested.
EDIT with the explanation of the macro:
qqqqq...#qq#q is a loop. Here's how it works:
qq followed by q clears the q register. This will be important later.
qq starts the macro recording.
ysa) surrounds around the parentheses with `.
nn goes to the next match. We have to do it twice, because surround jumps to before the paren, and n will match the same parentheses again.
#q invokes the q macro. It is empty, so this does nothing... now. However, read further...
q stops the macro recording, and stores it to the q register.
Now that q is not empty any more, we can execute it with #q. However, during the execution q will still not be empty, so when we get to the point in the macro that did nothing during the recording, the macro will relaunch, giving us a primitive, but functioning, recursion loop.
The loop stops when something in it breaks: for example, not being able to go to the next match. Usually, you'd just change all the matches so no more matches remain; however, the edit this macro does does not make the match fail, so we have to rely on :set nows to make sure we don't continue infinitely adding backticks to all parentheses.
After a bit of thought, you can actually rewrite the pattern so that :set nows (and additional n) is not needed:
/`\#<!(.\{-})<CR>
qqqqqysa)`n#qq#q
This matches a pair of parentheses not preceded by a backtick, so that after all matches have been dealt with there is no match for n, naturally breaking the loop.
If anyone thinks this is complex... note that most editors plain can't do it (since this takes into account proper parenthesis nesting, whereas I haven't yet seen an editor with search-replace robust enough to be able to pull it off).
Using a global command (assuming `S`` comes from surround.vim):
:global/(/normal f(ysab`
(This affects the whole file, and may only do one change at a time. Repeat with #:)
With a macro:
qqf(ysab`q
Repeat with #q and then ##
Or with substitute:
:substitute/([^)]\+)/`&`/g

Force Vim to align params in Lisp

I am in a computer science class that requires that Lisp style look like this:
(define append (as bs)
(if (null? as)
bs
(cons (car as)
(append (cdr as) bs))))
instead of like this:
(define append (as bs)
(if (null? as)
bs
(cons (car as)
(append (cdr as) bs))))
Namely, the if branches should be aligned. Is there a way to force Vim to do this?
If you want Vim's Lisp mode to treat all forms as function calls, so that items of a multi-line expression align with the second element, then simply clear the lispwords parameter:
:set lispwords=
From your exmaple, you do seem to want a split define to be treated with indentation rather than alignment. Figure out the set of forms for which you want indenting rather than aligning behavior and put that exact set into your lispwords:
:set lispwords=define[,... whatever other symbols]
This can be done based on file type with an auto-loaded. In your .vimrc file you can have:
:au BufRead,BufNewFile *.scm set lispwords=define
After putting that in my .vimrc temporarily, if I edit a new file:
$ vim foo.scm
and then insert a few lines, they get automatically formatted like thisL
(define fun ()
(if foo
(then ...)
(else ...)
~
~
~
:q!
I just hit Enter there; the auto-indentation kicked in. Vim's config already associates .scm files with Scheme and sets up Lisp mode. Our au command customizes that by overriding lispwords.

continuously execute an emacs lisp function

Is there a way to trigger the execution of an emacs lisp function other than M-x myfun? I would like to have the function re-called every time the buffer is changed.
Background: I have a table of numbers with some mistakes. The table has column totals and other features which can be used to identify the mistakes. My elisp function highlights suspicious columns of numbers. What I would like is for the highlighting to disappear as soon as the numbers are corrected, without repeated calling of the highlight-errors function.
The analogous feature in Excel is called, I believe, "conditional formatting"
The concept you're looking for in your first paragraphs is hooks. A hook variable is a list of functions that are executed when a certain event happens. Most hook variables have a name ending in -hook. The hook after-change-functions is executed each time you type something or otherwise change the buffer. Hooks are discussed in the Emacs Lisp manual under the heading "Hooks".
However, given what you're trying to do, it would be easier to use Emacs's highlighting mechanism. The solution may be as simple as adding a regexp in the right place.
Most files containing structured text (especially programming languages) are highlighted with the font locking mechanism. This is documented in both the Emacs and Emacs Lisp manuals under "Font Lock"; see in particular the function font-lock-add-keywords, for which the Emacs manual gives an example that is pretty much what you're after. There is also some information on the Emacs wiki.
ADDED:
Font lock can go beyond regexps; unfortunately the documentation is limited to the terse explanation in the docstring of font-lock-keywords. There are a few simple examples in cperl-mode.el (though they're somewhat buried in the mass). The wiki also references ctypes.el which uses this feature. Here is an example that highlights wrong integer additions.
(defun maybe-warn-about-addition ()
(let ((x (string-to-int (match-string 1)))
(y (string-to-int (match-string 2)))
(z (string-to-int (match-string 3))))
(if (/= (+ x y) z)
font-lock-warning-face)))
(font-lock-add-keywords
nil
'(("\\s-\\([0-9]+\\)\\s-*\\+\\s-*\\([0-9]+\\)\\s-*=\\s-*\\([0-9]+\\)\\s-"
(3 (maybe-warn-about-addition) t))))
Even the regexp can be replaced by arbitrary code that looks for the bounds of what you want to highlight (a function name as MATCHER, using the vocabulary from the docstring). There is an advanced example of font lock keywords in the standard C mode (cc-fonts.el).
Add your function to the variable after-change-functions.

Is there an extension or mode in Emacs similar to surround.vim?

Surround.vim is a nifty vim extension that allows you to surround blocks of text with , brackets, braces, and pretty much any arbitrary "surround" character. It supports paragraph and word surround, but I frequently use it in visual mode.
I'm playing around with Emacs and wondering if there's something similar; something that will let me highlight a region and then have the marked region (or rectangle) enclosed with braces, brackets or tags.
Maybe wrap-region is what you need.
smartparens is another excellent option if need to wrap something with delimiters, tags, etc.
I use evil-surround. It emulates vim behaviour but unfortunately might not be what most emacs users want since it requires the evil vim mode.
However, it may or may not be right for you since you referenced surround.vim in the first place.
evil-surround seems to support most of the features in Surround.vim, including modifying surroundings.
I don't think there is anything built in for tags, but for parens you can do M-(. For brackets/braces/quotes you could do:
(global-set-key (kbd "M-[") 'insert-pair)
(global-set-key (kbd "M-{") 'insert-pair)
(global-set-key (kbd "M-\"") 'insert-pair)
Note that if you don't have a region highlighted, it will just insert the pair of whatevers and put the cursor in between them. Also handy for deleting matching whatevers is
(global-set-key (kbd "M-)") 'delete-pair)
If you want to insert tag pairs, it's some simple elisp:
(defun my-insert-tags (tag)
(interactive "sTag: ")
(if (region-active-p)
(let ((beg (region-beginning)))
(save-excursion
(goto-char (region-end))
(insert "</" tag ">")
(goto-char beg)
(insert "<" tag ">")))
(insert "<" tag ">")
(save-excursion
(insert "</" tag ">"))))
Don't know of any way of doing that in Emacs, not even with a module.
My Elisp is a little rusty, buy here's a simple function that will enclose the current region (marked text) or word with quotes ("):
(defun insert-quotes ()
"Inserts quotes (\") around the current region or work."
(interactive)
(let (start end bounds)
(if (and transient-mark-mode mark-active)
(setq start (region-beginning)
end (region-end))
(progn
(setq bounds (bounds-of-thing-at-point 'symbol))
(setq start (car bounds)
end (cdr bounds))))
(goto-char start)
(insert "\"")
(goto-char (+ end 1))
(insert "\"")))
Yes, there is a clone of surround.vim, as of 1 week ago: http://github.com/timcharper/vimpulse-surround.el
It requires vimpulse, which requires vim. It implements much of surround.vim's functionality.
maybe evil-surround is what you are looking for.
thanks.
So you want to select a region or similar and then make a box around it like a various modes do for comments? I believe emacs-wiki (http://www.emacswiki.org/) has some ascii-line art (and a figlet tool as well) that will do that. Searching for box, quite, line art ...
############################
# #
# I AM REGION, WE ARE MANY #
# #
############################

How do I emulate Vim's 'softtabstop' in Emacs?

I've been trying to get into emacs lately, and one of the things I need to get right is indentation.
Example 1:
sub foo {
my $bar = 'quux';
|
Example 2:
sub foo {
my $bar = 'quux'; |# foo
Imagine that the pipe character in the above examples indicates the cursor position. Now, I use (4) spaces for every indent level (no tabs), and I have emacs setup to indent my code automatically with that in mind. No problems there. But in the examples above, if I were to hit backspace at the indicated cursor positions, I want emacs to backspace all the way back to the next indent level (column / 4). That is, I want it to treat the preceding whitespace as if it were made up of tabs. Instead, it always just erases a single space character.
In vim, I turn on 'expandtab' to make it insert spaces instead of tabs, and 'softtabstop', which makes it (among other things) backspace to the next "soft tabstop" as described above.
In emacs, I suppose I could (if I knew emacs/elisp better) bind backspace to a function which does something like the following:
if indent-tabs-mode is nil
if the cursor position is preceded by whitespace
calculate the position of the previous "soft tabstop"
if there's enough whitespace
backspace all the way to that point
else
backspace by one character
What I want to know is, is there a simpler way to do this, and/or does anyone know of an existing solution?
This works for me, where the 'tab-width is used as the width of the columns. Set the key in the appropriate keymaps...
(local-set-key (kbd "DEL") 'backward-delete-whitespace-to-column)
(defun backward-delete-whitespace-to-column ()
"delete back to the previous column of whitespace, or as much whitespace as possible,
or just one char if that's not possible"
(interactive)
(if indent-tabs-mode
(call-interactively 'backward-delete-char-untabify)
(let ((movement (% (current-column) tab-width))
(p (point)))
(when (= movement 0) (setq movement tab-width))
(save-match-data
(if (string-match "\\w*\\(\\s-+\\)$" (buffer-substring-no-properties (- p movement) p))
(backward-delete-char-untabify (- (match-end 1) (match-beginning 1)))
(call-interactively 'backward-delete-char-untabify))))))

Resources