Commits

khorser committed 6523b2d

Initial checkin

Comments (0)

Files changed (3)

autoload/qfnotes.vim

+" qfnotes.vim
+" Create file notes in quickfix format
+" Last Change: $HGLastChangedDate$
+" Maintainer: Sergey Khorev <sergey.khorev@gmail.com>
+" Based on qfn.vim by Will Drewry <redpig@dataspill.org>: http://www.vim.org/scripts/script.php?script_id=2216
+" License: See qfnotes.txt packaged with this file.
+
+if exists("g:loaded_qfnotes_auto")
+  finish
+endif
+let g:loaded_qfnotes_auto = 1
+
+let s:save_cpo = &cpo
+
+set cpo&vim
+
+let s:qfbuff = -1
+
+function s:QFXGetDefaultName()
+  if exists('g:QFXDefaultFileName')
+    if empty(g:QFXDefaultFileName)
+      return &errorfile
+    else
+      return g:QFXDefaultFileName
+    endif
+  else
+    return 'quickfix.err'
+  endif
+endfunction
+
+let s:NonSenseComment = '!@#$%^{edf341f1-d270-4f35-a04f-cce6e3dd78ce}&*()-='
+
+function s:QFXInput(prompt, default)
+  if exists('g:QFXUseDialog') && g:QFXUseDialog
+    let text = inputdialog(a:prompt, a:default, s:NonSenseComment)
+    if text == s:NonSenseComment
+      return ''
+    endif
+  else
+    return input(a:prompt, a:default)
+  endif
+endfunction
+
+function s:QFXList2Lines(list)
+  return map(copy(a:list), 'join([bufname(v:val.bufnr), v:val.lnum, v:val.col, v:val.text], ":")')
+endfunction
+
+function s:QFXSetupBuff()
+  set bufhidden=hide
+  set nobuflisted
+  let s:qfbuff = bufnr('%')
+  augroup QFX
+    " remove autocmd if another qf buffer existed
+    autocmd!
+    " updating quickfix window on each save
+    autocmd BufWritePost <buffer> exec 'cgetbuffer' expand('<abuf>')
+  augroup END
+
+  "remove the autocmd on switching to another qf buffer
+endfunction
+
+function s:QFXSyncBuff()
+  if s:qfbuff <= 0
+    exec 'silent keepalt new' fnameescape(s:QFXGetDefaultName())
+    call s:QFXSetupBuff()
+  else
+    exec 'silent keepalt sbuffer' s:qfbuff
+    silent 1,$del _
+  endif
+  call setline(1, s:QFXList2Lines(getqflist()))
+  silent keepalt hide
+endfunction
+
+" set QF list, open QF window, and position at pos-th error
+function s:QFXSetList(list, action, pos)
+  call setqflist(a:list, a:action)
+  let len = len(getqflist())
+  if a:pos < 0 || a:pos >= len
+    let pos = len - 1
+  else
+    let pos = a:pos
+  endif
+  if &buftype == 'quickfix'
+    let return2qf = 1
+  else
+    let return2qf = 0
+  endif
+  copen
+  if pos >= 0
+    exec 'cc' (pos + 1)
+  endif
+  if return2qf
+    copen
+  endif
+  call s:QFXSyncBuff()
+endfunction
+
+function qfnotes#QFXAddQ()
+  if &buftype != 'quickfix'
+    let txt = s:QFXInput('Enter note: ', '')
+    if !empty(txt)
+      call qfnotes#QFXAdd(txt)
+    endif
+  endif
+endfunction
+
+" add support for different note types?
+function qfnotes#QFXAdd(note)
+  if a:note == ''
+    return
+  endif
+  call s:QFXSetList(
+	\[{'bufnr': bufnr('%'), 'lnum': line('.'), 'col': col('.'), 'text': a:note}],
+	\'a', -1)
+endfunction
+
+function qfnotes#QFXSave(force, ...)
+  if a:0 > 0
+    let file = a:1
+  else
+    let file = ''
+  endif
+
+  if s:qfbuff > 0
+    exec 'silent keepalt sbuffer' s:qfbuff
+    if empty(file)
+      exec 'silent noautocmd w' . (a:force ? '!' : '')
+    else
+      exec 'silent noautocmd w' . (a:force ? '! ' : ' ') . fnameescape(file)
+    endif
+    silent keepalt hide
+  elseif empty(getqflist())
+    echoerr 'No quickfix entries found'
+  else
+    echoerr 'Internal error: no qf buffer found but qf list is not empty'
+  endif
+endfunction
+
+function qfnotes#QFXSaveRange(force, file) range
+  call s:QFXSavePosn()
+  try
+    if &buftype != 'quickfix'
+      let lines = filter(getqflist(),
+	    \ 'v:val.bufnr == bufnr("%") && v:val.lnum >= a:firstline && v:val.lnum <= a:lastline')
+    else
+      let lines = getqflist()[a:firstline - 1: a:lastline - 1]
+    endif
+
+    if !a:force && filereadable(a:file)
+      if &confirm
+	if confirm('File ' . a:file . ' exists. Overwrite?', "&Yes\n&No") > 1
+	  return
+	endif
+      else
+	echoerr 'QuickFixNotes: file' a:file 'already exists'
+	return
+      endif
+    endif
+
+    call writefile(s:QFXList2Lines(lines), a:file)
+  finally
+    call s:QFXRestorePosn()
+  endtry
+endfunction
+
+function! s:GetBufNrAndLine()
+  if &buftype != 'quickfix'
+    return [bufnr('%'), line('.')]
+  else
+    let qfentry = getqflist()[line('.') - 1]
+    return [qfentry.bufnr, qfentry.lnum]
+  endif
+endfunction
+
+function qfnotes#QFXDelete()
+  let [bufnr, line] = s:GetBufNrAndLine()
+  let modified = 0
+  let qflist = getqflist()
+  let idx = 0
+  let lastmodidx = -1
+  for i in qflist
+    if bufnr == i.bufnr && line == i.lnum
+      call remove(qflist, idx)
+      let modified = 1
+      let lastmodidx = idx
+    endif
+    let idx += 1
+  endfor
+  if modified
+    call s:QFXSetList(qflist, 'r', lastmodidx)
+  endif
+endfunction
+
+function qfnotes#QFXEdit(inbuffer)
+  let [bufnr, line] = s:GetBufNrAndLine()
+  let modified = 0
+  let qflist = getqflist()
+  let idx = 0
+  let lastmodidx = -1
+  let found = 0
+
+  for i in qflist
+    if bufnr == i.bufnr && line == i.lnum
+      let found = 1
+      if a:inbuffer
+	if &buftype == 'quickfix'
+	  " leaving quickfix window
+	  exec (idx + 1) . 'cc'
+	endif
+	call s:QFXOpen()
+	exec 'normal' ((idx + 1) . 'G')
+	return
+      else
+	let inp = s:QFXInput('Enter new comment: ', i.text)
+	if !empty(inp)
+	  let i.text = inp
+	  let modified = 1
+	  let lastmodidx = idx
+	endif
+      endif
+    endif
+    let idx += 1
+  endfor
+  if modified
+    call s:QFXSetList(qflist, 'r', lastmodidx)
+  elseif !found
+    if a:inbuffer " simply open notes buffer
+      if !empty(qflist)
+	exec '.cc'
+      endif
+      call s:QFXOpen()
+    else " not found => adding new note
+      call qfnotes#QFXAddQ()
+    endif
+  endif
+endfunction
+
+function qfnotes#QFXLoad(...)
+  if a:0 > 0
+    let file = a:1
+    if a:0 > 1
+      let dir = a:2
+    else
+      let dir = ''
+    endif
+  else
+    let file = s:QFXGetDefaultName()
+    let dir = ''
+  endif
+
+  exec 'silent keepalt new' fnameescape(file)
+  call s:QFXSetupBuff()
+  if line('$') == 1 && getline(1) =~ '\m^\s*$'
+    let bufempty = 1
+  else
+    let bufempty = 0
+  endif
+  silent keepalt hide
+
+  let save_cwd = getcwd()
+  let save_ef = &ef
+  let save_efm = &efm
+  try
+    set efm&
+    if !empty(dir)
+      exec 'silent cd' dir
+    endif
+    if !bufempty
+      exec 'silent cbuffer' s:qfbuff
+    endif
+    copen
+  finally
+    let &ef = save_ef
+    let &efm = save_efm
+    if !empty(dir)
+      exec 'silent cd' fnameescape(save_cwd)
+    endif
+  endtry
+endfunction
+
+function s:QFXOpen()
+  if s:qfbuff > 0
+    exec ':buffer' s:qfbuff
+  else
+    exec ':e' s:QFXGetDefaultName()
+    call s:QFXSetupBuff()
+  endif
+endfunction
+
+function qfnotes#QFXNew(...)
+  if a:0 > 0
+    let file = a:1
+  else
+    let file = s:QFXGetDefaultName()
+  endif
+  exec ':silent keepalt new' file
+  call s:QFXSetupBuff()
+  silent keepalt hide
+  call setqflist([], ' ')
+endfunction
+
+" code from netrw plugin to save and restore current position
+function! s:QFXRestorePosn(...)
+  let eikeep = &ei
+  set ei=all
+
+  if a:0 > 0
+    exe a:1
+  endif
+
+  " restore window
+  if exists('w:QFX_winnr')
+    exe 'silent! '.w:QFX_winnr.'wincmd w'
+  endif
+  " restore top-of-screen line
+  if exists('w:QFX_hline')
+    exe 'norm! '.w:QFX_hline."G0z\<CR>"
+  endif
+  " restore position
+  if exists('w:QFX_line') && exists('w:QFX_col')
+    exe 'norm! '.w:QFX_line.'G0'.w:QFX_col."\<bar>"
+  endif
+
+  let &ei = eikeep
+endfunction
+
+function! s:QFXSavePosn()
+  " Save current line and column
+  let w:QFX_winnr = winnr()
+  let w:QFX_line = line('.')
+  let w:QFX_col = virtcol('.')
+  " Save top-of-screen line
+  norm! H0
+  let w:QFX_hline = line('.')
+  " set up string holding position parameters
+  let ret = 'let w:QFX_winnr='.w:QFX_winnr.'|let w:QFX_line='.w:QFX_line.'|let w:QFX_col='.w:QFX_col.'|let w:QFX_hline='.w:QFX_hline
+
+  call s:QFXRestorePosn()
+  return ret
+endfunction
+
+let &cpo = s:save_cpo
+
+" vim: set ft=vim ts=8 sts=2 sw=2:
+*qfnotes.txt*	Plugin for external file annotation
+
+Author: Sergey Khorev(sergey.khorev AT gmail DOT com)
+Based on the work of Will Drewry (redpig AT dataspill DOT org)
+For Vim version 7.2 and above
+$HGLastChangedDate$
+
+1. Overview 					|qfnotes-intro|
+2. Requirements					|qfnotes-requirements|
+3. Installation 				|qfnotes-install|
+4. Usage 					|qfnotes-using|
+5. Options 					|qfnotes-options|
+6. Commands 					|qfnotes-commands|
+7. Default Key Mappings				|qfnotes-mappings|
+8. License 					|qfnotes-license|
+9. Todo						|qfnotes-todo|
+
+==============================================================================
+							       *qfnotes-intro*
+1. Overview~
+
+QFnotes is a plugin for Vim that allows file annotation based on |quickfix|
+functionality. In particular, this plugin allows the user to tie comments to
+a specific source file, line number, and column number without modifying the
+file being reviewed.
+
+The goal of the plugin is to provide a simple and useful
+mechanism for tracking notes when reviewing any sort of text file -- from
+documents and book drafts to source code and configuration files.
+There are many instances where placing comments into the file being reviewed
+is less practical.
+
+Also it may be used as a generic |quickfix| window editor.
+
+
+==============================================================================
+							*qfnotes-requirements*
+2. Requirements~
+
+The plugin requires Vim version 7.2 and above
+
+It will work on all the platforms where Vim is supported and |quickfix| support
+is enabled.
+
+
+==============================================================================
+							     *qfnotes-install*
+3. Installation~
+
+1. You need sufficiently recent |vimball|
+2. Run:
+>
+		vim qfnotes.vmb
+<
+3. Execute the following ex command:
+>
+		:so %
+<
+4. You should now be able to bind qfnotes bindings (starting with <Plug>QuickFix)
+to your preferred key combinations.  You can use the ":help qfnotes" command at
+any time to get more information.
+
+To uninstall the plugin, you only need to execute
+>
+		:RmVimball qfnotes
+<
+If it does not work for some reason, remove the plugin/qfnotes.vim and
+doc/qfnotes.txt files manually.
+
+==============================================================================
+							       *qfnotes-using*
+4. Usage~
+
+The plugin is meant to be used during some sort of file review.  If you are
+reading a document, reviewing source code, or anything else where having a
+scratch pad for notes associated with a file and line number is useful.
+
+
+Creating a new note~
+
+With default |qfnotes-mappings| you may press \qn on a line you'd like to
+comment. You'll be prompted for your note. Type it in, press enter, and you're
+done.
+
+Viewing your notes~
+
+If you'd like to see the notes as they are being taken, simply use the normal
+|quickfix| commands.  For example, |copen| will open the |quickfix| window.
+You can customize it in any way that is normally allowed.
+
+You can also open the |quickfix| window on startup using the following command
+line:
+>
+		$ vim +copen
+<
+
+Saving your notes~
+
+If you're taking the time to make these notes, you may also want to keep them
+for longer than just the time Vim is running.
+Default |qfnotes-mappings| allow pressing of \qs to save notes to a file
+determined by |g:QFXDefaultFileName| variable.
+To customise file name and saving ranges see |:QFXSave| and |:QFXSaveRange|
+
+Loading a note~
+
+|:QFXLoad| command may be used to load notes. Default mapping allows
+use of \ql to load a file with default name from the current directory
+
+Alternatively, you may use normal |quickfix| commands like |:cfile| to
+load your notes. If Vim cannot parse the file, try setting 'errorformat'
+to its default value:
+>
+		set errorformat&
+<
+
+Editing and deleting a note~
+
+To delete a comment you may press \qd in the source or |quickfix| window:
+\qe allows editing of the current note.
+\qE allows opening notes file in a Vim buffer. Every save of the buffer
+will overwrite your current |quickfix| list.
+
+Troubleshooting~
+
+If |:grep|, |:make|, or other |quickfix| command clobbered your notes, you can
+restore them with |:colder| command.
+
+Quickfix notes are stored in an |unlisted-buffer|. You may find it with |:ls|
+(:ls!) command and work with your data directly.
+
+==============================================================================
+							     *qfnotes-options*
+5. Options~
+
+				   *QFXDefaultFileName* *g:QFXDefaultFileName*
+								*quickfix.err*
+g:QFXDefaultFileName
+		Default notes file name (default value "quickfix.err")
+		When defined but left blank, current value of 'errorfile'
+		is used.
+
+					       *QFXUseDialog* *g:QFXUseDialog*
+g:QFXUseDialog
+		If possible, use GUI dialogs for entering comments.
+
+							*g:QFXDefaultMappings*
+g:QFXDefaultMappings
+		If the variable exists and is 0, default keymappings are not
+		created.
+
+==============================================================================
+							    *qfnotes-commands*
+6. Commands~
+
+The plugin provides the following ex-mode commands:
+
+|:QFXSave|	Saves the |quickfix| window contents
+|:QFXSaveRange|	Saves a part of the |quickfix| list
+|:QFXLoad|	Loads notes file
+|:QFXOpen|	Opens notes file for edit
+|:QFXAdd|	Adds a new note for the current line
+|:QFXAddQ|	Adds a new note for the current line
+|:QFXDelete|	Deletes notes for the current line
+|:QFXEdit|	Edits current note
+
+								    *:QFXSave*
+:QFXSave[!] [file]
+		Save the |quickfix| list to the specified [file]
+		The command works both in buffers and in |quickfix| window:
+>
+		:QFXSave quickfix.err
+<
+
+							       *:QFXSaveRange*
+:[range]QFXSaveRange[!] {file}
+		Saves a part of |quickfix| list.
+
+								    *:QFXLoad*
+:QFXLoad [file]
+:QFXLoad {file} [basedir]
+		Loads notes file to the |quickfix| window from {file}
+		[basedir] is a base directory for relative filenames
+		in the file
+
+								     *:QFXAdd*
+:QFXAdd {text}
+		Add a quickfix entry with the given text for the current file,
+		line, and colum.
+
+								    *:QFXAddQ*
+:QFXAddQ
+		Add a note with text derived from prompting the user.
+
+								  *:QFXDelete*
+:QFXDelete
+		Delete comments for the current line.
+
+								    *:QFXEdit*
+:QFXEdit[!]
+		Edit note for the current line (asks user for new text).
+		If there is no comment, adds new. For empty input deletes
+		current comment.
+		:QFXEdit! will open notes file in a buffer and position cursor
+		on selected comment.
+		To split window, you may use
+>
+		:split +QFXEdit!
+<
+		NOTE
+		Every save of the buffer will overwrite your current
+		|quickfix| list.
+
+								      *QFXNew*
+:QFXNew [file]
+		Start new note taking session
+
+==============================================================================
+							   *qfnotes-mappings*
+7. Default Key Mappings~
+
+<Leader>qn  - add a new note (or edit current)
+<Leader>qd  - delete selected note(s)
+<Leader>qe  - edit selected note(s)
+<Leader>qE  - edit selected note in a buffer
+
+<Leader>qs  - save current notes file
+<Leader>ql  - load notes file with default name (see |g:QFXDefaultFileName|)
+
+Code to create the mappings is below:
+>
+		map <Leader>qn <Plug>QuickFixNote
+		map <Leader>qd <Plug>QuickFixDelete
+		map <Leader>qe <Plug>QuickFixEdit
+		map <Leader>qE <Plug>QuickFixBuffer
+
+		map <Leader>qs <Plug>QuickFixSave
+		map <Leader>ql <Plug>QuickFixLoad
+<
+
+To turn the mappings off, put the following into your |.vimrc|:
+>
+		let g:QFXDefaultMappings = 0
+<
+
+==============================================================================
+							     *qfnotes-license*
+8. License~
+
+Permission is hereby granted to use and distribute the qfn plugin, with or
+without modifications, provided that this copyright notice is copied with it
+and attribution is included.  Like anything else that's free, qfn.vim is
+provided *as is* and comes with no warranty of any kind, either expressed or
+implied. In no event will the copyright holder be liable for any damamges
+resulting from the use of this software.
+
+==============================================================================
+								*qfnotes-todo*
+9. Todo~
+
+* Allow to move notes (useful if reviewed files have been changed)
+* Issue a warning if a quickfix command is going to overwrite our list
+* ?
+
+==============================================================================
+
+vim:tw=78:ts=8:noet:ft=help:

