Is there a vim equivalent to emacs's x-symbol? - vim

I am working on writing a vim plugin and I would like to have some way of displaying some tokens in the buffer using an alternative glyph to improve readability. Is there an existing approach to this problem? Is it even possible within vim?
What I have in mind is something like the emacs package x-symbol -- http://x-symbol.sourceforge.net/.

You'd get the very basics with
:se list
and the listchars option.
That is not very extensible though. For more involved work you can create concealing syntax rules:
Concealing
See
:he syn-conceal
:he 'cole'
:he hl-Conceal
Excerpts:
Syntax Rules
conceal *conceal* *:syn-conceal*
When the "conceal" argument is given, the item is marked as concealable.
Whether or not it is actually concealed depends on the value of the
'conceallevel' option. The 'concealcursor' option is used to decide whether
concealable items in the current line are displayed unconcealed to be able to
edit the line.
concealends *:syn-concealends*
When the "concealends" argument is given, the start and end matches of
the region, but not the contents of the region, are marked as concealable.
Whether or not they are actually concealed depends on the setting on the
'conceallevel' option. The ends of a region can only be concealed separately
in this way when they have their own highlighting via "matchgroup"
cchar *:syn-cchar*
The "cchar" argument defines the character shown in place of the item
when it is concealed (setting "cchar" only makes sense when the conceal
argument is given.) If "cchar" is not set then the default conceal
character defined in the 'listchars' option is used. Example: >
:syntax match Entity "&" conceal cchar=&
See |hl-Conceal| for highlighting.
Conceal Level
'conceallevel' 'cole' *'conceallevel'* *'cole'*
number (default 0)
local to window
{not in Vi}
{not available when compiled without the |+conceal|
feature}
Determine how text with the "conceal" syntax attribute |:syn-conceal|
is shown:
Value Effect ~
0 Text is shown normally
1 Each block of concealed text is replaced with one
character. If the syntax item does not have a custom
replacement character defined (see |:syn-cchar|) the
character defined in 'listchars' is used (default is a
space).
It is highlighted with the "Conceal" highlight group.
2 Concealed text is completely hidden unless it has a
custom replacement character defined (see
|:syn-cchar|).
3 Concealed text is completely hidden.
Note: in the cursor line concealed text is not hidden, so that you can
edit and copy the text. This can be changed with the 'concealcursor'
option.

Related

Limit vim syntax highlighting to diff

I am making changes to an existing C code. If I just want to check my changes, I can easily use vimdiff for that, with old & modified files.
What I want is to limit some syntax highlighting to just the diff part.
Particularly I need to highlight TABS, but only those TABS contained within DiffAdd & DiffChange sections/regions.
What I tried:
syntax region TESTRGN start="TESTRGN_START" end="TESTRGN_END"
highlight TESTRGN ctermbg=lightgreen guibg=lightgreen
syntax match LeadingTabsInRegion display contained containedin=TESTRGN /^\( *\t\+\)\+/
highlight LeadingTabsInRegion ctermbg=darkred guibg=darkred
Above snippet highlights the leading TABS within TESTRGN & tabs in remaining file remain un-highlighted.
However, if I change TESTRGN to DiffAdd in the syntax match line, it does not work as I expected.
My understanding is that DiffAdd is not a region defined using syntax region ... & hence containedin=DiffAdd does not work.
So is there any method/work-around for doing what I am trying to do?
First, what's so bad about having the highlighting everywhere? The diff highlighting stands out well and therefore provides visible scope; couldn't you just ignore the highlighting elsewhere?
In Vim, syntax groups are defined and then linked to colors and attributes defined in highlight groups. The diff stuff uses the second part of that mechanism, but not the syntax part. Therefore, you unfortunately cannot refer to the diff regions within :syntax commands.
There's only a very ugly workaround for this: You have to determine the line numbers that have diff highlighting (via repeatedly stepping through the changes with the ]c motion, and/or using synID() to check for diff highlighting). With those line numbers, you can then define :syntax match commands with the special \%l atom that only matches certain lines. Of course, any addition / deletion of lines would invalidate your definitions, which would need to be frequently re-synchronized (triggered by :autocmd). That's a lot of effort vs. just ignoring the highlighting elsewhere.
Though you need to reset whenever the line was changed, this is just a tip for one of line number based ideas, you can get a list of all diff highlighted lines with:
let dl = filter(range(1, line('$')),
\'index([hlID("DiffChange"), hlID("DiffText"), hlID("DiffAdd")],
\diff_hlID(v:val, 1)) != -1')
And using this, it might be possible to set your TESTRGN with:
exec "syntax match TESTRGN /\\(" . join(map(dl, '"\\%" . v:val . "l"'), "\\|") . "\\).*/"

Disable syntax hightlighting in vim only for specific buffer

