Follow up to this question.
The Question
I have code for a custom key mapping with conditional logic. My understanding is that in vimscript, that means:
- it has to be all on one line
(since it's a key mapping), and - I'm restricted to using nested ternary operators
(since it's all on one line).
The code works, and is reproduced below. (I know there are extraneous parentheses, but it helps me see the code more clearly since it's already such a jumbled mess.)
nnoremap <expr> <Leader>o (getline(line(".")) =~ '\v^' . strpart(&commentstring,0,1) . '?$') ? ( (getline(line(".")-1) =~ '\v^' . strpart(&commentstring,0,1) . '?$') ? ( (getline(line(".")+1) =~ '\v^' . strpart(&commentstring,0,1) . '?$') ? ("i") : ("O") ) : ( (getline(line(".")+1) =~ '\v^' . strpart(&commentstring,0,1) . '?$') ? ("o") : ( strlen(getline(line("."))) == 0 ? ("O\<CR>") : ("O\<CR>\<Space>") ) ) ) : ( (getline(line(".")+1) =~ '\v^' . strpart(&commentstring,0,1) . '?$') ? ("o\<CR>") : ( strlen(getline(line("."))) == 0 ? ("o\<CR>\<C-o>O") : ("o\<CR>\<C-o>O\<Space>") ) )
How can I (/what facilities does vimscript offer to) simplify, refactor, or otherwise clean up this code?
Pseudocode for clarity
1 if (current line is empty, or contains only a single comment marker)
2 if (previous line is empty, or contains only a single comment marker)
3 if (next line is empty, or contains only a single comment marker)
4 ("i")
5 else
6 ("O")
7 else
8 if (next line is empty, or contains only a single comment marker)
9 ("o")
10 else
11 if (current line does not contain a comment marker)
12 ("O\<CR>")
13 else
14 ("O\<CR>\<Space>")
15 else
16 if (previous line is empty, or contains only a single comment marker)
17 ("o\<CR>")
18 else
19 if (current line does not contain a comment marker)
20 ("o\<CR>\<C-o>O")
21 else
22 ("o\<CR>\<C-o>O\<Space>")
The Background
The mapping above facilitates creating new paragraphs by inserting the necessary carriage returns between two lines of text and placing the cursor halfway inbetween. That is to say that when executed here,
CURSOR (NORMAL MODE)
Morbi tincidunt elementum facilisis. Sed convallis, mi et vulputate vestibulum, mauris nulla maximus risus, sed sagittis augue arcu a risus.Mauris porta mauris nisi, sed facilisis tortor volutpat vel.
the mapping does o<CR>
to produce this:
Morbi tincidunt elementum facilisis. Sed convallis, mi et vulputate vestibulum, mauris nulla maximus risus, sed sagittis augue arcu a risus.
CURSOR (INSERT MODE)
Mauris porta mauris nisi, sed facilisis tortor volutpat vel.
It's also context-sensitive, which means it creates the appropriate spacing depending on whether the current, previous, and next line are blank. Thus, it will create the exact same end state shown above even for the following scenarios:
CURSOR
Morbi tincidunt elementum facilisis. Sed convallis, mi et vulputate vestibulum, mauris nulla maximus risus, sed sagittis augue arcu a risus.
Mauris porta mauris nisi, sed facilisis tortor volutpat vel.
(via o<CR><C-o>O
),
Morbi tincidunt elementum facilisis. Sed convallis, mi et vulputate vestibulum, mauris nulla maximus risus, sed sagittis augue arcu a risus.
CURSOR
Mauris porta mauris nisi, sed facilisis tortor volutpat vel.
(via O<CR>
),
Morbi tincidunt elementum facilisis. Sed convallis, mi et vulputate vestibulum, mauris nulla maximus risus, sed sagittis augue arcu a risus.
CURSOR
Mauris porta mauris nisi, sed facilisis tortor volutpat vel.
(via O
), etc.
There are, on lines 11 and 19 of the pseudocode, conditions for auto-indenting comments. If anyone knows of a better way of doing this, I'd be glad to hear it, too.