Task Management Using vim

Task management is a sensitive issue. Even the ones who do not explicitly manage tasks are defensive about how they do it. I was one of them for quite some time, till I realized that it was not working anymore. Like design, it is inevitable, it just happens. The problem is that it stops working after sometime and that too without any alarm.

I spent some time using other tools, reading philosophies like GTD and trying to customize it for my needs. Though there were some improvements some tedium was always present, and it sure did follow Matt Blodgett’s first law of software development.

So I set out to figure out my needs.

  • Tasks should be stored in pure text format, so that they are easily available from multiple interfaces. This also reduces the peripheral requirements and makes the system more portable.
  • The task management should work even when the Web connection is not available. This eliminates another big dependency.
  • I work on projects, so I want to group the tasks by projects. The orphan tasks go under unclassified, which is like an unclassified project.
  • A task had to capture the purpose, the action, the context and the constraints like the deadlines.
  • Though grouped by projects, I want to easily retrieve the tasks by timeline.
  • I need to use a tool that is always handy and available to me. Also, I end up working on multiple platforms, so it has to be a cross-platform tool.

I ended up on using vim as my base tool for this. And am I glad for this decision, take a look at this screenshot.

Task management in vim.


I used a schema to capture all information of the task. I wanted clear separation between different projects, so I decided to use one text file per project. The tasks were prefixed with a - . Every task would have a date, priority, action and status, e.g.,

- Discuss design decisions with xyz =01012007 =high :meet

No status implies the task has not even been started. I prefixed the date and the priority with = because it is one of the symbols easily accessible. The action meet indicates what is required to do so, the other ones I use are phone, email and chat. The actions are prefixed with a : so that they can be easily identified.

A task can have sub tasks, with the same schema. A task can also have its own document child, which I enclose within square brackets. This typically includes progress of the task or details which tend to get verbose a lot of times.

These child elements are indented inside the parent task so that I can use vim folding to use it as an outliner.

So the structure of a project file is:

Project Name *projecttag*

- Task 1 description =ddmmyyyy =high =started
    - Task 1a description =ddmmyyyy =done
        [Documentation of task 1a]   
    - Task 1b description

I typically also note down project specific information in there, like file paths and contact details of people involved.


Now I need a way of retrieving tasks by time. This is where the power of vim’s scripting comes in. I have the following functions in my .vimrc file.

function! Todo(day, ...)
    " Doing the first separately to clear the location list
    " before adding the first entry.
    let _date = strftime("%d%m", localtime()+a:day*86400)
        exec "lvimgrep /" . _date . "/j ~/wiki/*.txt"
    catch /^Vim(\a\+):E480:/

    if a:0 > 0
        " These commands will add results to the location list.
        for offset in range(a:day+1, a:1)
            " Returns 0601 for 1st June.
            let _date = strftime("%d%m", localtime()+offset*86400)
                exec "lvimgrepadd /" . _date . "/j ~/wiki/*.txt"
            catch /^Vim(\a\+):E480:/

    exec "lw"

command! Today :call Todo(0)
command! Tomorrow :call Todo(1)
command! Dayafter :call Todo(2)
command! Week :call Todo(0, 7)

It uses the lvimgrep command to look for the date pattern in text files under my wiki directory. The date string is formed using the strftime function. The results are stored in the location list and is invoked using the command lw. The try-catch is used to handle an exception when lvimgrep does not find any results. The script works perfectly for me today and lets me manage my tasks from vim, though I am sure that it can be optimized a lot. Also all my project files, which contain tasks by project are stored in ~/wiki/ directory.

Now all I have to do is use :Today command to get today’s tasks. The :Week command retrieves tasks for the whole week from today. This opens the location list in a split window and you can open the file by hitting Enter on the corresponding line. I like to open the file in a separate tab, so I position the cursor on the filename in the result and use gf command. I have mapped gf as:

map gf :tabe <cfile><CR>

It is possible that the function strftime is not available on some platforms. In such cases you can exploit the fact that it is a plain text format and use native scripting language to extract the data out of vim. Here is an example of how shell scripting can be used to retrieve the same data.

alias today='egrep -H `date +%d%m` ~/wiki/*.txt'
alias today+1="egrep -H =`date --date='tomorrow' +%d%m` ~/wiki/*.txt"
alias tomorrow='today+1'
alias today+2="egrep -H =`date --date='2 days' +%d%m` ~/wiki/*.txt"
alias today+3="egrep -H =`date --date='3 days' +%d%m` ~/wiki/*.txt"
alias today+4="egrep -H =`date --date='4 days' +%d%m` ~/wiki/*.txt"
alias today+5="egrep -H =`date --date='5 days' +%d%m` ~/wiki/*.txt"
alias today+6="egrep -H =`date --date='6 days' +%d%m` ~/wiki/*.txt"
alias today+7="egrep -H =`date --date='7 days' +%d%m` ~/wiki/*.txt"
alias week='today;tomorrow;today+2;today+3;today+4;today+5;today+6;today+7'