I want to disable syntax highlighting but only for a specific buffer. I tried using modeline at the end of the buffer:
#vim:syntax off:
and
#vim:set syntax=off:
But it is not working.
You need a space (minimally) between the comment symbols and vim for mode lines to be parsed. The first one is also missing an equals sign.
# vim:syntax=off:
Or
# vim:set syntax=off:
If you look at :h modeline you will see that there can be any leading text before vim: but there needs to be whitespace after that text.
The two forms fix the patterns
[text]{white}{vi:|vim:|ex:}[white]{options}
[text] any text or empty
{white} at least one blank character (<Space> or <Tab>)
{vi:|vim:|ex:} the string "vi:", "vim:" or "ex:"
[white] optional white space
{options} a list of option settings, separated with white space
or ':', where each part between ':' is the argument
for a ":set" command (can be empty)
Or
[text]{white}{vi:|vim:|Vim:|ex:}[white]se[t] {options}:[text]
[text] any text or empty
{white} at least one blank character (<Space> or <Tab>)
{vi:|vim:|Vim:|ex:} the string "vi:", "vim:", "Vim:" or "ex:"
[white] optional white space
se[t] the string "set " or "se " (note the space); When
"Vim" is used it must be "set".
{options} a list of options, separated with white space, which
is the argument for a ":set" command
: a colon
[text] any text or empty
tl;dr Switch to the manual mode (:sy manual), enable syntax highlighting with :se syn=ON.
What :sy on (:syntax on) does under the hood is sets the 'syn' ('syntax') option for all the active buffers, and makes vim set the 'syn' option for any new files you open. :sy manual disables the latter automatic behavior. So to enable syntax highlighting for a buffer in the manual mode you've got to: :se syn=ON. To make it clear :sy manual doesn't affect the open buffers. They remain highlighted. But when you later do :se syn=ON, syntax highlighting is enabled for all the active buffers.
In other words if you're going to open a big file, you might want to do :sy manual before that. Then the file will open unhighlighted. If you open another file (you didn't open before in this vim instance, i.e. the inactive buffer doesn't exist) it will also open unhighlighted. To enable syntax for this (supposedly not big) buffer you'd do: se syn=ON. When you no longer need to work with the big file, you do: :sy on.

In Vim, how to keep characters concealed even when cursor enters that line

