On Mon, Jul 13, 2009 at 5:06 PM, Toni Ruottu<[email protected]> wrote: > > I'd be perfectly happy in doing :w! and getting the file saved under a > random named (like the ones you proposed) under ~/.vim/rubbish/. If > someone then wants to make more advanced user interfaces for exploring > the rubbish folder, that is fine with me too, but I'd do fine without > one. I don't mind tidying the files in that folder up every once in a > while, as long as my work is not interrupted with irritating problems, > like thinking of file names.
It should be easy enough to create an autocommand that takes the first
line in the text and create a filename for it. I have been using a
small windows note taking utility called Tombo (for historical reasons
originating from Windows Mobile) that actually does this. You just
create a new note and start typing in, and on the first save, it
automatically names the file on the filesystem based on the first line
in the text (this is also how MS Word and quite a few other programs
suggest a name for a new document). I had been thinking of bringing
that convenience to Vim such that I can just stop using Tombo and
switch to Vim for all my note taking. The features that I really need
are:
- Ease of starting a new note
- Automatic naming and saving of new notes under predefined directory
- Tree view of the notes directory for the ease of browsing and opening notes
- Ease of organizing the notes (cut/copy/paste/delete) from tree view
- Sync the name of the file when the note header is updated
After seeing this thread, I got motivated to work on it and have the
attached script so far (CAUTION: It is work in progress). To use it,
configure the first few variables and use :Note command to create a
new note or specify an existing one.
It will be nice if I can find signers for doing early testing and
sending feedback and suggestions.
-- Hari
PS: not sure if attachments are allowed, so copy pasting below, hoping
it won't get truncated.
------------------notes.vim------------------
" TODO:
" - The technique doesn't work with unnamed files, vim refuses to allow :w
" command.
" - Lots of testing
" - Filename completion for Note
" - Better name generation for automatic names
" - Tree view and note management
" - Plugginization
"
let g:notesRoot = 'c:/tmp/root' " Please, no trailing-slash for now.
let g:notesDefaultName = 'New Note' " Add .txt automatically.
let g:notesMaxNameLenth = 100
let g:notesSyncNameAndTitle = 1
if !isdirectory(g:notesRoot)
echohl ErrorMsg | echomsg "Notes: Configured root doesn't exist or
is not a directory: " .
\ g:notesRoot | echohl NONE
endif
command! -nargs=? Note :call OpenNote('<args>')
function! OpenNote(notePath)
if a:notePath == ''
let notePath = NewName(g:notesRoot, g:notesDefaultName)
else
if (len(filter(['win16', 'win32', 'win65', 'win95', 'dos16',
'dos32'], 'has(v:val)')) > 0 &&
\ a:notePath =~ '^\([a-zA-Z]:\|[/\\]\)') || a:notePath =~
'^/'
" This is an absolute path
if fnamemodify(a:notePath, ':h') != fnamemodify(g:notesRoot)
echohl ErrorMsg | echohl 'Note not under g:notesRoot' | echohl
None
return
endif
let notePath = a:notePath
else
let notePath = fnamemodify(g:notesRoot.'/'.a:notePath, ':p')
endif
endif
exec 'sp' notePath
call InstallAutoCmd()
endfunction
function! InstallAutoCmd()
aug NoteSync
au BufWriteCmd <buffer> :call feedkeys(":SyncNoteName!\<CR>", 'n')
aug END
endfunction
function! UninstallAutoCmd()
aug NoteSync
au! BufWriteCmd <buffer>
aug END
endfunction
command! -bang SyncNoteName :call SyncNoteName(expand('<bang>') == '!' ? 1 : 0)
" Look at the first non-empty line and sync the filename to it.
function! SyncNoteName(save) abort
if &modified
if !a:save
echohl ErrorMsg | echo 'Note currently modified, save it first' |
echohl NONE
return
endif
try
call UninstallAutoCmd()
write!
catch
echohl ErrorMsg | echo 'Error saving the file: '.v:exception |
echohl NONE
return
finally
call InstallAutoCmd()
endtry
endif
if !g:notesSyncNameAndTitle
return
endif
let goodLine = ''
for lineNr in range(1, line('$'))
let line = getline(lineNr)
if line =~ '\w'
let goodLine = line
break
endif
endfor
if goodLine != ''
let name = substitute(line, '[^[:alnum:]_ ]', '_', 'g')[:
g:notesMaxNameLenth-1]
let newNotePath = NewName(g:notesRoot, name)
let prevNotePath = expand('%:p')
if NoteRootName(newNotePath) == NoteRootName(prevNotePath)
return
endif
if writefile(map(getline(1, '$'), '&ff == "dos" ? v:val."\<CR>" :
v:val'), newNotePath) == 0
" Success copying the contents, we can now switch to the new
" note and remove the other note
try
exec 'edit' newNotePath
call InstallAutoCmd()
catch
if expand('%:p') == fnamemodify(prevNotePath, ':p')
" We are still in the previous note, it is safe to remove
" the intermediate file.
if delete(newNotePath) != 0
echohl ErrorMsg |
\ echomsg 'An unexpected error prevented
sync and '.
\ 'deleting the intermediate file also
failed, manual '.
\ 'removal is required for:
'.newNotePath."\nOriginal error: ".
\ v:exception |
\ echohl NONE
endif
if expand('#:p') == fnamemodify(newNotePath, ':p')
bw #
endif
else
echohl ErrorMsg |
\ echomsg 'Aborted sync on an unxpected error,
old path: '.
\ prevNotePath. ' new path:'.newNotePath |
\ echohl NONE
endif
endtry
if delete(prevNotePath) != 0
echohl ErrorMsg | echomsg 'Error removing the old path to the
note:
'.prevNotePath | echohl NONE
else
silent! bw #
endif
endif
endif
endfunction
" Creates a new note and returns the path.
" This should really be the job of tempname(), but it doesn't accept the
" directory and prefix (like the Java's utility does)
" LIMITATIONS:
" - Has to start with "1" for the first file for the logic to work, will be
" nice if number is inserted only from "2" onwards.
function! NewName(dir, prefix)
let curSuffixMax = max(sort(map(map(
\ split(glob(a:dir.'/'.a:prefix.'*.txt'), "\<NL>"),
\ 'substitute(v:val, "^.*\\(\\d\\+\\)\\s*\\.txt$", "\\1",
"")'),
\ 'v:val + 0'), 'NumCompare'))
let newNamePath = a:dir . '/' . a:prefix . ' '.(curSuffixMax + 1) . '.txt'
" Just make sure we will not accidentally overwrite an existing file.
if exists(newNamePath)
throw "Notes:Couldn't create a new note, found an existing note with
the same name: " . newNamePath
endif
if writefile([], newNamePath) != 0
throw "Notes:writefile() failed to create new note: " . newNamePath
endif
return newNamePath
endfunction
function! NumCompare(i1, i2)
return a:i1 == a:i2 ? 0 : a:i1 > a:i2 ? 1 : -1
endfunc
function! NoteRootName(noteName)
let noteName = fnamemodify(a:noteName, ':t:r')
return substitute(noteName, '\d\+\s*$', '', '')
endfunction
------------------notes.vim------------------
--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---
notes.vim
Description: Binary data
