TITLE: Task management macros in Vim
DATE: 2019-05-25
AUTHOR: John L. Godlee
====================================================================


I'm slowly trying to emulate parts of the Emacs Org-mode syntax.
Particularly, when I write TODO lists, having [ ] or [*] at the
beginning of a line to indicate whether that task is 'pending' or
'done', respectively. I'm not ready to dive straight into a Vim
Org-mode plugin, but I have started to write little functions to
make editing the files slightly more efficient. One such keybinding
is simply to toggle whether a task is marked as 'done' or 'pending':

 [Emacs Org-mode syntax]: https://orgmode.org/guide/

   " Toggle task as done
   autocmd Filetype text,markdown nnoremap <Leader>D :call
ToggleTask()<CR>

   function! ToggleTask()
       if (getline('.') =~ '^\[\*\]')>0      " If you find [*] at
line start
           .s/^\[\*\]/[ ]/g
       elseif (getline('.') =~ '^\[\ \]')>0  " OR If you find [ ]
at line start
           .s/^\[\ \]/[*]/g
       else                                  " OR if neither
           echom 'Not a task line'
       endif
   endfunction

The keybinding applies to text and markdown files and is called by
<Leader>d. This calls a function named ToggleTask(). The function
searches the current cursor line to see if it contains [*] and if
it does, replaces it with [ ], then if [*] isn't found it does the
opposite, searching for [ ] and changing it to [*], finally if
neither of the abov regexes are matched, a message echom is
displayed stating that the cursor line is not a task.

Similarly, I have the line below which makes a line a task line
simply by prepending it with [ ]:

   autocmd Filetype text,markdown nnoremap <Leader>T :s/^/[ ] /g
<CR>

These aren't perfect by any stretch, it would be nicer to roll the
whole lot into a more intelligent single function that can toggle
between 'not a task', 'task to do', 'finished task', that would
also take into account common line prefixes like enumerated lists.

Update - 2019_06_06

I did what I said I would do and rolled it all into one function:

   " Create and toggle done status of task lines
   autocmd Filetype text,markdown nnoremap <Leader>z :call
ToggleTask()<CR>

   function! ToggleTask()
       if (getline('.') =~ '^\[x\]')>0       " IF you find [x] at
line start
           .s/^\[x\]/[ ]/g
       elseif (getline('.') =~ '^\[\ \]')>0  " OR if you find [ ]
at line start
           .s/^\[\ \]/[x]/g
       elseif (getline('.') =~ '^\d\+\.\ \[\ \]')>0  " OR if the
line begins with 1. [ ]
           .s/\[\ \]/[x]/g
       elseif (getline('.') =~ '^\d\+\.\ \[x\]')>0  " OR if the
line begins with 1. [x]
           .s/\[x\]/[ ]/g
       elseif (getline('.') =~ '^\d\+\.')>0  " OR if the line
begins with a 1.
           .s/\d\+\./& [ ]/
       elseif (getline('.') =~ '^\*\|-')>0   " OR if the line
begins with a * or -
           .s/^\*\|-/[ ]/
       else                                  " OR if none
           .s/^/[ ] /g
       endif
   endfunction