├── t ├── clean.sh ├── test_setup.vim ├── README ├── test001.t ├── test007.t ├── test006.t ├── test002.t ├── test003.t ├── test999.t └── test005.t ├── .gitignore ├── misc ├── README ├── autocommit.cfg └── autocommit.sh ├── make_dist.sh ├── README ├── LICENSE ├── QUICKREF ├── autoload └── vimtodo.vim ├── syntax └── todo.vim ├── doc └── todo.txt └── ftplugin └── todo.vim /t/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm *.dbg 3 | rm *.out 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vimtodo.vba 2 | *.swp 3 | test/*.msgout 4 | test/*.out 5 | test/*.tap 6 | t/*.out 7 | t/*.dbg 8 | doc/tags 9 | -------------------------------------------------------------------------------- /t/test_setup.vim: -------------------------------------------------------------------------------- 1 | " Set the autoload path 2 | set rtp+=.. 3 | 4 | " Load the todo plugin 5 | " This should have the same effect as set ft=todo 6 | source ../ftplugin/todo.vim 7 | source ../syntax/todo.vim 8 | 9 | " Whitespace settings - makes checking indented text easy 10 | setlocal sw=4 sts=4 et 11 | -------------------------------------------------------------------------------- /t/README: -------------------------------------------------------------------------------- 1 | These tests require the vimcram plugin, available from: 2 | 3 | https://github.com/mivok/vimcram 4 | 5 | To run the tests, execute the run_test.sh script on one or more .t files in 6 | this directory. For example: 7 | 8 | /path/to/vimcram/run_test.sh *.t 9 | 10 | or to run a specific test: 11 | 12 | /path/to/vimcram/run_test.sh test001.t 13 | -------------------------------------------------------------------------------- /t/test001.t: -------------------------------------------------------------------------------- 1 | Test TODO entry creation macros 2 | 3 | Setup tests: 4 | 5 | :so test_setup.vim 6 | :let g:today = strftime("%Y-%m-%d") 7 | 8 | TODO entry creation with cn abbreviation 9 | 10 | > cn Test Entry 11 | TODO ${g:today} Test Entry 12 | 13 | TODO entry creation with \cn macro (note the trailing space) 14 | 15 | @\cn 16 | (3) TODO ${g:today} 17 | 18 | vim: ft=vimcram 19 | -------------------------------------------------------------------------------- /misc/README: -------------------------------------------------------------------------------- 1 | Autocommit script 2 | ================= 3 | 4 | Autocommit.sh is a script that will automatically commit and push any changes 5 | to a remote git repository. If you have your todo.txt file stored in a git 6 | repository, then adding this script to your crontab will keep the git 7 | repository up to date. 8 | 9 | Configuration is in autocommit.cfg. See the comments for what each option 10 | does. 11 | -------------------------------------------------------------------------------- /make_dist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [[ -z $1 ]] && { 3 | echo "Usage: $0 [tag]" 4 | exit 1 5 | } 6 | TAG=$1 7 | # Strip out any 'v' from the tag when making the filename (e.g. v0.1 -> 0.1) 8 | VER=${TAG#v} 9 | 10 | echo "Tagging $TAG" 11 | git tag -s -m "Tagging $TAG" $TAG 12 | cd .. 13 | echo "Making tarball - vimtodo-$VER.tgz" 14 | tar cz --exclude={.gitignore,.git,make_dist.sh,vimball.vim,*.swp} \ 15 | --exclude=vimtodo/test/*.{msgout,out,tap} \ 16 | --exclude=vimtodo/doc/tags \ 17 | --exclude=vimtodo.vba \ 18 | -f vimtodo-$VER.tgz vimtodo 19 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Installation instructions 2 | ------------------------- 3 | 4 | Option 1 - Untar to your ~/.vim directory 5 | 6 | Option 2 - Using pathogen (www.vim.org/scripts/script.php?script_id=2332): 7 | 8 | Untar/clone to ~/.vim/bundle/vimtodo/ 9 | 10 | Once installed, use :help vimtodo for more documentation, or see the 11 | doc/todo.txt file. 12 | 13 | Development/Support 14 | ------------------- 15 | 16 | Report issues at http://github.com/mivok/vimtodo/issues 17 | 18 | The latest revision of the source code is available from: 19 | http://github.com/mivok/vimtodo 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009, Mark Harrison 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | -------------------------------------------------------------------------------- /t/test007.t: -------------------------------------------------------------------------------- 1 | Test task time totals 2 | 3 | Test setup 4 | 5 | :so test_setup.vim 6 | 7 | Basic test 8 | 9 | > cn TODO test entry 10 | > Some Subtask [0.5h] 11 | > Some other subtask [1.5h] 12 | @\ce 13 | (2) :INFO: 14 | (3) +TOTALTIME: 2.00 15 | 16 | Two entries 17 | 18 | @ggdG 19 | > cn TODO test entry [2.5h] 20 | > Some subtask [1.5h] 21 | > Some subtask [13.25h] 22 | > cn TODO another entry 23 | > Subtask 1 [1.00h] 24 | > Subtask 2 [4.75h] 25 | @\ce 26 | (2) :INFO: 27 | (3) +TOTALTIME: 17.25 28 | (7) :INFO: 29 | (8) +TOTALTIME: 5.75 30 | 31 | Change one time entry 32 | 33 | @zR 34 | @4Gc$Some subtask [1.75h] 35 | @\ce 36 | (3) +TOTALTIME: 17.50 37 | 38 | vim: ft=vimcram 39 | -------------------------------------------------------------------------------- /t/test006.t: -------------------------------------------------------------------------------- 1 | Test Archiving 2 | 3 | Ensure we have a clean archive file first 4 | :w test006.archive 5 | 6 | Setup tests: 7 | 8 | :so test_setup.vim 9 | :let g:todo_done_file='test006.archive' 10 | 11 | Insert some test data 12 | 13 | > TODO 2009-09-07 Test entry 14 | > DONE 2009-09-08 Test entry 2 15 | > CANCELLED 2009-09-08 Test entry 3 16 | > WAITING 2009-09-09 Test entry 4 17 | > CLOSED 2009-09-10 Test entry 5 18 | 19 | Archive, and check that done tasks were removed 20 | @\ca 21 | TODO 2009-09-07 Test entry 22 | WAITING 2009-09-09 Test entry 4 23 | 24 | Now check the contents of the archive file 25 | 26 | :e! test006.archive 27 | DONE 2009-09-08 Test entry 2 28 | CANCELLED 2009-09-08 Test entry 3 29 | CLOSED 2009-09-10 Test entry 5 30 | 31 | Clean up 32 | 33 | :call delete("test006.archive") 34 | 35 | vim: ft=vimcram 36 | -------------------------------------------------------------------------------- /t/test002.t: -------------------------------------------------------------------------------- 1 | Test TODO state changes 2 | 3 | Setup tests: 4 | 5 | :so test_setup.vim 6 | 7 | Regular expression to match a timestamp: 8 | :let g:ts_re='\d\{4\}-\d\{2\}-\d\{2\} \d\{2\}:\d\{2\}:\d\{2\}' 9 | 10 | Insert a sample entry 11 | 12 | > TODO 2009-09-06 Test entry 13 | :let g:entry = '2009-09-06 Test entry' 14 | 15 | Single state change: 16 | 17 | @k 18 | @\cs 19 | DONE ${g:entry} 20 | ^ CLOSED: ${g:ts_re} re 21 | :LOGBOOK: 22 | ^ DONE: ${g:ts_re} re 23 | 24 | More state changes 25 | 26 | @\cs 27 | CANCELLED ${g:entry} 28 | ^ CLOSED: ${g:ts_re} re 29 | :LOGBOOK: 30 | ^ CANCELLED: ${g:ts_re} re 31 | ^ DONE: ${g:ts_re} re 32 | 33 | @\cs 34 | TODO ${g:entry} 35 | :LOGBOOK: 36 | ^ TODO: ${g:ts_re} re 37 | ^ CANCELLED: ${g:ts_re} re 38 | ^ DONE: ${g:ts_re} re 39 | 40 | vim: ft=vimcram 41 | -------------------------------------------------------------------------------- /misc/autocommit.cfg: -------------------------------------------------------------------------------- 1 | # vim: ft=sh 2 | # Configuration for todo file autocommit script 3 | 4 | # Which files to commit 5 | FILES="*.txt autocommit.sh autocommit.cfg .gitignore" 6 | 7 | # Only commit if a file was modified more than n seconds ago (to prevent lots of 8 | # commits when editing a file, change this to something like 300 or 600 - 5 or 9 | # 10 minutes) 10 | SECONDS=60 11 | 12 | # Default commit message 13 | MESSAGE="Auto commit" 14 | 15 | # Option to ping a host and only try to push/pull if that host is up 16 | TESTNET=yes 17 | # Host to ping to test connectivity - change this to the address of your git 18 | # server. 19 | PINGHOST=google.com 20 | 21 | # Push if there are local changes 22 | PUSH=yes 23 | # Pull remote changes 24 | PULL=yes 25 | # Name of git remote/branch 26 | REMOTE=origin 27 | BRANCH=master 28 | 29 | # Log everything to the following file 30 | LOGFILE=autocommit.log 31 | 32 | # Path to git if not in your path 33 | GIT=git 34 | -------------------------------------------------------------------------------- /t/test003.t: -------------------------------------------------------------------------------- 1 | Test checkboxes 2 | 3 | Setup tests: 4 | 5 | :so test_setup.vim 6 | 7 | Normal checkbox: 8 | 9 | > [ ] 10 | @k 11 | @\cc 12 | [X] 13 | @\cc 14 | [ ] 15 | 16 | Y/N/? checkbox 17 | 18 | @dd 19 | > [Y] 20 | @k 21 | @\cc 22 | [N] 23 | @\cc 24 | [?] 25 | @\cc 26 | [Y] 27 | 28 | +/-/. checkbox 29 | 30 | @dd 31 | > [+] 32 | @k 33 | @\cc 34 | [-] 35 | @\cc 36 | [.] 37 | @\cc 38 | [+] 39 | 40 | Checkbox with some text 41 | 42 | @dd 43 | > [ ] Some text 44 | @k 45 | @\cc 46 | [X] Some text 47 | 48 | Checkbox with indent and text 49 | 50 | @dd 51 | > [ ] Some text 52 | @k 53 | @\cc 54 | [X] Some text 55 | 56 | Add a checkbox 57 | 58 | @dd 59 | > Some text 60 | @k 61 | @\cb 62 | [ ] Some text 63 | 64 | Ensure repeated \cb commands don't add more checkboxes 65 | 66 | @\cb 67 | [ ] Some text 68 | 69 | Ensure repeated \cn commands on checked boxes don't add more of them 70 | 71 | @\cc 72 | @\cb 73 | [X] Some text 74 | 75 | vim: ft=vimcram 76 | -------------------------------------------------------------------------------- /t/test999.t: -------------------------------------------------------------------------------- 1 | Test in file settings 2 | 3 | We insert the text first before loading the setup as we want to test the 4 | settings getting applied as the plugin is loaded. 5 | 6 | > :SETTINGS: 7 | > +DONEFILE: done2.txt 8 | > +LOGDONE: 0 9 | > +LOGDRAWER: ALTERNATE 10 | > +STATES: TODO INPROGRESS | DONE 11 | > +STATES: WAITING(w) FOO(f) | BAR(b) 12 | > +STATECOLORS: TODO:green, DONE : blue 13 | > +STATECOLORS: INPROGRESS: magenta , FOO:red 14 | > +CHECKBOXSTATES: A B C 15 | > +CHECKBOXSTATES: 1 2 3 16 | > +TASKURL: http://www.google.com/%s 17 | > +BROWSER: firefox 18 | 19 | Setup for tests: 20 | 21 | :so test_setup.vim 22 | 23 | Compare variable values: 24 | 25 | ? g:todo_log_done == 0 26 | ? g:todo_log_into_drawer == 'ALTERNATE' 27 | ? g:todo_done_file == 'done2.txt' 28 | ? g:todo_states == [["TODO", "INPROGRESS", "|", "DONE"], 29 | \ ["WAITING(w)", "FOO(f)", "|", "BAR(b)"]] 30 | ? g:todo_state_colors == { "TODO" : "green", "DONE": "blue", 31 | \ "INPROGRESS": "magenta", "FOO": "red" } 32 | ? g:todo_checkbox_states == [["A", "B", "C"], ["1", "2", "3"]] 33 | ? g:todo_taskurl == "http://www.google.com/%s" 34 | 35 | vim: ft=vimcram 36 | -------------------------------------------------------------------------------- /QUICKREF: -------------------------------------------------------------------------------- 1 | Vimtodo quick reference 2 | ======================= 3 | 4 | Todo entry components 5 | ===================== 6 | 7 | TODO - status 8 | 2009-09-01 - creation date 9 | @computer - context 10 | +learnvim - project 11 | {2010-01-01} - due date 12 | tid12345 - external task manager ticket reference 13 | 14 | Commands 15 | ======== 16 | 17 | means the vim leader command, by default it is backslash ('\') 18 | 19 | cn - New TODO entry 20 | cs - Cycle task status 21 | cv - Choose task status 22 | 23 | cb - Add a checkbox 24 | cc - Toggle checkbox 25 | 26 | ct - Load a task link 27 | cl - Load a http link 28 | 29 | ca - Archive all done tasks 30 | 31 | cd - Show tasks due today (ex command: :Today) 32 | cf - Show tasks due tomorrow (ex command: :Tomorrow) 33 | cw - Show tasks due within 7 days (ex command: :Week) 34 | cx - Show overdue tasks (ex command: :Overdue) 35 | 36 | :Filter - Search for tasks matching regex 37 | 38 | Abbreviations (insert mode) 39 | =========================== 40 | 41 | cn - New TODO entry (TODO and today's date) 42 | ds - Today's date. Can be used as {ds} for a deadline 43 | -------------------------------------------------------------------------------- /autoload/vimtodo.vim: -------------------------------------------------------------------------------- 1 | " Vim filetype plugin for heirarchical TODO lists 2 | " Maintainer: Mark Harrison 3 | " License: ISC - See LICENSE file for details 4 | 5 | " Utility functions 6 | " TodoParseTaskState - Parse TODO(t) into state and shortcut key {{{1 7 | function! vimtodo#TodoParseTaskState(state) 8 | let state=matchstr(a:state, '^[A-Z]\+') 9 | let key=matchstr(a:state, '\(^[A-Z]\+(\)\@<=[a-zA-Z0-9]\()\)\@=') 10 | return { "state": state, "key": key } 11 | endfunction 12 | "1}}} 13 | 14 | " Default settings 15 | " Set - setup script variables {{{1 16 | function! vimtodo#Set(varname, value) 17 | if !exists(a:varname) 18 | exec "let" a:varname "=" string(a:value) 19 | endif 20 | endfunction 21 | "1}}} 22 | 23 | " Default variables {{{1 24 | function! vimtodo#SetDefaultVars() 25 | call vimtodo#Set("g:todo_states", 26 | \[["TODO(t)", "|", "DONE(d)", "CANCELLED(c)"], 27 | \["WAITING(w)", "CLOSED(l)"]]) 28 | call vimtodo#Set("g:todo_state_colors", { "TODO" : "Blue", "DONE": "Green", 29 | \ "CANCELLED" : "Red", "WAITING": "Yellow", "CLOSED": "Grey" }) 30 | call vimtodo#Set("g:todo_checkbox_states", [[" ", "X"], ["+", "-", "."], 31 | \["Y", "N", "?"]]) 32 | call vimtodo#Set("g:todo_log_done", 1) 33 | call vimtodo#Set("g:todo_log_into_drawer", "LOGBOOK") 34 | call vimtodo#Set("g:todo_done_file", "done.txt") 35 | call vimtodo#Set("g:todo_property_vars", {}) 36 | call vimtodo#Set("g:todo_property_types", {}) 37 | endfunction 38 | "1}}} 39 | -------------------------------------------------------------------------------- /misc/autocommit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Autocommit script - pushes your todo file to a git repository and pulls any 3 | # updates. 4 | # 5 | # Add it to cron to run every minute (or 5 minutes if desired) 6 | # 7 | 8 | MYDIR=`dirname $0` 9 | 10 | [[ -f $MYDIR/autocommit.cfg ]] && . $MYDIR/autocommit.cfg 11 | 12 | # Debugging functions 13 | if [[ "$1" == "-x" ]]; then 14 | DEBUG=yes 15 | else 16 | DEBUG=no 17 | fi 18 | 19 | debugmsg() { 20 | if [[ "$DEBUG" == "yes" ]]; then 21 | echo "$@" 22 | fi 23 | echo "$@" >> $LOGFILE 24 | } 25 | 26 | CURRTIME=`date +%s` 27 | COMMIT=no 28 | PINGCMD="ping -q -n -W 1 -c 1 $PINGHOST" 29 | NETWORKUP=no 30 | 31 | cd $MYDIR 32 | debugmsg "===================================================================" 33 | debugmsg "Running $0 - `date`" 34 | debugmsg "===================================================================" 35 | 36 | debugmsg "In: $PWD" 37 | debugmsg "Currtime: $CURRTIME" 38 | 39 | debugmsg "Files:" 40 | for f in $FILES; do 41 | MODTIME=`stat -c %Y $f` 42 | debugmsg -n " $f - $MODTIME - " 43 | # If the file wasn't modified in the last $SECONDS seconds, then add it to 44 | # be committed 45 | if [[ "($CURRTIME - $SECONDS)" -gt "$MODTIME" ]]; then 46 | debugmsg "adding" 47 | $GIT add $f > /dev/null 48 | else 49 | debugmsg "not adding: recently modified" 50 | fi 51 | done 52 | 53 | if TESTNET=yes; then 54 | debugmsg -n "Testing for network connectivity - " 55 | if $PINGCMD > /dev/null 2>&1; then 56 | debugmsg "UP" 57 | NETWORKUP=yes 58 | else 59 | debugmsg "DOWN" 60 | NETWORKUP=no 61 | fi 62 | else 63 | debugmsg "Not testing for network connectivity - assuming it is up" 64 | NETWORKUP=yes 65 | fi 66 | 67 | if $GIT status > /dev/null; then 68 | debugmsg "We have changed files - committing" 69 | $GIT commit -m "$MESSAGE" >> $LOGFILE 70 | fi 71 | 72 | if [[ "$PUSH" == "yes" ]]; then 73 | debugmsg -n "Try to push - " 74 | if [[ "$NETWORKUP" == "yes" ]]; then 75 | if ! $GIT diff --quiet $BRANCH..$REMOTE/$BRANCH; then 76 | debugmsg "Pushing" 77 | $GIT push --porcelain $REMOTE $BRANCH >> $LOGFILE 2>&1 78 | else 79 | debugmsg "Nothing to push" 80 | fi 81 | else 82 | debugmsg "Network down" 83 | fi 84 | fi 85 | 86 | if [[ "$PULL" == "yes" ]]; then 87 | debugmsg -n "Try to pull - " 88 | if [[ "$NETWORKUP" == "yes" ]]; then 89 | debugmsg "pulling" 90 | $GIT pull $REMOTE $BRANCH >> $LOGFILE 2>&1 91 | else 92 | debugmsg "Network down" 93 | fi 94 | fi 95 | -------------------------------------------------------------------------------- /syntax/todo.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Maintainer: Mark Harrison 3 | " Last Change: Aug 15, 2009 4 | " License: ISC - See LICENSE file for details 5 | 6 | " au BufRead,BufNewFile todo.txt,*.todo.txt,recur.txt,*.todo set filetype=todo 7 | 8 | " Quit when a (custom) syntax file was already loaded 9 | if exists("b:current_syntax") 10 | finish 11 | endif 12 | 13 | " Load default variables if not already set 14 | call vimtodo#SetDefaultVars() 15 | 16 | syn match todoProject /+\S\+/ 17 | syn match todoContext /\s@\S\+/ 18 | syn match todoPriority /([A-Z])/ 19 | "syn match todoDone /^\s*\[\?[xX]\]\?\s.*/ 20 | 21 | syn match todoDate /\w\?{[^}]\+}[+=-]\?/ 22 | syn match todoDate /\d\{4\}-\d\{2\}-\d\{2\}/ 23 | syn match todoTasknum /tid\d\+/ 24 | 25 | syn match todoURI /\w\+:\/\/\S\+/ 26 | syn match todoEmail /\S\+@\S\+\.\S\+/ 27 | 28 | syn match todoBold /\*[^*]\+\*/ 29 | syn match todoUline /_[^_]\{2,}_/ 30 | syn match todoComment /\s*#.*$/ 31 | syn match todoLog /\(^\s*\)\@<=[A-Z]\+:/ 32 | syn match todoDrawer /\(^\s*\)\@<=:[A-Z]\+:/ 33 | 34 | hi def link todoProject Statement 35 | hi def link todoContext Identifier 36 | hi def link todoPriority Special 37 | hi def link todoDone Comment 38 | hi def link todoDate Constant 39 | hi def link todoTasknum Number 40 | 41 | hi def link todoBold PreProc 42 | hi def link todoUline PreProc 43 | hi def link todoComment Comment 44 | hi def link todoLog PreProc 45 | hi def link todoDrawer Type 46 | 47 | hi def link todoURI String 48 | hi def link todoEmail String 49 | 50 | " Highlight state colors 51 | function! s:HighlightStatus(name, color) 52 | " Sets the highlight for a particular status to the given color 53 | let name=toupper(a:name) 54 | exe "syn match todoState".name." /\\(^\\s*\\)\\@<=".name. 55 | \":\\?\\(\\s\\|$\\)\\@=/ contains=todoDone" 56 | exe "hi def todoState".name." guifg=".a:color." ctermfg=".a:color. 57 | \" gui=bold cterm=bold" 58 | endfunction 59 | for state in keys(g:todo_state_colors) 60 | call s:HighlightStatus(state, g:todo_state_colors[state]) 61 | endfor 62 | 63 | " Might want to make this dynamic so we can add 'contains=todoLogDONE' etc. 64 | function! s:HighlightDone() 65 | for group in g:todo_states 66 | let idx = index(group, "|") 67 | if idx != -1 68 | let idx = idx + 1 69 | elseif idx == len(group) 70 | continue 71 | endif 72 | let parsed = [] 73 | for state in group[idx+0:] 74 | call add(parsed, vimtodo#TodoParseTaskState(state)["state"]) 75 | endfor 76 | let match = join(parsed, "\\|") 77 | exec "syn region todoDone start=\"^\\z(\\s*\\)\\%(".match."\\)\\s\"". 78 | \" end=\"^\\%(\\n*\\z1\\s\\)\\@!\"". 79 | \" contains=todoLog" 80 | endfor 81 | endfunction 82 | call s:HighlightDone() 83 | 84 | let b:current_syntax = "todo" 85 | -------------------------------------------------------------------------------- /t/test005.t: -------------------------------------------------------------------------------- 1 | Test TODO entry filtering 2 | 3 | Setup tests: 4 | 5 | :so test_setup.vim 6 | 7 | Make sure we don't include any of the user's files: 8 | 9 | :if exists("g:todo_files") | unlet g:todo_files | endif 10 | 11 | Set some variables to match specific dates: 12 | 13 | :let g:lastmonth = strftime("%Y-%m-%d", localtime() - 86400 * 30) 14 | :let g:lastweek = strftime("%Y-%m-%d", localtime() - 86400 * 7) 15 | :let g:yesterday = strftime("%Y-%m-%d", localtime() - 86400) 16 | :let g:today = strftime("%Y-%m-%d") 17 | :let g:tomorrow = strftime("%Y-%m-%d", localtime() + 86400) 18 | :let g:day2 = strftime("%Y-%m-%d", localtime() + 86400 * 2) 19 | :let g:day3 = strftime("%Y-%m-%d", localtime() + 86400 * 3) 20 | :let g:day4 = strftime("%Y-%m-%d", localtime() + 86400 * 4) 21 | :let g:day7 = strftime("%Y-%m-%d", localtime() + 86400 * 7) 22 | :let g:day8 = strftime("%Y-%m-%d", localtime() + 86400 * 8) 23 | 24 | Insert some TODO entries with varying due dates. 25 | 26 | > TODO ${g:today} Last Month {${g:lastmonth}} 27 | > TODO ${g:today} Last Week {${g:lastweek}} 28 | > TODO ${g:today} Yesterday {${g:yesterday}} 29 | > TODO ${g:today} Today {${g:today}} 30 | > TODO ${g:today} Tomorrow {${g:tomorrow}} 31 | > TODO ${g:today} 2 Days {${g:day2}} 32 | > TODO ${g:today} 3 Days {${g:day3}} 33 | > TODO ${g:today} 4 Days {${g:day4}} 34 | > TODO ${g:today} 7 Days {${g:day7}} 35 | > TODO ${g:today} 8 Days {${g:day8}} 36 | > DONE ${g:today} Last Month {${g:lastmonth}} 37 | > DONE ${g:today} Last Week {${g:lastweek}} 38 | > DONE ${g:today} Yesterday {${g:yesterday}} 39 | > DONE ${g:today} Today {${g:today}} 40 | > DONE ${g:today} Tomorrow {${g:tomorrow}} 41 | > DONE ${g:today} 2 Days {${g:day2}} 42 | > DONE ${g:today} 3 Days {${g:day3}} 43 | > DONE ${g:today} 4 Days {${g:day4}} 44 | > DONE ${g:today} 7 Days {${g:day7}} 45 | > DONE ${g:today} 8 Days {${g:day8}} 46 | :silent w test005.txt 47 | 48 | Tasks due Today (\cd command) 49 | 50 | @\cd 51 | :close 52 | ? map(getloclist(0), 'v:val.text') == [ 53 | \ 'TODO '.g:today.' Today {'.g:today.'}' 54 | \ ] 55 | 56 | Tasks due Today (:Today command) 57 | :Today 58 | :close 59 | ? map(getloclist(0), 'v:val.text') == [ 60 | \ 'TODO '.g:today.' Today {'.g:today.'}' 61 | \ ] 62 | 63 | 64 | Tasks due Tomorrow (\cf command) 65 | 66 | @\cf 67 | :close 68 | ? map(getloclist(0), 'v:val.text') == [ 69 | \ 'TODO '.g:today.' Tomorrow {'.g:tomorrow.'}' 70 | \ ] 71 | 72 | Tasks due Tomorrow (:Tomorrow command) 73 | 74 | :Tomorrow 75 | :close 76 | ? map(getloclist(0), 'v:val.text') == [ 77 | \ 'TODO '.g:today.' Tomorrow {'.g:tomorrow.'}' 78 | \ ] 79 | 80 | Tasks due in 7 days (\cw command) 81 | 82 | @\cw 83 | :close 84 | ? map(getloclist(0), 'v:val.text') == [ 85 | \ 'TODO '.g:today.' Today {'.g:today.'}', 86 | \ 'TODO '.g:today.' Tomorrow {'.g:tomorrow.'}', 87 | \ 'TODO '.g:today.' 2 Days {'.g:day2.'}', 88 | \ 'TODO '.g:today.' 3 Days {'.g:day3.'}', 89 | \ 'TODO '.g:today.' 4 Days {'.g:day4.'}', 90 | \ 'TODO '.g:today.' 7 Days {'.g:day7.'}' 91 | \ ] 92 | 93 | Tasks due in 7 days (:Week command) 94 | 95 | :Week 96 | :close 97 | ? map(getloclist(0), 'v:val.text') == [ 98 | \ 'TODO '.g:today.' Today {'.g:today.'}', 99 | \ 'TODO '.g:today.' Tomorrow {'.g:tomorrow.'}', 100 | \ 'TODO '.g:today.' 2 Days {'.g:day2.'}', 101 | \ 'TODO '.g:today.' 3 Days {'.g:day3.'}', 102 | \ 'TODO '.g:today.' 4 Days {'.g:day4.'}', 103 | \ 'TODO '.g:today.' 7 Days {'.g:day7.'}' 104 | \ ] 105 | 106 | Tasks overdue (\cx command) 107 | 108 | @\cx 109 | :close 110 | ? map(getloclist(0), 'v:val.text') == [ 111 | \ 'TODO '.g:today.' Last Month {'.g:lastmonth.'}', 112 | \ 'TODO '.g:today.' Last Week {'.g:lastweek.'}', 113 | \ 'TODO '.g:today.' Yesterday {'.g:yesterday.'}' 114 | \ ] 115 | 116 | Tasks overdue (:Overdue command) 117 | 118 | :Overdue 119 | :close 120 | ? map(getloclist(0), 'v:val.text') == [ 121 | \ 'TODO '.g:today.' Last Month {'.g:lastmonth.'}', 122 | \ 'TODO '.g:today.' Last Week {'.g:lastweek.'}', 123 | \ 'TODO '.g:today.' Yesterday {'.g:yesterday.'}' 124 | \ ] 125 | 126 | Standard filter command - Note that filter includes DONE tasks 127 | 128 | :Filter Month 129 | :close 130 | ? map(getloclist(0), 'v:val.text') == [ 131 | \ 'TODO '.g:today.' Last Month {'.g:lastmonth.'}', 132 | \ 'DONE '.g:today.' Last Month {'.g:lastmonth.'}' 133 | \ ] 134 | 135 | Clean up 136 | 137 | :call delete("test005.txt") 138 | 139 | vim: ft=vimcram 140 | -------------------------------------------------------------------------------- /doc/todo.txt: -------------------------------------------------------------------------------- 1 | *todo.txt* Vim todo list plugin 2 | 3 | Vim todo list plugin *vimtodo* 4 | 5 | Plugin for managing hierarchical to do lists in vim. 6 | 7 | ============================================================================== 8 | ABOUT *vimtodo-about* 9 | 10 | Vimtodo originally started out as a set of syntax highlights for the todo.txt 11 | (http://www.todotxt.com/) format in vim with a few added extras such as 12 | subtasks. However, it quickly grew into a fully fledged task management 13 | system, taking several ideas from Emacs' org-mode (http://www.orgmode.org/). 14 | 15 | ============================================================================== 16 | INSTALLATION *vimtodo-installation* 17 | 18 | Untar the archive to ~/.vim. If you wish, untar to a temporary directory, and 19 | copy the contents of the autoload/, doc/, ftplugin/ and syntax/ directories to 20 | the respective directories in your ~/.vim directory. 21 | 22 | Alternatively, if you have pathogen installed, untar the entire archive to 23 | ~/.vim/bundle/vimtodo/. 24 | 25 | ============================================================================== 26 | BASIC TODO ENTRIES *vimtodo-basics* 27 | 28 | To start with, open up a new file, and add the following line to the 29 | beginning: > 30 | # vim:ft=todo 31 | 32 | This line tells vim that the file is a vimtodo file. See |modeline| for more 33 | information. Now write the file, quit and reopen it. Alternatively, you can 34 | just type the following to set the filetype without reopening the file: > 35 | :set ft=todo 36 | 37 | To do entries are simply lines in the file that follow a specific format. Add 38 | the following line into the file: > 39 | TODO 2009-09-01 @computer +learnvim Read vim tutorial 40 | 41 | This is a todo entry. You can also add a new entry, with the 'cn' alias. In 42 | insert mode, type 'cn' and a new todo entry along with the current date will 43 | be added. You can also use cn in normal mode to add a new entry. 44 | 45 | The todo entry is made up of several parts: 46 | 47 | TODO - the task status, this is something like TODO, DONE, WAITING 48 | 2009-09-01 - the task creation date 49 | @computer - the context of the task, in this case, something to do at the 50 | computer 51 | +learnvim - the project the task is associated with 52 | 53 | Giving multiple tasks a context or project tag allows you to filter out just 54 | the tasks you are interested in using the filter function (described later). 55 | 56 | For now, press escape to go back to normal mode, make sure the cursor is on 57 | the same line at the todo entry you just added, and press cs (\cs 58 | by default). The task status will change to 'DONE' and the line will be greyed 59 | out. Here, several things have happened: 60 | 61 | - The task status changed from TODO to DONE 62 | - The entire task changes color to show that the task is complete 63 | - A CLOSED: line has been added underneath showing the date and time that 64 | the task was closed. 65 | - A logbook entry has been added (but is currently hidden), logging the 66 | time and date of the task state change. 67 | 68 | A CLOSED: entry is added whenever a task is closed, and will be removed 69 | if a task is re-opened. 70 | 71 | Logbook entries however, log the date and time every time you change the state 72 | of a task, and look like this: > 73 | 74 | :LOGBOOK: 75 | TODO: 2009-09-30 18:19:51 76 | CANCELLED: 2009-09-30 18:19:50 77 | DONE: 2009-09-30 18:12:58 78 | 79 | Currently the todo entry is folded, so move the cursor to the fold line (just 80 | below the todo entry) and press zO to open all the folds. Then move the cursor 81 | back to the todo line and press cs to change the task status a 82 | few times to see the behavior of the closed/logbook lines. 83 | 84 | If desired, the display of closed/logbook lines can be turned off in your 85 | .vimrc. See the configuration section for more details. 86 | 87 | You can add more information to a task using normal text editing commands. 88 | Anything that is indented is considered to be information that is part of a 89 | todo entry. For example, the closed and logbook lines are indented and 90 | considered part of the todo entry. 91 | 92 | A due date for a task can be added. Add the following to the end of the 93 | original todo entry you added earlier: {2009-09-30}. This will be highlighted 94 | just like the task date. If you wish to add the current date, type in ds. For 95 | example {ds} will set a deadline of today. 96 | 97 | If you have tasks with due dates, you can use several commands to view tasks 98 | that are due soon: 99 | 100 | cd - Show tasks due today 101 | cf - Show tasks due tomorrow 102 | cw - Show tasks due within 7 days 103 | cx - Show overdue tasks (tasks that were due sometime in the past 104 | year) 105 | 106 | Each of these opens up another buffer listing the matching entries. Pressing 107 | enter on one of the items in the list will take you to the corresponding 108 | entry. Try this - change the deadline for your task to today, and type 109 | cd. 110 | 111 | You can filter on other criteria too, such as context or project using the 112 | :Filter ex command. It takes a regular expression and will show matching 113 | tasks. For example: > 114 | 115 | :Filter @home 116 | 117 | which would bring up all tasks with a context of @home. 118 | 119 | ============================================================================== 120 | TASK STATES *vimtodo-state* *vimtodo-taskstate* *vimtodo-taskstates* 121 | 122 | The first word of a task in all caps shows the tasks state. Normally it is is 123 | something like TODO or DONE, but the available states can be configured as 124 | needed. 125 | 126 | Task states can be changed in one of two ways: The cs normal mode 127 | command, and the cv normal mode command. 128 | 129 | cs will cycle through the task states (by default, TODO, DONE, 130 | CANCELLED) See |vimtodo-stateprogression| for more information on this. 131 | 132 | cv will bring up a prompt asking you to pick which state you want to 133 | switch to. Press the letter associated with the state to immediately change 134 | the task to that state. 135 | 136 | Some task states are considered "done" states. In these states, the entire 137 | task is highlighted in the same color (as if it was a comment) and a CLOSED 138 | tag is added to the task to show the date and time the task was closed. 139 | 140 | In addition to the closed task, whenever a tasks state is changed, the state 141 | change is appended to the task in a LOGBOOK section (or "drawer"). This is an 142 | indented part of the task with one line for each state change. 143 | 144 | The closed/logbook behavior can be configured in your .vimrc using the 145 | 'g:todo_log_done' and 'g:todo_log_drawer' settings. Alternatively, you can set 146 | this behavior on a per file basis using the LOGDONE and LOGDRAWER properties. 147 | See |vimtodo-config| for more information on these settings. 148 | 149 | STATE PROGRESSION *vimtodo-stateprogression* 150 | 151 | When using cs to change between task states, the state will cycle 152 | between succesive states in the progression, and back to the beginning if the 153 | final state is reached. The progression can be configured, but the default 154 | states are: 155 | 156 | TODO -> DONE -> CANCELLED 157 | WAITING -> CLOSED 158 | 159 | If you wish to change to a state that is on a different progression (e.g. from 160 | TODO to WAITING), then you can use the cv command to jump direct 161 | to that state. 162 | 163 | ============================================================================== 164 | ARCHIVING *vimtodo-archive* *vimtodo-archiving* 165 | 166 | VimTODO can move all completed tasks to another file to reduce clutter. The 167 | ca command is used for this. Any task that has been closed will 168 | be moved to the done file, which by default is 'done.txt' in the same 169 | directory as the todo file. 170 | 171 | The name of the done file can be changed using the g:todo_done_file .vimrc 172 | setting or on a per-file basis using the DONEFILE property. 173 | 174 | ============================================================================== 175 | CHECKBOXES *vimtodo-checkboxes* 176 | 177 | In addition to tasks with a given state, Vimtodo can manage checkboxes. Any 178 | line in a file can contain a checkbox. It doesn't have to be a task heading, 179 | and in fact it probably isn't a good idea to mix task entries (with a state) 180 | and checkboxes. 181 | 182 | To create a checkbox, simply type [ ] in insert mode. Alternatively, you can 183 | use cb in normal mode to add a checkbox to the beginning of a 184 | line. Note that if you do this on the header line for a task, it will be 185 | inserted before the task state (e.g. TODO) and the task will lose any special 186 | meaning. 187 | 188 | To toggle a checkbox, use the cc command. By default, a checkbox 189 | will be checked with an X, and another use of cc will uncheck the 190 | box. However, like task states, there are a number of states a checkbox can 191 | cycle through: > 192 | 193 | [ ] -> [X] 194 | [+] -> [-] -> [.] 195 | [Y] -> [N] -> [?] 196 | 197 | To use one of these other progressions, simply start with the relevant state 198 | when creating your checkbox. For example, type [Y] in insert mode to create a 199 | Y/N/? check box. 200 | 201 | Again, like task states, checkbox state progression can be configured. The 202 | g:todo_checkbox_states variable and the CHECKBOXSTATES property controls this 203 | behavior. 204 | 205 | ============================================================================== 206 | TASK LINKS *vimtodo-tasklinks* *vimtodo-links* 207 | 208 | Vimtodo can be configured to reference an external task management system. By 209 | adding tidXXXX to your task, you can use ct to open up a web page 210 | showing the external task. 211 | 212 | For example: 213 | 214 | You have an external task management system where all tickets are available on 215 | the web at the following URL: http://tasks.example.com/tickets/tid=12345 (for 216 | ticket #12345) 217 | 218 | Set up the g:todo_taskurl variable in your .vimrc to be the same as the above 219 | url, substituting '%s' for the ticket number. In addition, you need to set the 220 | g:todo_browser variable to be a command to load a web page in your browser. In 221 | the example below, gnome-open is used to open the default browser (If you are 222 | using Linux/Gnome): > 223 | 224 | let g:todo_taskurl="http://tasks.example.com/tickets/tid=%s" 225 | let g:todo_browser="gnome-open" 226 | 227 | You wish to reference this ticket in a TODO entry, so you add tid12345 228 | to the ticket. At this point, ct will open up your web browser 229 | and take you to the referenced ticket. 230 | 231 | Vimtodo can also open any URL in a web browser if the g:todo_browser variable 232 | is configured. To do this, use cl and any http/https link on the 233 | current line will be opened in the web browser. 234 | 235 | ============================================================================== 236 | FOLDING *vimtodo-folding* 237 | 238 | Any extra data added to an entry (be it the logbook/closed tags, or notes on a 239 | task) is indented from the first line, and is folded away when the file is 240 | first opened using vim's folding features. Folding is based on the indentation 241 | of the text. 242 | 243 | All of vim's normal folding commands can be used to manipulate what is 244 | hidden/shown. For a good overview on this, see |fold-commands|. However, the 245 | basic commands used to open/close folds are |zo| and |zc| (both normal mode 246 | commands). 247 | 248 | ============================================================================== 249 | TIME SPENT ON TASKS *vimtodo-timespent* 250 | 251 | Vimtodo has limited support for logging the time spent on tasks. For each 252 | subtask in a todo entry, you can add the time spent tag that looks something 253 | like: [1.5h] (for 1.5 hours spent on the task). 254 | 255 | Vimtodo can then total up the time spent on each subtask and display the total 256 | in the top level task. The command to update the totals is ce, 257 | which will create or update a TIMETOTAL property inside the INFO drawer on the 258 | top level task. 259 | 260 | In addition to the normal mode command, the ex command :UpdateTimeTotal is 261 | provided, which will allow you to automate the updating as desired. One option 262 | is to update the totals just before saving the file with an autocommand. The 263 | following example is something you could add in ~/.vim/after/ftplugin/todo.vim 264 | which would automatically update the times whenever a todo file is written: > 265 | 266 | au BufWrite :UpdateTimeTotal 267 | 268 | ============================================================================== 269 | CONFIGURATION *vimtodo-config* *vimtodo-configuration* 270 | 271 | Much of vimtodo's behavior can be changed if desired. There are two options 272 | for configuration: variables in .vimrc and properties. 273 | 274 | PROPERTIES *vimtodo-properties* 275 | 276 | Properties are simply per-file configuration options that you add to the 277 | beginning of a todo file. They are all contained in a :SETTINGS: drawer, 278 | usually near the top of the file, and each setting begins with a + sign: 279 | For example: > 280 | 281 | :SETTINGS: 282 | +DONEFILE: custom_done_file.txt 283 | +LOGDONE: 0 284 | 285 | CONFIGURATION OPTIONS *vimtodo-configoptions* 286 | 287 | g:todo_checkbox_states (property: +CHECKBOXSTATES) 288 | 289 | Sets the list of checkbox state progressions. 290 | 291 | If set in the vimrc file, this is a list of valid checkbox progressions, 292 | each progression of which is itself a list. To set multiple checkbox 293 | progressions using properties, just use multiple +CHECKBOXSTATES lines. 294 | 295 | Examples (vimrc first, then properties example below): > 296 | 297 | let g:todo_checkbox_states = [ 298 | \["A", "B", "C"], 299 | \["1", "2", "3"]] 300 | 301 | :SETTINGS: 302 | +CHECKBOXSTATES: A B C 303 | +CHECKBOXSTATES: 1 2 3 304 | 305 | g:todo_done_file (property: +DONEFILE) 306 | 307 | Set the name of the file to archive done tasks into. (Default: done.txt) 308 | 309 | g:todo_log_done (property: +LOGDONE) 310 | 311 | Enable/disable logging of the time a task is done with the CLOSED: tag. 312 | Set to 1 to enable logging, 0 to disable. (Default: 1) 313 | 314 | g:todo_log_into_drawer (property: +LOGDRAWER) 315 | 316 | Set the name of the drawer to log state changes into. If blank, then don't 317 | log state changes into a drawer. (Default: LOGBOOK) 318 | 319 | g:todo_states (property: +STATES) 320 | 321 | Set a custom list of valid task states. 322 | 323 | If set in the vimrc file, this is a list of valid state progressions, each 324 | progression of which is itself a list. To set multiple state progressions 325 | using properties, just use multiple +STATES lines. 326 | 327 | If '|' is included in a given state progression, it separates normal 328 | states from "done" states. If '|' is not present, then all states in that 329 | progression are normal states. To have a progression made entirely of done 330 | states, put '|' as the first entry in the list. 331 | 332 | Each state should be in all caps (e.g. TODO). An optional shortcut key 333 | (for use with cv) can be added in parentheses after the state 334 | (e.g. "TODO(t)"). 335 | 336 | To set the colors for each state, see the g:todo_state_colors option. 337 | 338 | Examples (vimrc first, then properties example below): > 339 | 340 | let g:todo_states=[['TODO(t)', '|', 'DONE(d)', 'CANCELLED(c)'], 341 | \['WAITING(w)', 'HOLD(h)', 'INPROGRESS(i)', 'SOMEDAY(s)', 'CLOSED(l)']] 342 | 343 | :SETTINGS: 344 | +STATES: TODO(t) | DONE(d) CANCELLED(c) 345 | +STATES: WAITING(w) HOLD(g) INPROGRESS(i) SOMEDAY(s) CLOSED(l) 346 | 347 | g:todo_state_colors (property: +STATECOLORS) 348 | 349 | Set the highlight colors for each state. 350 | 351 | This is a map from state names to colors. Any color name recognized by vim 352 | can be used here. Standard colors such as 'Red', 'Blue', 'Green', 'Grey' 353 | are all recognized. 354 | 355 | When using the +STATECOLORS property, use a colon to separate the state 356 | name from the color, separate each state/color pair with a comma, and use 357 | multiple property lines if required. 358 | 359 | Examples (vimrc first, then properties example below): > 360 | 361 | let g:todo_state_colors= { 362 | \'DONE': 'Green', 363 | \'CLOSED': 'Grey', 364 | \'CANCELLED': 'Red', 365 | \'TODO': 'Blue', 366 | \'WAITING': 'Yellow', 367 | \'HOLD': 'Grey', 368 | \'INPROGRESS': 'Cyan', 369 | \'SOMEDAY': 'Grey' 370 | \} 371 | 372 | :SETTINGS: 373 | +STATECOLORS: DONE:Green, CLOSED:Grey, CANCELLED:Red, TODO:Blue 374 | +STATECOLORS: WAITING:Yellow, HOLD:Grey, INPROGRESS:Cyan 375 | +STATECOLORS: SOMEDAY:Grey 376 | 377 | g:todo_taskurl (property: +TASKURL) 378 | 379 | Sets the url for referencing external task manager tickets using tidXXXX 380 | format in an entry. 381 | 382 | Any occurence of %s in the URL will be replaced with the id of the ticket 383 | when ct is used. 384 | 385 | Default: blank (ct does nothing) 386 | 387 | g:todo_browser (property: +BROWSER) 388 | 389 | Sets the command to use when loading a url or external ticket. The command 390 | is executed with a single parameter - the URL to load in the browser. 391 | 392 | If you are running GNOME, then 'gnome-open' is a good choice, as it will 393 | load your default browser. Likewise, Mac users can use 'open' for this. If 394 | you want a specific browser to open, you can specify that instead. 395 | 396 | Default: blank (any commands that require this will have no effect) 397 | 398 | CUSTOM PROPERTIES *vimtodo-customproperties* 399 | 400 | If you wish, you can define custom properties in the settings drawer to allow 401 | other configuration options to be set inside todo files. To do this, you can 402 | set the g:todo_property_vars, and optionally, the g:todo_property_types. For 403 | example: > 404 | 405 | let g:todo_property_vars={ 406 | \'FOO': 'g:todo_foo' 407 | \'BAR': 'g:todo_bar' 408 | \} 409 | let g:todo_property_types={ 410 | \'BAR': 'dict' 411 | \} 412 | 413 | This is mostly a developer feature. You probably won't need it during normal 414 | use. 415 | 416 | ============================================================================== 417 | TROUBLESHOOTING *vimtodo-troubleshooting* 418 | 419 | When I load a todo file (or set ft=todo), the syntax coloring shows up, but 420 | none of the commands seem to work. 421 | 422 | Make sure you have filetype plugins enabled in your vim config. This can 423 | be done by adding 'filetype plugin on' to your .vimrc file. See 424 | |:filetype-plugin-on| for more details. 425 | 426 | ============================================================================== 427 | REPORTING BUGS AND FEATURE REQUESTS *vimtodo-bugs* 428 | 429 | Vimtodo uses github for bug tracking. Go to 430 | http://github.com/mivok/vimtodo/issues to report any issues. 431 | 432 | The latest version of the script is always available on github: 433 | 434 | http://github.com/mivok/vimtodo 435 | 436 | ============================================================================== 437 | vim:ft=help:tw=78 438 | -------------------------------------------------------------------------------- /ftplugin/todo.vim: -------------------------------------------------------------------------------- 1 | " Vim filetype plugin for heirarchical TODO lists 2 | " Maintainer: Mark Harrison 3 | " Last Change: Nov 27, 2010 4 | " License: ISC - See LICENSE file for details 5 | 6 | " This file has folded functions - Use zR to show all source code if you 7 | " aren't familiar with folding in vim. 8 | 9 | " Only load if we haven't already {{{1 10 | if exists("b:did_ftplugin") 11 | finish 12 | endif 13 | let b:did_ftplugin = 1 14 | "1}}} 15 | " Make sure we aren't running in compatible mode {{{1 16 | let s:save_cpo = &cpo 17 | set cpo&vim 18 | "1}}} 19 | 20 | " Utility Functions 21 | " s:Map - mapping helper function {{{1 22 | function! s:Map(keys, funcname) 23 | if !hasmapto('Todo'.a:funcname) 24 | exe "map ".a:keys. 25 | \" Todo".a:funcname 26 | endif 27 | exe "noremap