Context sensitive word wrap in vi/vim - vim

How can I can specific word wrapping for specific tags. For example, in LaTex I want word wrapping for my paragraphs but not for my figure commands (they are always very long and run off the screen).
Or with Javascript, I want the right margin for code to be at, for example 50 columns, but for the comments to be at only 40 columns

This is not builtin
You could probably script something yourself using a devious combination of `formatexpr` and synID(). I suggest you look at the help of the latter first, because it contains inspirational samples:
for id in synstack(line("."), col("."))
echo synIDattr(id, "name")
endfor
taken from :he synstack
The formatexpr is usually set to something like
:set formatexpr=mylang#Format()
thus delegating to a filetype plugin. You could implement the function to use different margins for different syntax contexts.
Bear in mind
the default formatexpr (if absent, formatprg) are probably no good for a source file (in my experience it has the tendency to string together lines as if they were text paragraphs). But then again, you can implement it any which way you want
that syntax highlighting may become out of sync. I'm not sure what happens when the cursor is at, say, 70% of a large document and you issue ggVGgq. It might not update the syntax highlighting all the way (meaning that your formatexpr function would get the 'wrong' synID() values. You get around this by saying something like
:syntax sync fromstart
this again might impact the highlighting performance depending on the size/complexity of the source and highlighting scripts

Related

Vim: Is it possible to have a filtered view of a file?

In a given text file, I would like to work on a "filtered view" (hiding lines with a pattern), but still to be able to edit visible lines : the filtering would only affect the visibility of some lines, and as soon as I would reset the filter, the hidden lines would appear again.
The feature I describe could be compared to the & key in the less command (except, of course, that less can't edit the file's content) :
&some_pattern <RETURN> starts a new filter,
& <RETURN> reset the filter.
Does such a feature exist in vim, natively or as a plugin?
This usually is done with folding; you can easily define a 'foldexpr' that filters lines based on a regular expression match; see Folding with Regular Expression for implementations.
However, a single fold line will remain for each condensed block. To do away with those, I can only think of the NrrwRgn plugin, which transfers selected lines into a separate scratch buffer. It's usually only for a single block, but :help NR-multi-example suggests this works on ranges, too:
For example before editing your config file, you decide to strip all comments
for making big changes but when you write your changes back, these comments
will stay in your file. You would do it like this: >
:v/^#/NRP
:NRMulti
It can be done with plain Vim, and it's named folding. Drew Neil has two screencasts about it that you might find informative.

Is there a less fantastically kludgy way to do one-off highlights in Vim?

i. The Problem
My goal is something like the following:
I have a line of text like
Who left the dead mouse in the fridge?
and I want to highlight the first the in green, just this one occurrence. That is, I don't want to syn match ThisMagicWord "\<the\>" or anything that will overzealously highlight other thes.
There is one other requirement, which is that if the user edits the other text on the line, say to
Who on earth left the delicious dead mouse in the fridge?
the highlighting will track with the word the, so long as the user doesn't edit that one particular word.
ii. The Kludge
Now, I have a solution to this. In fact, I am proud of my solution, because it was tricky to think up. But it is not, by any stretch of the imagination, a good solution.
It turns out that the Unicode character Combining Grapheme Joiner is effectively a no-op in Vim. It produces no glyph, and takes up no width. It is the only such character that I have discovered. So what I do is, I surreptitiously edit the line in question to be
Who left the<CGJ> dead mouse in the fridge?
and then define a rule
syn match ThisMagicWord "the<CGJ>"
I will additionally trigger on BufWritePre and BufWritePost to strip the CGJs out of the file on disk.
iii. The Questions
Is there a no-op character in Vim (or a way to produce one) other than CGJ? Ideally a non-combining character, since the<CGJ> will not match a search for /the, due to the way Vim regexes handle combining characters.
Is there a better way to get at the behavior that I want?
You're right that there's currently no good way to mark static matches and keep them up-to-date when edits are done nearby. My approach would have been worse than your kludge: Include the line / column information in the match (via the \%l and \%v special atoms), and attempting to update those with a combination of marks (works for line changes) and intra-line custom diffing.
Though your use of special Unicode characters is clever, it's (as you admit) a hack. I've asked you for uses in the comments, and am still not completely satisfied / convinced. If you can come up with good, real use cases and current pain points, please direct them to the vim_dev mailing list (best with a functional draft patch attached). The functionality to keep track of such text is basically there (in the Vim internals), it's just not yet tracked and exposed to users / Vimscript. Though Vim development has been (often frustratingly) slow, with a compelling argument on your side, new functionality can and does happen.
How about using marks?
Move the cursor to the word you want, set a lowercase letter mark (e.g. mz), then add highlighting for the word like \%'zthe

Is there a way to elegantly comment specific lines in vim search history, similar to " in command-line history?