plugin/qfnotes.vim

+" qfnotes.vim
+" Create file notes in quickfix format
+" Last Change: $HGLastChangedDate$
+" Maintainer: Sergey Khorev <sergey.khorev@gmail.com>
+" Based on qfn.vim by Will Drewry <redpig@dataspill.org>: http://www.vim.org/scripts/script.php?script_id=2216
+" License: See qfnotes.txt packaged with this file.
+
+if exists("g:loaded_qfnotes")
+  finish
+endif
+let g:loaded_qfnotes = 1
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+if v:version < 700
+  echo "QFXotes requires version 7.0 or higher"
+  finish
+endif
+
+" Map these local functions globally with the script id
+noremap <unique> <script> <Plug>QuickFixNote <SID>QFXAddQ
+nnoremap <unique> <script> <Plug>QuickFixSave <SID>QFXSave
+noremap <unique> <script> <Plug>QuickFixDelete <SID>QFXDelete
+noremap <unique> <script> <Plug>QuickFixEdit <SID>QFXEdit
+noremap <unique> <script> <Plug>QuickFixBuffer <SID>QFXBuffer
+noremap <unique> <script> <Plug>QuickFixLoad <SID>QFXLoad
+noremap <SID>QFXAddQ :call qfnotes#QFXAddQ()<CR>
+nnoremap <SID>QFXSave :call qfnotes#QFXSave(0)<CR>
+noremap <SID>QFXDelete :call qfnotes#QFXDelete()<CR>
+noremap <SID>QFXEdit :call qfnotes#QFXEdit(0)<CR>
+noremap <SID>QFXBuffer :call qfnotes#QFXEdit(1)<CR>
+noremap <SID>QFXLoad :call qfnotes#QFXLoad()<CR>
+
+command! -nargs=1 QFXAdd :call qfnotes#QFXAdd(<f-args>)
+command! -nargs=0 QFXAddQ :call qfnotes#QFXAddQ()
+command! -nargs=? -complete=file -bang QFXSave :call qfnotes#QFXSave('<bang>'=='!', <f-args>)
+command! -nargs=1 -complete=file -bang -range QFXSaveRange <line1>,<line2>call qfnotes#QFXSaveRange('<bang>'=='!', <f-args>)
+command! -nargs=0 -range QFXDelete :<line1>,<line2>call qfnotes#QFXDelete()
+command! -nargs=0 -range -bang QFXEdit :<line1>,<line2>call qfnotes#QFXEdit('<bang>'=='!')
+command! -nargs=* -complete=file QFXLoad :call qfnotes#QFXLoad(<f-args>)
+command! -nargs=? -complete=file QFXNew :call qfnotes#QFXNew(<f-args>)
+
+if !exists('g:QFXDefaultMappings') || g:QFXDefaultMappings
+  if !hasmapto('<Plug>QuickFixNote')
+    map <unique> <Leader>qn <Plug>QuickFixNote
+  endif
+
+  if !hasmapto('<Plug>QuickFixSave')
+    map <unique> <Leader>qs <Plug>QuickFixSave
+  endif
+
+  if !hasmapto('<Plug>QuickFixLoad')
+    map <unique> <Leader>ql <Plug>QuickFixLoad
+  endif
+
+  if !hasmapto('<Plug>QuickFixDelete')
+    map <unique> <Leader>qd <Plug>QuickFixDelete
+  endif
+
+  if !hasmapto('<Plug>QuickFixEdit')
+    map <unique> <Leader>qe <Plug>QuickFixEdit
+  endif
+
+  if !hasmapto('<Plug>QuickFixBuffer')
+    map <unique> <Leader>qE <Plug>QuickFixBuffer
+  endif
+endif
+
+let &cpo = s:save_cpo
+
+finish
+
+Vimball filelist
+
+doc/qfnotes.txt
+autoload/qfnotes.vim
+plugin/qfnotes.vim
+
+" vim: set ft=vim ts=8 sts=2 sw=2:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.