Skip to content

Commit

Permalink
Automatic completion of @tags inside notes (suggested by Lukas Muehle…
Browse files Browse the repository at this point in the history
…thaler)
  • Loading branch information
xolox committed Jul 9, 2011
1 parent 215fd1c commit 74e8455
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 4 deletions.
10 changes: 9 additions & 1 deletion README.md
Expand Up @@ -13,7 +13,7 @@ The notes.vim plug-in for the [Vim text editor] [vim] makes it easy to manage yo
* A [Python 2] [python] script is included that accelerates keyword searches using an [SQLite] [sqlite] database
* The `:RecentNotes` command lists your notes by modification date, starting with the most recently edited note
* **Navigating between notes:** The included file type plug-in redefines [gf] [gf] to jump between notes and the syntax script highlights note names as hyper links
* **Writing aids:** The included file type plug-in contains mappings for automatic curly quotes, arrows and list bullets and supports completion of note titles using Control-X Control-U
* **Writing aids:** The included file type plug-in contains mappings for automatic curly quotes, arrows and list bullets and supports completion of note titles using Control-X Control-U and completion of tags using Control-X Control-O
* **Embedded file types:** The included syntax script supports embedded highlighting using blocks marked with `{{{type … }}}` which allows you to embed highlighted code and configuration snippets in your notes

Here's a screen shot of the syntax mode using the [slate] [slate] color scheme:
Expand Down Expand Up @@ -80,6 +80,14 @@ When you execute this command it will start a new note with the selected text as

The `:DeleteNote` command deletes the current note, destroys the buffer and removes the note from the internal cache of filenames and note titles. This fails when changes have been made to the current buffer, unless you use `:DeleteNote!` which discards any changes.

### The `:IndexTaggedNotes` command

The notes plug-in defines an omni completion function that can be used to complete the names of tags. To trigger the omni completion you type Control-X Control-O. When you type `@` in insert mode the plug-in will automatically start omni completion.

The completion menu is populated from a text file listing all your tags, one on each line. The first time omni completion triggers, an index of tag names is generated and saved to the location set by `g:notes_tagsindex`. To update this tags index you need to execute the `:IndexTaggedNotes` command.

If you execute this command with a bang as in `:IndexTaggedNotes!` it wil open a split window with a cross reference of all the tags you've used and the files in which each tag has been used.

### The `:SearchNotes` command

This command wraps [:vimgrep] [vimgrep] and enables you to search through your notes using one or more keywords or a regular expression pattern. To search for a pattern you pass a single argument that starts/ends with a slash:
Expand Down
78 changes: 78 additions & 0 deletions autoload/xolox/notes.vim
Expand Up @@ -174,6 +174,84 @@ function! xolox#notes#user_complete(findstart, base) " {{{1
endif
endfunction

function! xolox#notes#omni_complete(findstart, base) " {{{1
if a:findstart
" For now we assume omni completion was triggered by the mapping for
" automatic tag completion. Eventually it might be nice to check for a
" leading "@" here and otherwise make it complete e.g. note names, so that
" there's only one way to complete inside notes and the plug-in is smart
" enough to know what the user wants to complete :-)
return col('.') - 1
else
let fname = expand(g:notes_tagsindex)
if !filereadable(fname)
return xolox#notes#index_tagged_notes(0)
else
return readfile(fname)
endif
endif
endfunction

function! xolox#notes#index_tagged_notes(verbose) " {{{1
let starttime = xolox#misc#timer#start()
let notes = xolox#notes#get_fnames()
let num_notes = len(notes)
let known_tags = {}
for idx in range(len(notes))
let fname = notes[idx]
call xolox#misc#msg#info("notes.vim %s: Scanning note %i of %i: %s", g:notes_version, idx + 1, num_notes, fname)
let text = join(readfile(fname), "\n")
" Strip code blocks from the text.
let text = substitute(text, '{{{\w\+\_.\{-}}}}', '', 'g')
for token in filter(split(text), 'v:val =~ "^@"')
" Strip any trailing punctuation.
let token = substitute(token, '[[:punct:]]*$', '', '')
if token != ''
if !a:verbose
let known_tags[token] = 1
else
" Track the origins of tags.
if !has_key(known_tags, token)
let known_tags[token] = {}
endif
let known_tags[token][fname] = 1
endif
endif
endfor
endfor
" Save the index of known tags as a text file.
let fname = expand(g:notes_tagsindex)
let tagnames = keys(known_tags)
call sort(tagnames, 1)
if writefile(tagnames, fname) != 0
call xolox#misc#msg#warn("notes.vim %s: Failed to save tags index as %s!", g:notes_version, fname)
else
call xolox#misc#timer#stop('notes.vim %s: Indexed tags in %s.', g:notes_version, starttime)
endif
if !a:verbose
return tagnames
endif
" If the user executed :IndexTaggedNotes! we show them the origins of tags,
" because after the first time I tried the :IndexTaggedNotes command I was
" immediately wondering where all of those false positives came from... This
" doesn't give a complete picture (doing so would slow down the indexing
" and complicate this code significantly) but it's better than nothing!
let lines = ['All tags', '', printf("You have used %i tags in your notes, they're listed below.", len(known_tags))]
let bullet = xolox#notes#insert_bullet('*')
for tagname in tagnames
call extend(lines, ['', '# ' . tagname, ''])
let fnames = keys(known_tags[tagname])
let titles = map(fnames, 'xolox#notes#fname_to_title(v:val)')
call sort(titles, 1)
for title in titles
call add(lines, ' ' . bullet . ' ' . title)
endfor
endfor
vnew
call setline(1, lines)
setlocal ft=notes nomod
endfunction

