Variable-width hanging indents in vim? - vim

This isn't a programming question per se, since I'm aiming to use this for note-taking -- but there just isn't any community more reliable for in-depth vim knowledge than this one.
What I'd like to do is set a hanging indent in vim - you know, the kind that looks like this:
Lorem ipsum dolor sit amet consectetur
adipisicing elit neque amet fuga
dolores voluptatem aspernatur
explicabo quasi. Nostrum...
Except I know you can do this with
set formatoptions+=2
What I'd really like is for vim to automatically set the width of the indent based on the presence of a special character in the first line. For instance, I might want to set this special character to ":" to format my text like so:
Lorem: Ipsum porro dolorem nostrum
incidunt similique a? Eaque
minus aliquid dolorem veritatis
omnis odit.
Quidem: distinctio quibusdam distinctio
accusamus alias magnam.
Voluptatem: dignissimos exercitationem
deleniti aliquam ratione?
Necessitatibus expedita
praesentium.
In my ideal scenario, this would also be compatible with vim's breakindent setting, which visually indents soft-wrapped lines (officially included in vim as of patch 7.4.338).
Does anyone know if this is possible - or even if this functionality can be achieved with a plugin?

Related

Vim: same change to all line-endings of selected lines?

In https://stackoverflow.com/a/11790464/5354137, there is a very detailed description how to, e.g. perform the same insert to the beginnings of all selected lines by placing the cursor over the first character of the first line, then after <C-v> moving down, then Isomething<Esc><down> inserting something everywhere.
But how does one do the same thing in the case of lines of unequal length, such as:
'Lorem ipsum
'dolor sit amet,
'consectetur adipiscing elit,
'sed do...
to their respective line endings? E.g. if I wanted to insert ', after m, ,, , and ., how would I do that without resorting to :substitute? (Or to a plugin, just using original vim-fu...)
Substitute (original answer)
The easiest way to do it is with the :substitute command. Select the lines in visual mode and then do:
:'<,'>s/$/',/<CR>
The $ stands for the end of the line. Note that vim will already write the :'<,'> part, so you only have to type from there.
Using a macro
With the question having been updated and :substitute off the table, I'd suggest recording a macro. Place the cursor on the line with "Lorm ipsum" and do:
qaA',<Esc>jq
then call the macro three times for the remaining lines. Either by hitting # a lot:
#a####
or with the more elegant
3#a
Using a recursive macro
As commented by #AndR, it's possible to record a macro that calls itself which will run until it reaches the end of the buffer:
qaqqaA',<Esc>j#aq
Note that the macro already calls itself with #a.
Afterwards, call #a and single quotes will be appended to every line until the end of the buffer.
Without visual selection
Both #AndR's answer using :normal and my :substitute answer above rely on a visual selection of the lines to modify. It is possible without that by typing in a range or line numbers. For "Lorem ipsum..." on lines 1 through 4, type either of the two commands:
:1,4s/$/',/
:1,4norm A',
This has the benefit that it works without a visual selection and from anywhere in the buffer.
Based on your reference link and reproduction steps, this is your problem halfway:
But how does one do the same thing in the case of lines of unequal length ...
Follow the link and use the first method Using only visual-block mode, let's start with step 5:
Select any column, hit <C-v> to enter visual-block mode and expand your selection toward the bottom:
'Lo[r]em ipsum
'do[l]or sit amet,
'co[n]sectetur adipiscing elit,
'se[d] do...
Hit $ or <End> (see :help $), will get the selection like this:
'Lo[rem ipsum]
'do[lor sit amet,]
'co[nsectetur adipiscing elit,]
'se[d do...]
Hit A',<Esc> to achieve your goal:
'Lorem ipsum',
'dolor sit amet,',
'consectetur adipiscing elit,',
'sed do...',
Note and supplement:
If you use the latest Vim9 and your virtualedit option contains block, when you hit $ or <End>, you may see this selection (Vim8 won't):
'Lo[rem ipsum ]
'do[lor sit amet, ]
'co[nsectetur adipiscing elit, ]
'se[d do... ]
This could be a issue with the VIM9 or an intentional design? I don't know, but don't care, just press A. You'll see your cursor at the end of the first line, which is fine (| is the cursor position):
'Lorem ipsum|
'dolor sit amet,
'consectetur adipiscing elit,
'sed do...
Then you enter the text you need (e.g. ',) and <Esc> ends editing, it works fine:
'Lorem ipsum',
'dolor sit amet,',
'consectetur adipiscing elit,',
'sed do...',
As a supplement, oppositely, if you want to insert text in the same column where has no text when there are irregular endings : You can add block to your virtualedit option (see :h 'virtualedit'), using other left-right-motions (e.g. l or |) instead of $ to get this selection:
'Lo[rem ipsum ]
'do[lor sit amet, ]
'co[nsectetur adipiscing elit, ]
'se[d do... ]
When you press A, the cursor will be at (| is the cursor position):
'Lorem ipsum |
'dolor sit amet,
'consectetur adipiscing elit,
'sed do...
Then enter the text you want (e.g. ',), hit <Esc> to obtain:
'Lorem ipsum ',
'dolor sit amet, ',
'consectetur adipiscing elit, ',
'sed do... ',
Here the goal can be achieved by appending ' at the end of each line. In one line you'd normally do A'. In order to do this this in each line of the visual selection, run
:<,>norm A'
Assuming that you have selected the needed lines visually (with v or V).
See :h :normal for details.

How to append a character after any number followed by a dot in Vim using regex?

I want to append a character after any number followed by a dot in Vim using regex.
Example (append -):
1. Contrary to popular belief, Lorem Ipsum is not simply random text.
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
4022. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Becomes:
1.- Contrary to popular belief, Lorem Ipsum is not simply random text.
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
4022.- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Please help.
:%s/\(\d\.\)/\1-/g
It changes this:
1. this 2. will
3_ do 4305. what 5.. you
ask 6*
to this:
1.- this 2.- will
3_ do 4305.- what 5.-. you
ask 6*
The way it works is to match and remember any digit \d followed by a dot \.
(the stuff between \( and \) is remembered for later use - these are called
capture groups). Then replace this with the remembered capture group using \1
and add a -. The g at the end makes happen for every match on each line.

Is it possible to make a pattern a single word for line wrapping purposes?

Edit: I changed the title to more accurately present what I am asking for. The sentence immediately below should read "is it possible to make a pattern, such as '.*' treated as a single word for line wrapping purposes?"
Using vimwiki, is it possible to prevent a link from being word-wrapped?
Currently,
Etiam iaculis tempor dui, et mollis ligula accumsan et. Nam mattis cursus lorem sit amet accumsan. [Mauris elementum turpis eget](magna) ultrices molestie. Maecenas sagittis mauris id lacus consectetur, cursus mollis ex pretium. Quisque volutpat tellus ut augue fermentum ultricies eget eu metus. In lacinia sit amet massa ut feugiat.
becomes
Etiam iaculis tempor dui, et mollis
ligula accumsan et. Nam mattis cursus
lorem sit amet accumsan. [Mauris
elementum turpis eget](magna) ultrices
molestie. Maecenas sagittis mauris id
lacus consectetur, cursus mollis ex
pretium. Quisque volutpat tellus ut
augue fermentum ultricies eget eu metus.
In lacinia sit amet massa ut feugiat.
Note the Mauris elementum turpis eget link. The link markdown is broken when the text is reformatted.
Setting a longer textwidth won't solve the issue; I prefer the width I already have, and it will still happen. Link breaking will just happen at different points.
Changing the general word wrap settings won't work either ... they are just the way I like them, except in this one case.
As said in the comment, text-width does limit the column count of your file. You can't turn it on and off based on a line. It is exactly like you would write a small piece of paper, there is just no space left.
Of course, vim has different options to control where exactly it breaks the line (see h formatoptions and h fo-table) , but they aren't context-sensitive. And as soon as your text between [ and ] will be longer than 80 chars, you will have the problem again.
So what are the alternatives?
Don't use text-width but use wrap. This will not limit your column count at all. But will display the lines of text over multiple lines of screen space.
set colorcolumn=80 this does not do anything for you, but highlight the column, so you can wrap the text yourself.
Write a custom function, that does the wrapping for you.
I was looking at this problem the wrong way.
Vimwiki is not parsing markdown link text with multiple lines correctly, but wontfix at the moment.
So, the options described elsewhere in this question are the only choices at the moment.
I answered this myself because I wanted to include an explanation of what was going on and a pointer to the relevant issue.

Vim: generate table of contents for plain text files (not Markdown)?

I'm aware of Vim plugins such as vim-markdown-toc, etc. but those apply to markdown files. Are there any approaches/suggestions for auto-generating a tables of contents in plain-text files (.txt, or no extension) in Vim? For example, something like:
CONTENTS
∙ Executive Summary
∙ Technical Review
∙ Biomedical Natural Language Processing
∙ Preliminary Work
... where (for convenience) headers could adopt the markdown syntax:
# EXECUTIVE SUMMARY
Lorem ipsum dolor sit amet, consectetur adipiscing elit. ...
...
# TECHNICAL REVIEW
Lorem ipsum dolor sit amet, consectetur adipiscing elit. ...
...
## BIOMEDICAL NATURAL LANGUAGE PROCESSING
Lorem ipsum dolor sit amet, consectetur adipiscing elit. ...
...
# PROPOSED WORK
Lorem ipsum dolor sit amet, consectetur adipiscing elit. ...
You could use something like that:
:g/^#* /t0
This will copy all this lines to the top. Unfortunaly in the wrong order, reverse it:
:0,4g/^/m0
(You may need to increase the numer 4 here, it is for your example). Then select the lines in visual line mode and replace # with tab or spaces.
:'<,'>s/#/ /g
Then do some formating. You could of course automate this further.

Vim snippets, without snippet/templating addon

I use vim a lot, but my workflow usually forces me to interact with other IDE's, so I am not a god-like vim poweruser, nor am I trying to be anytime soon. Vim is not an IDE for me, nor do I want it to be. It is a fast and light editor that doesn't get in my way.
I am looking for simplicity in both usage and config, not uber power or gold stars in efficiency.
I have been preloading several registers with my snippets up until now, and then keep a cheatsheet for which register has which text block. But I am running out of registers, and one single alpha-numeric letter does not immediately remind me of what I preloaded it with.
What is the easiest way to store any number of raw text blocks, and then retrieve them using a single keyword and 1 hotkey (in either order: keyword<>hotkey).
I don't need language aware snippets (clever keywords will be my solution)
I don't need snippets that are context aware or smart in any way
I don't plan on using a mini-template-language to streamline my snippets, thats excessive.
My snippets should literally paste in the raw text they were defined with, nothing else.
I guess I could just start writing named functions that merely print a block of text into the current buffer. Thats almost all I need, but I was hoping for a little easier way of maintaining/updating my snippet collection.
Are there any minimalist plugins out there that cover my use-case, or do I need to just stick with my .vimrc/python-commands approach?
Minor Update
I didn't realize you could chain so many letters with a mapleader, this may provide the magic I need. Then I will still have to alias back to some larger set of functions (probably use python to define commands).
If you want plugin-free solutions you can use:
abbreviations
:iabbrev obj var foo = {};<Left><Left>
:iabbrev func function foo() {<CR><CR>}<Up><Tab>
:iabbrev lipsum Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer diam augue, egestas quis, aliquam ut, venenatis ut, quam. Quisque ut augue. Integer non neque a lectus venenatis fermentum. Morbi quis eros nec elit molestie vehicula. Integer nunc lacus, sodales posuere, rutrum quis, blandit at, mi. Vivamus imperdiet wisi vel mauris. Morbi mattis ante non metus. Sed turpis dui, fermentum ut, aliquam eget, vulputate ullamcorper, pede. Nam non dolor. Etiam lobortis, urna id bibendum convallis, ligula augue auctor eros, a dictum sapien mi a tellus. Proin vel justo. Nunc malesuada turpis a sapien.
You can expand those with <Space> if you don't mind the trailing space or with <C-]> if you do.
See :help abbreviations.
insert mode mappings
You can create any complex mapping you want, either using <leader> or not.
The key (pun not intended), here, is just to choose a rarely used key and use it as a namespace for your mappings. On my French AZERTY keyboard, for example, I have the § key which is totally useless (not used in Vim, not used in French, not used in any programming language I work with). If I wanted to build a library of mappings I would use it as "leader" for those snippets:
:inoremap §obj var foo = {};<Left><Left>
:inoremap §func function foo() {<CR><CR>}<Up><Tab>
:inoremap §lipsum Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer diam augue, egestas quis, aliquam ut, venenatis ut, quam. Quisque ut augue. Integer non neque a lectus venenatis fermentum. Morbi quis eros nec elit molestie vehicula. Integer nunc lacus, sodales posuere, rutrum quis, blandit at, mi. Vivamus imperdiet wisi vel mauris. Morbi mattis ante non metus. Sed turpis dui, fermentum ut, aliquam eget, vulputate ullamcorper, pede. Nam non dolor. Etiam lobortis, urna id bibendum convallis, ligula augue auctor eros, a dictum sapien mi a tellus. Proin vel justo. Nunc malesuada turpis a sapien.
Whether you choose abbreviations or mappings, you can save all of them in a dedicated file:
~/.vim/snippets.vim
and source it in your ~/.vimrc:
runtime snippets.vim
If you decide to put that file somewhere outside your ~/.vim/ directory, you can source it with:
source ~/path/to/snippets.vim
edit
About <leader>…
<leader> is really not that special: you can generally think of it as a variable but, just like inserting $foo in a database will insert the value of $foo, registering <leader>something will register {current value of mapleader}something.
Supposing you create a custom <leader> mapping:
let mapleader = ","
map <leader>b :bnext<CR>
Vim registers ,b. If you decide to change you <leader> later in the current session:
:let mapleader = "%"
you'll still have ,b. Only further mappings will use the new <leader>:
map <leader>b :bnext<CR>
You get both ,b and %b.
<leader> means something only when you create a mapping. In usage, it's just ,b or %b.

Resources