I am using vim to edit structured text files.
Sometimes I use search-and-replace feature, and sometimes I am better off with search, followed with a macro, in which case I have several macros at hand, and the choice of one depends upon the particular search result.
In both cases, though I have to spend some effort to arrive at an acceptable regex to satisfy my editing needs. As the regexs are often very long and sophisticated, I end up with both command-line history and search history full of my trial-and-error by-products. The correct regex is not always the last one in a series of attempts, so if I want to reuse the hard-earned regex in a similar editing situation, I have to dig through the pile again.
In search-and-replace scenario I have quickly fixed this with comments that I now put in place at the end of a would-be reusable search-and-replace command string, for example:
:%s/very_long_and_sophisticated_regex/another_long_and_sophisticated_regex/gc "comments on what this search and replace command does and how it might be reused
This way I can easily ignore the piles of stuff in my command line history and quickly find relevant re-use candidates, they are shown in different color. The commands are reusable right away, comments are ignored.
Not so with the search history, though.
Having rtfmed and searched the web, I have not found anything similar. At the moment I put quasi-comments using XXX at the end of reusable search strings, for example:
/search_string_containing_very_long_and_sophisticated_regex XXX comments on what it finds and how it might be re-used
This way I can at least find the right string for re-use, but I have to first delete 'XXX' and the comments.
I wonder if there is a more elegant way of commenting the search strings in search history, similar to command-line history.
You used the word "elegant" in your title, and that I don't have on offer. If instead you can also accept a quirky workaround that relies on Vim internals, here's one.
To restate your problem, it is possible to add comments after Ex :commands,
:AComplicatedExCommand -42 -quux " this fizzes the brobble
:HardToRememberCommand test.txt " use this to brew the framble
but the same is not possible for complicated search /queries (or ?queries).
I've just discovered that you can trick Vim by terminating your search query with a literal null byte:
/[Complicated]*regexp/^# this regexp finds all scrobbles
/another\+Rege\x*p/^# use this to search foo bars
The ^# here is a literal NUL. You can enter it by pressing CtrlV and then 000.
Vim will ignore everything after the null byte, but it'll still show the whole line in the search history, including the "comment".
You can add a regexp branch that never matches, e.g. /\%$indicator\|search string
\%$ is a special Vim atom matching the end of the file. Since that will never match when followed by the indicator text, the first branch (up to \|) will never match and therefore can represent your indicator.
I've created the TaggedSearchPattern plugin to make adding the tag and recalling it even easier.

VIM Delete Standard Scripting Word Groups

How would you use VIM to delete a word group, which includes white space characters, but is a standard grouping you would want to access when scripting? Specifically, when you have your cursor over some part of the following text, how would delete help="initialize, lines, h2, derivs, tt, history", from below. Maybe one would need to create specific mappings. But on the other hand, it seems pretty natural to want to access text like this if you are using VIM to edit scripting programs.
parser = argparse.ArgumentParser()
parser.add_argument("task", help="initialize, lines, h2, derivs, tt, history", default='yes')
Vim has a variety of text objects built-in, e.g. da" deletes quoted text (including the quotes; di" keeps the quotes). See :help text-objects for more information.
There are some plugins, e.g. textobj-user - Support for user-defined text objects and my own CountJump plugin that make it easy to define your own, "special" text objects. Also, you'll find many such text objects on vim.org. Based on your example, argtextobj.vim - Text-object like motion for arguments may be exactly what you need here.
If you are inside the " you want to delete, I would use:
di"diW
If you were above help=, I would use something like:
d/defEnter
to remove everything until you encounter default, followed by a few x, and left-wise motion, to remove the remaining characters.
I don't really think a new mapping is needed, but your experience may vary.
What makes sense from Vim's perspective and according to its design goals is to provide small and generic elements and a few rules to combine them in order to achieve higher level tasks. It does quite a good job, I'd say, with its numerous text-objects and motions but we always have to repeat domain-specific tasks and that's exactly where Vim's extensibility comes into play. It is where users and plugin authors fill the gap with custom mappings/object/functions and… plugins.
It is fairly easy, for example, to record a macro and map it for later reuse. Or create a quick and dirty custom text-object…
The following snippet should work with your sample.
xnoremap aa /\v["'][,)]/e<CR>o?\v\s+\w+\=<CR>
onoremap aa :normal vaa<CR>
With it, you can do daa, caa, yaa and vaa from anywhere within that argument.
Obviously, this solution is extremely specific and making it more generic would most certainly involve a bit more thought but there are already relatively smart solutions floating around, as in Ingo's answer.

Vim Visual Select around Variables

I'm wondering if there's a way to select variables intelligently in the same way that one can select blocks using commands like va}. There's some language-specific parsing going on to differentiate php and ruby, for example. For future reference, It'd be nice to tap into that - ideally selecting around various syntactic elements.
For example. I'd like to select around $array['testing'] in the following line of php:
$array['testing'] = 'whatever'
Or, lets say I want to select the block parameter list |item, index| here:
hash.each_with_index { |item, index| print item }
EDIT:
Specific regexps might address the various questions individually, but I have a sense that there ought to be a way to leverage syntactic analysis to get something far more robust here.
Though your given examples are quick to select with built-in Vim text objects (the first is just viW, for the second I would use F|v,), I acknowledge that Vim's syntax highlighting could be a good source for motions and text objects.
I've seen the first implementation of this idea in the SyntaxMotion plugin, and I've recently implemented a similar plugin: SameSyntaxMotion. The first defines motions for normal and visual mode, but no operator-pending and text objects. It does not skip over contained sub-syntax items and uses same color as the distinguishing property, whereas mine uses syntax (which can be more precise, but also more difficult to grasp), and has text objects (ay and iy), too.
You can define your own arbitrary text objects in Vim.
The simplest way to do custom text objects is defining a :vmap (or :xmap) for the Visual mode part and an :omap for the Operator-pending mode part. For example, the following mappings
xnoremap aC F:o,
onoremap aC :normal! F:v,<CR>
let you select a colon-enclosed bit of text. Try doing vaP or daP on the word "colon" below:
Some text :in-colon-text: more of the same.
See :h omap-info for another short example of :omap.
If you don't mind depending on a plugin, however, there is textobj-user. This is a general purpose framework for custom text objects written by Kana Natsuno. There are already some excellent text objects written for that framework like textobj-indent which I find indispensable.
Using this you can easily implement filetype-dependent text objects for variables. And make it available for everybody!

Resources