function! xolox#notes#save() abort " {{{1
" When the current note's title is changed, automatically rename the file.
if &filetype == 'notes'
Expand Down
20 changes: 19 additions & 1 deletion doc/notes.txt
Expand Up @@ -43,7 +43,8 @@ notes in Vim:

- Writing aids: The included file type plug-in contains mappings for automatic
curly quotes, arrows and list bullets and supports completion of note
titles using Control-X Control-U
titles using Control-X Control-U and completion of tags using Control-X
Control-O

- Embedded file types: The included syntax script supports embedded
highlighting using blocks marked with '{{{type … }}}' which allows you to
Expand Down Expand Up @@ -159,6 +160,23 @@ removes the note from the internal cache of filenames and note titles. This
fails when changes have been made to the current buffer, unless you use
':DeleteNote!' which discards any changes.

-------------------------------------------------------------------------------
The *:IndexTaggedNotes* command

The notes plug-in defines an omni completion function that can be used to
complete the names of tags. To trigger the omni completion you type Control-X
Control-O. When you type '@' in insert mode the plug-in will automatically
start omni completion.

The completion menu is populated from a text file listing all your tags, one
on each line. The first time omni completion triggers, an index of tag names
is generated and saved to the location set by 'g:notes_tagsindex'. To update
this tags index you need to execute the |:IndexTaggedNotes| command.

If you execute this command with a bang as in ':IndexTaggedNotes!' it wil open
a split window with a cross reference of all the tags you've used and the
files in which each tag has been used.

-------------------------------------------------------------------------------
The *:SearchNotes* command

Expand Down
10 changes: 9 additions & 1 deletion ftplugin/notes.vim
@@ -1,6 +1,6 @@
" Vim file type plug-in
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 8, 2011
" Last Change: July 9, 2011
" URL: http://peterodding.com/code/vim/notes/

if exists('b:did_ftplugin')
Expand Down Expand Up @@ -51,6 +51,14 @@ let b:undo_ftplugin .= ' includeexpr<'
setlocal completefunc=xolox#notes#user_complete
let b:undo_ftplugin .= ' completefunc<'

" Enable completion of tag names using C-x C-o. {{{1
setlocal omnifunc=xolox#notes#omni_complete
let b:undo_ftplugin .= ' omnifunc<'

" Automatic completion of tag names after typing "@". {{{1
inoremap <buffer> <silent> @ <C-x><C-o>
let b:undo_ftplugin .= ' | execute "iunmap <buffer> @"'

" Change double-dash to em-dash as it is typed. {{{1
if xolox#notes#unicode_enabled()
imap <buffer> --
Expand Down
8 changes: 7 additions & 1 deletion plugin/notes.vim
Expand Up @@ -11,7 +11,7 @@ if &cp || exists('g:loaded_notes')
finish
endif

let g:notes_version = '0.9.5'
let g:notes_version = '0.10'

" Make sure the default paths below are compatible with Pathogen.
let s:plugindir = expand('<sfile>:p:h') . '/../misc/notes'
Expand Down Expand Up @@ -41,13 +41,19 @@ if !exists('g:notes_suffix')
let g:notes_suffix = ''
endif

" Define the default location for the tag name index (used for completion).
if !exists('g:notes_tagsindex')
let g:notes_tagsindex = s:plugindir . '/tags.txt'
endif

" User commands to create, delete and search notes.
command! -bar -bang -nargs=? -complete=customlist,xolox#notes#cmd_complete Note call xolox#notes#edit(<q-bang>, <q-args>)
command! -bar -bang -range NoteFromSelectedText call xolox#notes#from_selection(<q-bang>)
command! -bar -bang DeleteNote call xolox#notes#delete(<q-bang>)
command! -bang -nargs=? SearchNotes call xolox#notes#search(<q-bang>, <q-args>)
command! -bar -bang RelatedNotes call xolox#notes#related(<q-bang>)
command! -bar -bang -nargs=? RecentNotes call xolox#notes#recent(<q-bang>, <q-args>)
command! -bar -bang IndexTaggedNotes call xolox#notes#index_tagged_notes(<q-bang> == '!')

" Automatic commands to enable the :edit note:… shortcut and load the notes file type.

Expand Down

0 comments on commit 74e8455

Please sign in to comment.