Syntax Highlighting

However, the task is still not visually parseable. So I used the following syntax file to make that happen.

" Vim syntax file
" Language:	Project
" Maintainer:	Abhijit Nadgouda (http://ifacethoughts.net/)

syntax clear

syn match projTag            "\*[a-zA-z]*\*"
syn match projJump           "|[a-zA-z]*|"

syn match projDate           "=\d\d\d\d\d\d\d\d" contained
syn match projDone           "=done" contained
syn match projHigh           "=high" contained

syn match projKeyword        ":phone" contained
syn match projKeyword        ":email" contained
syn match projKeyword        ":chat" contained
syn match projKeyword        ":meet" contained

syn match projTask      "\-\s.*" contains=projDate,projDone,projHigh,projKeyword
syn match projTaskH     "\-\s.*=high" contains=projDate,projHigh,projKeyword
syn match projTaskD     "\-\s.*=done$" contains=projDate,projDone,projKeyword
syn region projTaskDoc  matchgroup=Comment start=/\[/ end=/\]/

hi def link projTag          String
hi def link projJump         String

hi def link projDate         Constant
hi def link projDone         SpecialChar
hi def link projHigh         SpecialChar
hi def link projKeyword      SpecialChar

hi def link projTask         Statement
hi def link projTaskDoc      Comment
hi def link projTaskD        Comment
hi def link projTaskH        Special

I set the file type for every project file to project by including the line vim:sw=4:ts=4:ft=project at the end of every project file. The syntax file is called project.vim and place it in the syntax directory, which is ~/.vim/syntax/ for me. Needless to say even this can be optimized a lot. If the name project causes problems for you, you can use your name and set the filetype accordingly.

I also tag the projects so that they automatically become part of my wiki. Sometimes I also tag individual tasks, especially if I need to access some of them directly.

I now have a full-fledged task management system, which is organized by projects. Completed projects go in the archive and can be searched whenever required.

vim offers extreme extensibility from all aspects. Even you can modify the scripts, keywords and the syntax highlighting as per your needs and enjoy the power and convenience of vim.