I may have a unique situation here. I want gVim (gui version, in Linux) to keep concealed characters concealed no matter what, even when the cursor is on that line or that character gets selected. (It should be as close to if the characters never existed as possible.) Currently the concealed characters show themselves when the cursor enters that line, which causes text to jump around when scrolling and when selecting text.
We are using gView (read-only gVim) to view logs, so as to take advantage of its robust syntax highlighting. Problem is, these logs contain lots of escape characters and TTY color codes, that make reading difficult. (^[33mSomeText^[0m)
I'm using this line to hide them:
syntax match Ignore /\%o33\[[0-9]\{0,5}m/ conceal
Since the files are viewed by non-vim-experts, it looks glitchy and broken when the text un-conceals itself. (And also looks glitchy and broken if the color codes are present, and also looks glitchy and broken if the color codes are blacked-out to become invisible, but still show when selected and appear after copy/paste.)
This should be fine because these files are opened read-only in gview, with an extra set nomodifiable making it even more difficult to save the file. While it's possible to edit and attempt to save the logs, doing so is considered both an invalid thing to do, and a harmless thing to do, and requires enough Vim skills that if someone manages to edit a file they know what they're doing. The problem with being able to edit a line with concealed text does not apply.
If 'conceal' can't be configured to keep hidden text hidden no matter what, an acceptable alternative would be to replace the TTY color codes with whitespace when the file gets opened. But, this has to be done in read-only mode, and we can't have gview throwing up a save dialog on closing the window because the file has been modified by its .vimrc.
Note: I am in full control of the .vim script file sourced when these are read, but cannot control the existence of the TTY color codes or the code that opens the log files in gview. (i.e. I can't pass it through sed or anything like that.) The ideal solution is anything that can transparently nuke the color codes from within a .vimrc, but I'll hear any suggestions. The 'conceal' feature is just my most promising lead.
So, any ideas how to permanently get rid of these on file view without dialogs popping up on close?
:help conceal
When the "conceal" argument is given, the item is marked as concealable.
Whether or not it is actually concealed depends on the value of the
'conceallevel' option. The 'concealcursor' option is used to decide whether
concealable items in the current line are displayed unconcealed to be able to
edit the line.
:help concealcursor
Sets the modes in which text in the cursor line can also be concealed.
When the current mode is listed then concealing happens just like in
other lines.
n Normal mode
v Visual mode
i Insert mode
c Command line editing, for 'incsearch'
'v' applies to all lines in the Visual area, not only the cursor.
A useful value is "nc". This is used in help files. So long as you
are moving around text is concealed, but when starting to insert text
or selecting a Visual area the concealed text is displayed, so that
you can see what you are doing.
Keep in mind that the cursor position is not always where it's
displayed. E.g., when moving vertically it may change column.
Also, :help conceallevel
Determine how text with the "conceal" syntax attribute |:syn-conceal|
is shown:
Value Effect ~
0 Text is shown normally
1 Each block of concealed text is replaced with one
character. If the syntax item does not have a custom
replacement character defined (see |:syn-cchar|) the
character defined in 'listchars' is used (default is a
space).
It is highlighted with the "Conceal" highlight group.
2 Concealed text is completely hidden unless it has a
custom replacement character defined (see
|:syn-cchar|).
3 Concealed text is completely hidden.
Only one command is needed: set concealcursor=n
I might have a better idea—you can pass it through sed (using %!sed) or really do a bunch of other :substitute commands—whatever edits you need to get rid of the color codes.
When you’re done, make sure to set nomodified—this forces vim to think there haven’t been any changes!

VIM: How to change the Showbreak Highlight color without using the NonText Color-element

I noted that the 'showbreak' symbol is highlighted with the highlight "NonText" color-element. NonText is also used for the EOL Characters.
I would like to keep the highlight-color for the EOL characters but want to change it for the showbreak symbol is that possible?
Another problem is that my showbreak symbol is not displayed.
I would like to use this symbol "↳" and put it in the linenumbers column (using set cpoptions+=n). I can't find out how to display the symbol and how to put a space after the showbreak symbol (between the text and the symbol).
Can anyone help me?
I don't think you're going to get highlighting to be different than the EOL character, at least I am not aware of a way to do that.
For the second part I can help with. I was able to get "↳ " to show up in my line number column with the following settings:
let &showbreak = '↳ '
set wrap
set cpo=n
Note that there is a space after the ↳. This lines up nice until you have > 9 lines in the file. If you wanted it to line up with the last character of the number column regardless of the number of lines I'm not sure what you're going to have to do.
Edit: I've recently written a proof-of-concept function for someone on IRC that highlights the first character on a line that has been wrapped with a different highlight group. It hasn't been tested much but it seems to work. Not exactly what you're looking for but maybe it's worth a look.
:help hl-NonText makes it pretty clear that you cannot have different colors for the 'showbreak' string and other non-text strings, of which eol is a member (see :help 'listchars'):
NonText
'~' and '#' at the end of the window, characters from 'showbreak' and
other characters that do not really exist in the text (e.g., ">"
displayed when a double-wide character doesn't fit at the end of the
line).
If you're willing to accept this limitation (#elliottcable) hi! link NonText LineNr will match the 'showbreak' string to the line number colors.
If you really wanted to get clever, as a compromise you could create a mapping or command to toggle between ':set list' and ':set nolist' that would also adjust the NonText highlight setting simultaneously.
If you use :set relativenumber (added in vim 7.3), :set showbreak=↳\ \ \ will reliably keep your 'showbreak' neatly lined up since the number width will not change as you navigate through the file. (This in addition to the :set cpo+=n and :set wrap #Randy Morris mentioned in his answer.)
You'll definitely need UTF-8 for the ↳ character, since it does not appear in other encodings. I'd strongly recommend you carefully document your encoding problems, with details about how to reproduce them along with your OS, its version, and the :version output of vim, and post them as separate questions. UTF-8 should be helping you wrangle multiple languages rather than being an impediment.

How to change word recognition in vim spell?

I like that vim 7.0 supports spell checking via :set spell, and I like that it by default only checks comments and text strings in my C code. But I wanted to find a way to change the behavior so that vim will know that when I write words containing underscores, I don't want that word spell checked.
The problem is that I often will refer to variable or function names in my comments, and so right now vim thinks that each piece of text that isn't a complete correct word is a spelling error. Eg.
/* The variable proj_abc_ptr is used in function do_func_stuff' */
Most of the time, the pieces seperated by underscores are complete words, but other times they are abbreviations that I would prefer not to add to a word list. Is there any global way to tell vim to include _'s as part of the word when spell checking?
Here are some more general spell-checking exception rules to put in .vim/after/syntax/{LANG}.vim files:
" Disable spell-checking of bizarre words:
" - Mixed alpha / numeric
" - Mixed case (starting upper) / All upper
" - Mixed case (starting lower)
" - Contains strange character
syn match spellingException "\<\w*\d[\d\w]*\>" transparent contained containedin=pythonComment,python.*String contains=#NoSpell
syn match spellingException "\<\(\u\l*\)\{2,}\>" transparent contained containedin=pythonComment,python.*String contains=#NoSpell
syn match spellingException "\<\(\l\+\u\+\)\+\l*\>" transparent contained containedin=pythonComment,python.*String contains=#NoSpell
syn match spellingException "\S*[/\\_`]\S*" transparent contained containedin=pythonComment,python.*String contains=#NoSpell
Change pythonComment,python.*String for your language.
transparent means that the match inherits its highlighting properties from the containing block (i.e. these rules do not change the way text is displayed).
contained prevents these matches from extending past the containing block (the last rule ends with \S* which would likely match past the end of a block)
containedin holds a list of existing syntax groups to add these new rules to.
contains=#NoSpell overrides any and all inherited groups, thus telling the spellchecker to skip the matched text.
You'll need to move it into its own group. Something like this:
hi link cCommentUnderscore cComment
syn match cCommentUnderscore display '\k\+_\w\+'
syn cluster cCommentGroup add=cCommentUnderscore
In some highlighters you may need contains=#NoSpell on the end of the match line, but in C, the default is #NoSpell, so it should be fine like that.

Resources