I edit files in Vim were I log terminal command lines along with descriptions of what I did. All my command lines start with $, so my files look like this:
This is a description of what this command does, it can be quite long and should have line breaks. $ ./the_command.sh
These are actually Viki files, but I guess this question should apply to any file type. I have filetype detection on and the files are correctly identified.
The question now is:
I want (hard) line breaks to be inserted into all the text except for the actual copies of command lines, which could be easily identified by the leading $.
Is it possible in Vim to define an exception for applying the line break rule based on a pattern? Would I do that in the syntax file for viki files?
UPDATE Using a combination of what Herbert and Jefromi suggested, I now have this in my .vimrc:
au CursorMovedI *.viki call SetTextWidth()
function! SetTextWidth()
if getline(".")=~'^\$'
set textwidth=1000
else
set textwidth=80
endif
endfunction
It does exactly what I want. Thanks guys!
I gather when you say you want "hard line breaks" you mean you want Vim to break a line automatically, as when it reaches a textwidth column. The best way to do this, I think, is to define an 'au' command that sets textwidth to a high number (higher than longest possible line) when it's on a line that begins with a "$".
So something like this would change textwidth whenever you enter or exit insert mode on a line:
au InsertEnter call SetTextWidth()
au InsertLeave call SetTextWidth()
function! SetTextWidth()
if getline(line('.')) =~ '^\$'
" [edit: 'set textwidth = 0' is preferable to line below]
set textwidth =1000
else
set textwidth=78
endif
endfunction
You might want to use the CursorMoved/CursorMovedI groups instead of InsertEnter/Leave since they're more fine-grained. They get triggered whenever you move the cursor, so the function ends up getting called lots more times, but function is simple enough that it's probably not going to introduce any noticeable degradation in performance.
For doing without a function at all you could probably use something like this:
au InsertEnter exec "set tw=" . getline(line('.'))=~'^\$' ? 1000 : 78
au InsertLeave exec "set tw=" . getline(line('.'))=~'^\$' ? 1000 : 78
I believe this would meet your criteria:
set textwidth=78
v/^$/normal gq/^$\|\%$^M
^M
is ctrl-v
followed by enter
Lets break this down into smaller peices
/^$\|\%$
is a pattern that matches every line not starting with a $. The \%$
will include the lines between the last $ started line and the end of file.
gq/^$\|\%$
formats from the current line up to the pattern /^$\|\%$
:normal {cmd}
executes a normal mode commands on current line.
:v/pattern/
is equivalent to :g!/pattern/
which executes a command on every line lot matching /pattern/
This solution does not format as you type as @Herbert Sitz solution does. Instead formats the text in one fell swoop at the end.
You could of course apply this before each write with
au BufWritePre filename-pattern-here set textwidth=78 | v/^$/normal gq/^$\|\%$^M
au BufWritePost filename-pattern-here set textwidth=0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With