Discussion [Participate or Link]

  1. Robert said:

    Very nice.

  2. Robert said:

    …hopefully you will put this up on the vim scripts site. =)

  3. Max said:

    I agree, great stuff! It would be great to see this on vim.org in the scripts section…

  4. Starr Horne said:

    You know, it’s funny –

    I just finished setting up my own GTD system using vim snippets and yaml (to make parsing easier)

    So far, I’m digging the stripped-down approach. Your system looks nice – especially the syntax highlighting.

  5. Vim for Project Management: http://ifac … « Random Trap said:

    […] pm on May 11, 2008 | # | Tags: gtd, projectmanagement, vim Vim for Project Management: http://ifacethoughts.net/2008/05/11/task-management-using-vim/ […]

  6. doce cosas : vim said:

    […] a hablar sobre el artículo “Task management usign vim” sobre gestión de tareas con VIM pero me he dado cuenta de que en la portada de […]

  7. links for 2008-05-12 - AndrasiNet said:

    […] Task Management Using vim | iface thoughts (tags: vim gtd productivity) You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site. […]

  8. bryan berry said:

    Why didn’t you consider VimOutliner or adding your code to it? I like vimoutliner because it has some very nice highlighting features and integrates code-folding — in this case To do folding — nicely. http://www.vimoutliner.org/

    Really the best tool for todo management is Emacs Org Mode IMHO. Vim doesn’t hurt my wrists like xemacs. C-x C-x M-shell => RSI. Xemacs also doesn’t run on every system, like you point out.

    If you are willing to use Emacs and sacrifice portability, you should really try Emacs Org mode. I am not 🙂

  9. links for 2008-05-18 « dMitry Alexandrov said:

    […] Task Management Using vim (tags: vim gtd pim productivity text) […]

  10. Steve said:

    Does not work for me. I know absolutely nothing about vim scripting, so I’m sure it’s something stupid. but when I cut and paste your script into my .vimrc file I get the following errors whenever I fire up vi.

    Error detected while processing /home/web/.vimrc:
    line 1:
    E319: Sorry, the command is not available in this version: :function! Todo(day, …)
    line 4:
    E319: Sorry, the command is not available in this version: : let _date = strftime(“%d%m”, localtime()+a:day*86400)
    line 5:
    E319: Sorry, the command is not available in this version: : try
    line 6:
    E319: Sorry, the command is not available in this version: : exec “lvimgrep /” . _date . “/j ~/Todo/*.txt”
    line 7:
    E319: Sorry, the command is not available in this version: : catch /^Vim(\a\+):E480:/
    line 8:
    E319: Sorry, the command is not available in this version: : endtry
    line 22:
    E319: Sorry, the command is not available in this version: : exec “lw”
    line 23:
    E319: Sorry, the command is not available in this version: :endfunction
    line 25:
    E319: Sorry, the command is not available in this version: :command! Today :call Todo(0)
    line 26:
    E319: Sorry, the command is not available in this version: :command! Tomorrow :call Todo(1)
    line 27:
    E319: Sorry, the command is not available in this version: :command! Dayafter :call Todo(2)
    line 28:
    E319: Sorry, the command is not available in this version: :command! Week :call Todo(0, 7)

  11. jerik said:

    Good to know that I am not the only one who manages projects with text files. A lot of interessting and usefull stuff which i will reconsider to integrate into my vim-project-organisation.

    Additional I use subversion as backup. The server is configured with webdav support, so that I can have access to the files even with the browser.

    cheers — jerik

  12. Extending Bash Auto-Completion | iface thoughts said:

    […] and using them to auto complete command line arguments for your application. I use vim as a wiki, task managemer and contacts. The vim helptags system lets me index the content instead of searching through it, […]

  13. SG said:

    Regarding those error messages “E319: Sorry, the command is not available in this version”, the problem is probably that you’re using a “tiny” version of vim that has a bunch of features removed. Ubuntu installs vim-tiny by default. To fix it, “apt-get install vim” to install the normal version.

  14. batz said:

    Great bit. Definitely a great choice (I prefer it to TVO), with a number of modifications it was exactly what I had been looking for (and it saved me from implementing a todo/time tracker it in Curses).


    If you’re interested…
    I mainly changed the syntax (+ for project which can take the date (with @date time\=) tags (:…) and priority (=low/med/high/done) reminder time (@rem offset date), added some states to the priorities (low/med/high/done), made tags be generic, added some keywords, changed the syntax for notes (~~…~~), and links ([…])), a perl script to send an email for reminders, and added a indentation file.

  15. Agrath said:

    Even being a year old, I just stumbled on this, and was curious how you use this tool to access tasks that don’t have dates attached to them. I see a handful of items in your example. Do you manually scan your project files individually? Or do you assign arbitrary reminder dates to objects with no solid due dates?

  16. Andrey said:

    I just found out that inside the for-loop lvimgrepadd should be used instead of lvimgrep,
    are you currently still using the VIM setup ?
    it would be very interesting to see more of your VIM based GTD system

  17. Federico Hernandez said:

    Very interesting setup. I came across while searching for more information orgmode for Emacs 😉

    I would like to point you to the CLI application “task” at http://taskwarrior.org which is a small app to handle task with projects, tags, due dates, etc on the command line. You can use it to do GTD.

    (Disclosure: I’m part of the developer team of task)

    Thanks for writing done your GTD approach.

  18. Andrey said:

    Inspired by your description I’ve setup my own small GTD system using the TVO outliner. I replaced the lvimgrep command with a python script to retrieve data: due-dates, contexts, etc.., this gives far more power and flexibility

    It’s pretty simple but already very useful for daily usage

  19. I Do Not Use The Tools I Recommend | iface thoughts said:

    […] List: Custom developed / Getting Things […]

  20. More On Task Managemnt Using vim | iface thoughts said:

    […] never expected that task management using vim will be used by others. It is a duct-tape approach that really worked well for me. My intention of […]

  21. Task Management Plugin for vim | iface thoughts said:

    […] I have converted my hacky task management script for vim into a plugin. It is still not polished, but the code is available at github and the plugin […]

  22. LastYvette said:

    I see you don’t monetize your website, don’t waste your traffic, you can earn additional bucks every month
    because you’ve got high quality content. If you want to know how to make extra bucks, search
    for: Mertiso’s tips best adsense alternative

Say your thought!

If you want to use HTML you can use these tags: <a>, <em>, <strong>, <abbr>, <code>, <blockquote>. Closing the tags will be appreciated as this site uses valid XHTML.



Abhijit Nadgouda
iface Consulting
+91 9819820312
My bookmarks


This is the weblog of Abhijit Nadgouda where he writes down his thoughts on software development and related topics. You are invited to subscribe to the feed to stay updated or check out more subscription options. Or you can choose to browse by one of the topics.