assorted-commits Mailing List for Assorted projects (Page 15)
Brought to you by:
yangzhang
You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(9) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(86) |
Feb
(265) |
Mar
(96) |
Apr
(47) |
May
(136) |
Jun
(28) |
Jul
(57) |
Aug
(42) |
Sep
(20) |
Oct
(67) |
Nov
(37) |
Dec
(34) |
2009 |
Jan
(39) |
Feb
(85) |
Mar
(96) |
Apr
(24) |
May
(82) |
Jun
(13) |
Jul
(10) |
Aug
(8) |
Sep
(2) |
Oct
(20) |
Nov
(31) |
Dec
(17) |
2010 |
Jan
(16) |
Feb
(11) |
Mar
(17) |
Apr
(53) |
May
(31) |
Jun
(13) |
Jul
(3) |
Aug
(6) |
Sep
(11) |
Oct
(4) |
Nov
(17) |
Dec
(17) |
2011 |
Jan
(3) |
Feb
(19) |
Mar
(5) |
Apr
(17) |
May
(3) |
Jun
(4) |
Jul
(14) |
Aug
(3) |
Sep
(2) |
Oct
(1) |
Nov
(3) |
Dec
(2) |
2012 |
Jan
(3) |
Feb
(7) |
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
(4) |
Aug
(5) |
Sep
(2) |
Oct
(3) |
Nov
|
Dec
|
2013 |
Jan
|
Feb
|
Mar
(9) |
Apr
(5) |
May
|
Jun
(2) |
Jul
(1) |
Aug
(10) |
Sep
(1) |
Oct
(2) |
Nov
|
Dec
|
2014 |
Jan
(1) |
Feb
(3) |
Mar
(3) |
Apr
(1) |
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
2016 |
Jan
(1) |
Feb
|
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
2017 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(5) |
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <yan...@us...> - 2010-01-25 03:42:59
|
Revision: 1552 http://assorted.svn.sourceforge.net/assorted/?rev=1552&view=rev Author: yangzhang Date: 2010-01-25 03:42:50 +0000 (Mon, 25 Jan 2010) Log Message: ----------- forgot snipmate doc Added Paths: ----------- configs/trunk/src/vim/doc/snipMate.txt Added: configs/trunk/src/vim/doc/snipMate.txt =================================================================== --- configs/trunk/src/vim/doc/snipMate.txt (rev 0) +++ configs/trunk/src/vim/doc/snipMate.txt 2010-01-25 03:42:50 UTC (rev 1552) @@ -0,0 +1,286 @@ +*snipMate.txt* Plugin for using TextMate-style snippets in Vim. + +snipMate *snippet* *snippets* *snipMate* +Last Change: July 13, 2009 + +|snipMate-description| Description +|snipMate-syntax| Snippet syntax +|snipMate-usage| Usage +|snipMate-settings| Settings +|snipMate-features| Features +|snipMate-disadvantages| Disadvantages to TextMate +|snipMate-contact| Contact + +For Vim version 7.0 or later. +This plugin only works if 'compatible' is not set. +{Vi does not have any of these features.} + +============================================================================== +DESCRIPTION *snipMate-description* + +snipMate.vim implements some of TextMate's snippets features in Vim. A +snippet is a piece of often-typed text that you can insert into your +document using a trigger word followed by a <tab>. + +For instance, in a C file using the default installation of snipMate.vim, if +you type "for<tab>" in insert mode, it will expand a typical for loop in C: > + + for (i = 0; i < count; i++) { + + } + + +To go to the next item in the loop, simply <tab> over to it; if there is +repeated code, such as the "i" variable in this example, you can simply +start typing once it's highlighted and all the matches specified in the +snippet will be updated. To go in reverse, use <shift-tab>. + +============================================================================== +SYNTAX *snippet-syntax* + +Snippets can be defined in two ways. They can be in their own file, named +after their trigger in 'snippets/<filetype>/<trigger>.snippet', or they can be +defined together in a 'snippets/<filetype>.snippets' file. Note that dotted +'filetype' syntax is supported -- e.g., you can use > + + :set ft=html.eruby + +to activate snippets for both HTML and eRuby for the current file. + +The syntax for snippets in *.snippets files is the following: > + + snippet trigger + expanded text + more expanded text + +Note that the first hard tab after the snippet trigger is required, and not +expanded in the actual snippet. The syntax for *.snippet files is the same, +only without the trigger declaration and starting indentation. + +Also note that snippets must be defined using hard tabs. They can be expanded +to spaces later if desired (see |snipMate-indenting|). + +"#" is used as a line-comment character in *.snippets files; however, they can +only be used outside of a snippet declaration. E.g.: > + + # this is a correct comment + snippet trigger + expanded text + snippet another_trigger + # this isn't a comment! + expanded text +< +This should hopefully be obvious with the included syntax highlighting. + + *snipMate-${#}* +Tab stops ~ + +By default, the cursor is placed at the end of a snippet. To specify where the +cursor is to be placed next, use "${#}", where the # is the number of the tab +stop. E.g., to place the cursor first on the id of a <div> tag, and then allow +the user to press <tab> to go to the middle of it: + > + snippet div + <div id="${1}"> + ${2} + </div> +< + *snipMate-placeholders* *snipMate-${#:}* *snipMate-$#* +Placeholders ~ + +Placeholder text can be supplied using "${#:text}", where # is the number of +the tab stop. This text then can be copied throughout the snippet using "$#", +given # is the same number as used before. So, to make a C for loop: > + + snippet for + for (${2:i}; $2 < ${1:count}; $1++) { + ${4} + } + +This will cause "count" to first be selected and change if the user starts +typing. When <tab> is pressed, the "i" in ${2}'s position will be selected; +all $2 variables will default to "i" and automatically be updated if the user +starts typing. +NOTE: "$#" syntax is used only for variables, not for tab stops as in TextMate. + +Variables within variables are also possible. For instance: > + + snippet opt + <option value="${1:option}">${2:$1}</option> + +Will, as usual, cause "option" to first be selected and update all the $1 +variables if the user starts typing. Since one of these variables is inside of +${2}, this text will then be used as a placeholder for the next tab stop, +allowing the user to change it if he wishes. + +To copy a value throughout a snippet without supplying default text, simply +use the "${#:}" construct without the text; e.g.: > + + snippet foo + ${1:}bar$1 +< *snipMate-commands* +Interpolated Vim Script ~ + +Snippets can also contain Vim script commands that are executed (via |eval()|) +when the snippet is inserted. Commands are given inside backticks (`...`); for +TextMates's functionality, use the |system()| function. E.g.: > + + snippet date + `system("date +%Y-%m-%d")` + +will insert the current date, assuming you are on a Unix system. Note that you +can also (and should) use |strftime()| for this example. + +Filename([{expr}] [, {defaultText}]) *snipMate-filename* *Filename()* + +Since the current filename is used often in snippets, a default function +has been defined for it in snipMate.vim, appropriately called Filename(). + +With no arguments, the default filename without an extension is returned; +the first argument specifies what to place before or after the filename, +and the second argument supplies the default text to be used if the file +has not been named. "$1" in the first argument is replaced with the filename; +if you only want the filename to be returned, the first argument can be left +blank. Examples: > + + snippet filename + `Filename()` + snippet filename_with_default + `Filename('', 'name')` + snippet filename_foo + `filename('$1_foo')` + +The first example returns the filename if it the file has been named, and an +empty string if it hasn't. The second returns the filename if it's been named, +and "name" if it hasn't. The third returns the filename followed by "_foo" if +it has been named, and an empty string if it hasn't. + + *multi_snip* +To specify that a snippet can have multiple matches in a *.snippets file, use +this syntax: > + + snippet trigger A description of snippet #1 + expand this text + snippet trigger A description of snippet #2 + expand THIS text! + +In this example, when "trigger<tab>" is typed, a numbered menu containing all +of the descriptions of the "trigger" will be shown; when the user presses the +corresponding number, that snippet will then be expanded. + +To create a snippet with multiple matches using *.snippet files, +simply place all the snippets in a subdirectory with the trigger name: +'snippets/<filetype>/<trigger>/<name>.snippet'. + +============================================================================== +USAGE *snipMate-usage* + + *'snippets'* *g:snippets_dir* +Snippets are by default looked for any 'snippets' directory in your +'runtimepath'. Typically, it is located at '~/.vim/snippets/' on *nix or +'$HOME\vimfiles\snippets\' on Windows. To change that location or add another +one, change the g:snippets_dir variable in your |.vimrc| to your preferred +directory, or use the |ExtractSnips()|function. This will be used by the +|globpath()| function, and so accepts the same syntax as it (e.g., +comma-separated paths). + +ExtractSnipsFile({directory}, {filetype}) *ExtractSnipsFile()* *.snippets* + +ExtractSnipsFile() extracts the specified *.snippets file for the given +filetype. A .snippets file contains multiple snippet declarations for the +filetype. It is further explained above, in |snippet-syntax|. + +ExtractSnips({directory}, {filetype}) *ExtractSnips()* *.snippet* + +ExtractSnips() extracts *.snippet files from the specified directory and +defines them as snippets for the given filetype. The directory tree should +look like this: 'snippets/<filetype>/<trigger>.snippet'. If the snippet has +multiple matches, it should look like this: +'snippets/<filetype>/<trigger>/<name>.snippet' (see |multi_snip|). + + *ResetSnippets()* +The ResetSnippets() function removes all snippets from memory. This is useful +to put at the top of a snippet setup file for if you would like to |:source| +it multiple times. + + *list-snippets* *i_CTRL-R_<Tab>* +If you would like to see what snippets are available, simply type <c-r><tab> +in the current buffer to show a list via |popupmenu-completion|. + +============================================================================== +SETTINGS *snipMate-settings* *g:snips_author* + +The g:snips_author string (similar to $TM_FULLNAME in TextMate) should be set +to your name; it can then be used in snippets to automatically add it. E.g.: > + + let g:snips_author = 'Hubert Farnsworth' + snippet name + `g:snips_author` +< + *snipMate-expandtab* *snipMate-indenting* +If you would like your snippets to be expanded using spaces instead of tabs, +just enable 'expandtab' and set 'softtabstop' to your preferred amount of +spaces. If 'softtabstop' is not set, 'shiftwidth' is used instead. + + *snipMate-remap* +snipMate does not come with a setting to customize the trigger key, but you +can remap it easily in the two lines it's defined in the 'after' directory +under 'plugin/snipMate.vim'. For instance, to change the trigger key +to CTRL-J, just change this: > + + ino <tab> <c-r>=TriggerSnippet()<cr> + snor <tab> <esc>i<right><c-r>=TriggerSnippet()<cr> + +to this: > + ino <c-j> <c-r>=TriggerSnippet()<cr> + snor <c-j> <esc>i<right><c-r>=TriggerSnippet()<cr> + +============================================================================== +FEATURES *snipMate-features* + +snipMate.vim has the following features among others: + - The syntax of snippets is very similar to TextMate's, allowing + easy conversion. + - The position of the snippet is kept transparently (i.e. it does not use + markers/placeholders written to the buffer), which allows you to escape + out of an incomplete snippet, something particularly useful in Vim. + - Variables in snippets are updated as-you-type. + - Snippets can have multiple matches. + - Snippets can be out of order. For instance, in a do...while loop, the + condition can be added before the code. + - [New] File-based snippets are supported. + - [New] Triggers after non-word delimiters are expanded, e.g. "foo" + in "bar.foo". + - [New] <shift-tab> can now be used to jump tab stops in reverse order. + +============================================================================== +DISADVANTAGES *snipMate-disadvantages* + +snipMate.vim currently has the following disadvantages to TextMate's snippets: + - There is no $0; the order of tab stops must be explicitly stated. + - Placeholders within placeholders are not possible. E.g.: > + + '<div${1: id="${2:some_id}}">${3}</div>' +< + In TextMate this would first highlight ' id="some_id"', and if + you hit delete it would automatically skip ${2} and go to ${3} + on the next <tab>, but if you didn't delete it it would highlight + "some_id" first. You cannot do this in snipMate.vim. + - Regex cannot be performed on variables, such as "${1/.*/\U&}" + - Placeholders cannot span multiple lines. + - Activating snippets in different scopes of the same file is + not possible. + +Perhaps some of these features will be added in a later release. + +============================================================================== +CONTACT *snipMate-contact* *snipMate-author* + +To contact the author (Michael Sanders), please email: + msanders42+snipmate <at> gmail <dot> com + +I greatly appreciate any suggestions or improvements offered for the script. + +============================================================================== + +vim:tw=78:ts=8:ft=help:norl: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2010-01-25 03:39:50
|
Revision: 1551 http://assorted.svn.sourceforge.net/assorted/?rev=1551&view=rev Author: yangzhang Date: 2010-01-25 03:39:43 +0000 (Mon, 25 Jan 2010) Log Message: ----------- added snipmate for vim Added Paths: ----------- configs/trunk/src/vim/after/ configs/trunk/src/vim/after/plugin/ configs/trunk/src/vim/after/plugin/snipMate.vim configs/trunk/src/vim/autoload/ configs/trunk/src/vim/autoload/snipMate.vim configs/trunk/src/vim/ftplugin/html_snip_helper.vim configs/trunk/src/vim/plugin/snipMate.vim configs/trunk/src/vim/snippets/ configs/trunk/src/vim/snippets/_.snippets configs/trunk/src/vim/snippets/autoit.snippets configs/trunk/src/vim/snippets/c.snippets configs/trunk/src/vim/snippets/cpp.snippets configs/trunk/src/vim/snippets/html.snippets configs/trunk/src/vim/snippets/java.snippets configs/trunk/src/vim/snippets/javascript.snippets configs/trunk/src/vim/snippets/mako.snippets configs/trunk/src/vim/snippets/objc.snippets configs/trunk/src/vim/snippets/perl.snippets configs/trunk/src/vim/snippets/php.snippets configs/trunk/src/vim/snippets/python.snippets configs/trunk/src/vim/snippets/ruby.snippets configs/trunk/src/vim/snippets/sh.snippets configs/trunk/src/vim/snippets/snippet.snippets configs/trunk/src/vim/snippets/tcl.snippets configs/trunk/src/vim/snippets/tex.snippets configs/trunk/src/vim/snippets/vim.snippets configs/trunk/src/vim/snippets/zsh.snippets configs/trunk/src/vim/syntax/snippet.vim Added: configs/trunk/src/vim/after/plugin/snipMate.vim =================================================================== --- configs/trunk/src/vim/after/plugin/snipMate.vim (rev 0) +++ configs/trunk/src/vim/after/plugin/snipMate.vim 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,35 @@ +" These are the mappings for snipMate.vim. Putting it here ensures that it +" will be mapped after other plugins such as supertab.vim. +if !exists('loaded_snips') || exists('s:did_snips_mappings') + finish +endif +let s:did_snips_mappings = 1 + +ino <silent> <tab> <c-r>=TriggerSnippet()<cr> +snor <silent> <tab> <esc>i<right><c-r>=TriggerSnippet()<cr> +ino <silent> <s-tab> <c-r>=BackwardsSnippet()<cr> +snor <silent> <s-tab> <esc>i<right><c-r>=BackwardsSnippet()<cr> +ino <silent> <c-r><tab> <c-r>=ShowAvailableSnips()<cr> + +" The default mappings for these are annoying & sometimes break snipMate. +" You can change them back if you want, I've put them here for convenience. +snor <bs> b<bs> +snor <right> <esc>a +snor <left> <esc>bi +snor ' b<bs>' +snor ` b<bs>` +snor % b<bs>% +snor U b<bs>U +snor ^ b<bs>^ +snor \ b<bs>\ +snor <c-x> b<bs><c-x> + +" By default load snippets in snippets_dir +if empty(snippets_dir) + finish +endif + +call GetSnippets(snippets_dir, '_') " Get global snippets + +au FileType * if &ft != 'help' | call GetSnippets(snippets_dir, &ft) | endif +" vim:noet:sw=4:ts=4:ft=vim Added: configs/trunk/src/vim/autoload/snipMate.vim =================================================================== --- configs/trunk/src/vim/autoload/snipMate.vim (rev 0) +++ configs/trunk/src/vim/autoload/snipMate.vim 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,433 @@ +fun! Filename(...) + let filename = expand('%:t:r') + if filename == '' | return a:0 == 2 ? a:2 : '' | endif + return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g') +endf + +fun s:RemoveSnippet() + unl! g:snipPos s:curPos s:snipLen s:endCol s:endLine s:prevLen + \ s:lastBuf s:oldWord + if exists('s:update') + unl s:startCol s:origWordLen s:update + if exists('s:oldVars') | unl s:oldVars s:oldEndCol | endif + endif + aug! snipMateAutocmds +endf + +fun snipMate#expandSnip(snip, col) + let lnum = line('.') | let col = a:col + + let snippet = s:ProcessSnippet(a:snip) + " Avoid error if eval evaluates to nothing + if snippet == '' | return '' | endif + + " Expand snippet onto current position with the tab stops removed + let snipLines = split(substitute(snippet, '$\d\+\|${\d\+.\{-}}', '', 'g'), "\n", 1) + + let line = getline(lnum) + let afterCursor = strpart(line, col - 1) + " Keep text after the cursor + if afterCursor != "\t" && afterCursor != ' ' + let line = strpart(line, 0, col - 1) + let snipLines[-1] .= afterCursor + else + let afterCursor = '' + " For some reason the cursor needs to move one right after this + if line != '' && col == 1 && &ve != 'all' && &ve != 'onemore' + let col += 1 + endif + endif + + call setline(lnum, line.snipLines[0]) + + " Autoindent snippet according to previous indentation + let indent = matchend(line, '^.\{-}\ze\(\S\|$\)') + 1 + call append(lnum, map(snipLines[1:], "'".strpart(line, 0, indent - 1)."'.v:val")) + + " Open any folds snippet expands into + if &fen | sil! exe lnum.','.(lnum + len(snipLines) - 1).'foldopen' | endif + + let [g:snipPos, s:snipLen] = s:BuildTabStops(snippet, lnum, col - indent, indent) + + if s:snipLen + aug snipMateAutocmds + au CursorMovedI * call s:UpdateChangedSnip(0) + au InsertEnter * call s:UpdateChangedSnip(1) + aug END + let s:lastBuf = bufnr(0) " Only expand snippet while in current buffer + let s:curPos = 0 + let s:endCol = g:snipPos[s:curPos][1] + let s:endLine = g:snipPos[s:curPos][0] + + call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1]) + let s:prevLen = [line('$'), col('$')] + if g:snipPos[s:curPos][2] != -1 | return s:SelectWord() | endif + else + unl g:snipPos s:snipLen + " Place cursor at end of snippet if no tab stop is given + let newlines = len(snipLines) - 1 + call cursor(lnum + newlines, indent + len(snipLines[-1]) - len(afterCursor) + \ + (newlines ? 0: col - 1)) + endif + return '' +endf + +" Prepare snippet to be processed by s:BuildTabStops +fun s:ProcessSnippet(snip) + let snippet = a:snip + " Evaluate eval (`...`) expressions. + " Using a loop here instead of a regex fixes a bug with nested "\=". + if stridx(snippet, '`') != -1 + while match(snippet, '`.\{-}`') != -1 + let snippet = substitute(snippet, '`.\{-}`', + \ substitute(eval(matchstr(snippet, '`\zs.\{-}\ze`')), + \ "\n\\%$", '', ''), '') + endw + let snippet = substitute(snippet, "\r", "\n", 'g') + endif + + " Place all text after a colon in a tab stop after the tab stop + " (e.g. "${#:foo}" becomes "${:foo}foo"). + " This helps tell the position of the tab stops later. + let snippet = substitute(snippet, '${\d\+:\(.\{-}\)}', '&\1', 'g') + + " Update the a:snip so that all the $# become the text after + " the colon in their associated ${#}. + " (e.g. "${1:foo}" turns all "$1"'s into "foo") + let i = 1 + while stridx(snippet, '${'.i) != -1 + let s = matchstr(snippet, '${'.i.':\zs.\{-}\ze}') + if s != '' + let snippet = substitute(snippet, '$'.i, s.'&', 'g') + endif + let i += 1 + endw + + if &et " Expand tabs to spaces if 'expandtab' is set. + return substitute(snippet, '\t', repeat(' ', &sts ? &sts : &sw), 'g') + endif + return snippet +endf + +" Counts occurences of haystack in needle +fun s:Count(haystack, needle) + let counter = 0 + let index = stridx(a:haystack, a:needle) + while index != -1 + let index = stridx(a:haystack, a:needle, index+1) + let counter += 1 + endw + return counter +endf + +" Builds a list of a list of each tab stop in the snippet containing: +" 1.) The tab stop's line number. +" 2.) The tab stop's column number +" (by getting the length of the string between the last "\n" and the +" tab stop). +" 3.) The length of the text after the colon for the current tab stop +" (e.g. "${1:foo}" would return 3). If there is no text, -1 is returned. +" 4.) If the "${#:}" construct is given, another list containing all +" the matches of "$#", to be replaced with the placeholder. This list is +" composed the same way as the parent; the first item is the line number, +" and the second is the column. +fun s:BuildTabStops(snip, lnum, col, indent) + let snipPos = [] + let i = 1 + let withoutVars = substitute(a:snip, '$\d\+', '', 'g') + while stridx(a:snip, '${'.i) != -1 + let beforeTabStop = matchstr(withoutVars, '^.*\ze${'.i.'\D') + let withoutOthers = substitute(withoutVars, '${\('.i.'\D\)\@!\d\+.\{-}}', '', 'g') + + let j = i - 1 + call add(snipPos, [0, 0, -1]) + let snipPos[j][0] = a:lnum + s:Count(beforeTabStop, "\n") + let snipPos[j][1] = a:indent + len(matchstr(withoutOthers, '.*\(\n\|^\)\zs.*\ze${'.i.'\D')) + if snipPos[j][0] == a:lnum | let snipPos[j][1] += a:col | endif + + " Get all $# matches in another list, if ${#:name} is given + if stridx(withoutVars, '${'.i.':') != -1 + let snipPos[j][2] = len(matchstr(withoutVars, '${'.i.':\zs.\{-}\ze}')) + let dots = repeat('.', snipPos[j][2]) + call add(snipPos[j], []) + let withoutOthers = substitute(a:snip, '${\d\+.\{-}}\|$'.i.'\@!\d\+', '', 'g') + while match(withoutOthers, '$'.i.'\(\D\|$\)') != -1 + let beforeMark = matchstr(withoutOthers, '^.\{-}\ze'.dots.'$'.i.'\(\D\|$\)') + call add(snipPos[j][3], [0, 0]) + let snipPos[j][3][-1][0] = a:lnum + s:Count(beforeMark, "\n") + let snipPos[j][3][-1][1] = a:indent + (snipPos[j][3][-1][0] > a:lnum + \ ? len(matchstr(beforeMark, '.*\n\zs.*')) + \ : a:col + len(beforeMark)) + let withoutOthers = substitute(withoutOthers, '$'.i.'\ze\(\D\|$\)', '', '') + endw + endif + let i += 1 + endw + return [snipPos, i - 1] +endf + +fun snipMate#jumpTabStop(backwards) + let leftPlaceholder = exists('s:origWordLen') + \ && s:origWordLen != g:snipPos[s:curPos][2] + if leftPlaceholder && exists('s:oldEndCol') + let startPlaceholder = s:oldEndCol + 1 + endif + + if exists('s:update') + call s:UpdatePlaceholderTabStops() + else + call s:UpdateTabStops() + endif + + " Don't reselect placeholder if it has been modified + if leftPlaceholder && g:snipPos[s:curPos][2] != -1 + if exists('startPlaceholder') + let g:snipPos[s:curPos][1] = startPlaceholder + else + let g:snipPos[s:curPos][1] = col('.') + let g:snipPos[s:curPos][2] = 0 + endif + endif + + let s:curPos += a:backwards ? -1 : 1 + " Loop over the snippet when going backwards from the beginning + if s:curPos < 0 | let s:curPos = s:snipLen - 1 | endif + + if s:curPos == s:snipLen + let sMode = s:endCol == g:snipPos[s:curPos-1][1]+g:snipPos[s:curPos-1][2] + call s:RemoveSnippet() + return sMode ? "\<tab>" : TriggerSnippet() + endif + + call cursor(g:snipPos[s:curPos][0], g:snipPos[s:curPos][1]) + + let s:endLine = g:snipPos[s:curPos][0] + let s:endCol = g:snipPos[s:curPos][1] + let s:prevLen = [line('$'), col('$')] + + return g:snipPos[s:curPos][2] == -1 ? '' : s:SelectWord() +endf + +fun s:UpdatePlaceholderTabStops() + let changeLen = s:origWordLen - g:snipPos[s:curPos][2] + unl s:startCol s:origWordLen s:update + if !exists('s:oldVars') | return | endif + " Update tab stops in snippet if text has been added via "$#" + " (e.g., in "${1:foo}bar$1${2}"). + if changeLen != 0 + let curLine = line('.') + + for pos in g:snipPos + if pos == g:snipPos[s:curPos] | continue | endif + let changed = pos[0] == curLine && pos[1] > s:oldEndCol + let changedVars = 0 + let endPlaceholder = pos[2] - 1 + pos[1] + " Subtract changeLen from each tab stop that was after any of + " the current tab stop's placeholders. + for [lnum, col] in s:oldVars + if lnum > pos[0] | break | endif + if pos[0] == lnum + if pos[1] > col || (pos[2] == -1 && pos[1] == col) + let changed += 1 + elseif col < endPlaceholder + let changedVars += 1 + endif + endif + endfor + let pos[1] -= changeLen * changed + let pos[2] -= changeLen * changedVars " Parse variables within placeholders + " e.g., "${1:foo} ${2:$1bar}" + + if pos[2] == -1 | continue | endif + " Do the same to any placeholders in the other tab stops. + for nPos in pos[3] + let changed = nPos[0] == curLine && nPos[1] > s:oldEndCol + for [lnum, col] in s:oldVars + if lnum > nPos[0] | break | endif + if nPos[0] == lnum && nPos[1] > col + let changed += 1 + endif + endfor + let nPos[1] -= changeLen * changed + endfor + endfor + endif + unl s:endCol s:oldVars s:oldEndCol +endf + +fun s:UpdateTabStops() + let changeLine = s:endLine - g:snipPos[s:curPos][0] + let changeCol = s:endCol - g:snipPos[s:curPos][1] + if exists('s:origWordLen') + let changeCol -= s:origWordLen + unl s:origWordLen + endif + let lnum = g:snipPos[s:curPos][0] + let col = g:snipPos[s:curPos][1] + " Update the line number of all proceeding tab stops if <cr> has + " been inserted. + if changeLine != 0 + let changeLine -= 1 + for pos in g:snipPos + if pos[0] >= lnum + if pos[0] == lnum | let pos[1] += changeCol | endif + let pos[0] += changeLine + endif + if pos[2] == -1 | continue | endif + for nPos in pos[3] + if nPos[0] >= lnum + if nPos[0] == lnum | let nPos[1] += changeCol | endif + let nPos[0] += changeLine + endif + endfor + endfor + elseif changeCol != 0 + " Update the column of all proceeding tab stops if text has + " been inserted/deleted in the current line. + for pos in g:snipPos + if pos[1] >= col && pos[0] == lnum + let pos[1] += changeCol + endif + if pos[2] == -1 | continue | endif + for nPos in pos[3] + if nPos[0] > lnum | break | endif + if nPos[0] == lnum && nPos[1] >= col + let nPos[1] += changeCol + endif + endfor + endfor + endif +endf + +fun s:SelectWord() + let s:origWordLen = g:snipPos[s:curPos][2] + let s:oldWord = strpart(getline('.'), g:snipPos[s:curPos][1] - 1, + \ s:origWordLen) + let s:prevLen[1] -= s:origWordLen + if !empty(g:snipPos[s:curPos][3]) + let s:update = 1 + let s:endCol = -1 + let s:startCol = g:snipPos[s:curPos][1] - 1 + endif + if !s:origWordLen | return '' | endif + let l = col('.') != 1 ? 'l' : '' + if &sel == 'exclusive' + return "\<esc>".l.'v'.s:origWordLen."l\<c-g>" + endif + return s:origWordLen == 1 ? "\<esc>".l.'gh' + \ : "\<esc>".l.'v'.(s:origWordLen - 1)."l\<c-g>" +endf + +" This updates the snippet as you type when text needs to be inserted +" into multiple places (e.g. in "${1:default text}foo$1bar$1", +" "default text" would be highlighted, and if the user types something, +" UpdateChangedSnip() would be called so that the text after "foo" & "bar" +" are updated accordingly) +" +" It also automatically quits the snippet if the cursor is moved out of it +" while in insert mode. +fun s:UpdateChangedSnip(entering) + if exists('g:snipPos') && bufnr(0) != s:lastBuf + call s:RemoveSnippet() + elseif exists('s:update') " If modifying a placeholder + if !exists('s:oldVars') && s:curPos + 1 < s:snipLen + " Save the old snippet & word length before it's updated + " s:startCol must be saved too, in case text is added + " before the snippet (e.g. in "foo$1${2}bar${1:foo}"). + let s:oldEndCol = s:startCol + let s:oldVars = deepcopy(g:snipPos[s:curPos][3]) + endif + let col = col('.') - 1 + + if s:endCol != -1 + let changeLen = col('$') - s:prevLen[1] + let s:endCol += changeLen + else " When being updated the first time, after leaving select mode + if a:entering | return | endif + let s:endCol = col - 1 + endif + + " If the cursor moves outside the snippet, quit it + if line('.') != g:snipPos[s:curPos][0] || col < s:startCol || + \ col - 1 > s:endCol + unl! s:startCol s:origWordLen s:oldVars s:update + return s:RemoveSnippet() + endif + + call s:UpdateVars() + let s:prevLen[1] = col('$') + elseif exists('g:snipPos') + if !a:entering && g:snipPos[s:curPos][2] != -1 + let g:snipPos[s:curPos][2] = -2 + endif + + let col = col('.') + let lnum = line('.') + let changeLine = line('$') - s:prevLen[0] + + if lnum == s:endLine + let s:endCol += col('$') - s:prevLen[1] + let s:prevLen = [line('$'), col('$')] + endif + if changeLine != 0 + let s:endLine += changeLine + let s:endCol = col + endif + + " Delete snippet if cursor moves out of it in insert mode + if (lnum == s:endLine && (col > s:endCol || col < g:snipPos[s:curPos][1])) + \ || lnum > s:endLine || lnum < g:snipPos[s:curPos][0] + call s:RemoveSnippet() + endif + endif +endf + +" This updates the variables in a snippet when a placeholder has been edited. +" (e.g., each "$1" in "${1:foo} $1bar $1bar") +fun s:UpdateVars() + let newWordLen = s:endCol - s:startCol + 1 + let newWord = strpart(getline('.'), s:startCol, newWordLen) + if newWord == s:oldWord || empty(g:snipPos[s:curPos][3]) + return + endif + + let changeLen = g:snipPos[s:curPos][2] - newWordLen + let curLine = line('.') + let startCol = col('.') + let oldStartSnip = s:startCol + let updateTabStops = changeLen != 0 + let i = 0 + + for [lnum, col] in g:snipPos[s:curPos][3] + if updateTabStops + let start = s:startCol + if lnum == curLine && col <= start + let s:startCol -= changeLen + let s:endCol -= changeLen + endif + for nPos in g:snipPos[s:curPos][3][(i):] + " This list is in ascending order, so quit if we've gone too far. + if nPos[0] > lnum | break | endif + if nPos[0] == lnum && nPos[1] > col + let nPos[1] -= changeLen + endif + endfor + if lnum == curLine && col > start + let col -= changeLen + let g:snipPos[s:curPos][3][i][1] = col + endif + let i += 1 + endif + + " "Very nomagic" is used here to allow special characters. + call setline(lnum, substitute(getline(lnum), '\%'.col.'c\V'. + \ escape(s:oldWord, '\'), escape(newWord, '\&'), '')) + endfor + if oldStartSnip != s:startCol + call cursor(0, startCol + s:startCol - oldStartSnip) + endif + + let s:oldWord = newWord + let g:snipPos[s:curPos][2] = newWordLen +endf +" vim:noet:sw=4:ts=4:ft=vim Added: configs/trunk/src/vim/ftplugin/html_snip_helper.vim =================================================================== --- configs/trunk/src/vim/ftplugin/html_snip_helper.vim (rev 0) +++ configs/trunk/src/vim/ftplugin/html_snip_helper.vim 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,10 @@ +" Helper function for (x)html snippets +if exists('s:did_snip_helper') || &cp || !exists('loaded_snips') + finish +endif +let s:did_snip_helper = 1 + +" Automatically closes tag if in xhtml +fun! Close() + return stridx(&ft, 'xhtml') == -1 ? '' : ' /' +endf Added: configs/trunk/src/vim/plugin/snipMate.vim =================================================================== --- configs/trunk/src/vim/plugin/snipMate.vim (rev 0) +++ configs/trunk/src/vim/plugin/snipMate.vim 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,247 @@ +" File: snipMate.vim +" Author: Michael Sanders +" Last Updated: July 13, 2009 +" Version: 0.83 +" Description: snipMate.vim implements some of TextMate's snippets features in +" Vim. A snippet is a piece of often-typed text that you can +" insert into your document using a trigger word followed by a "<tab>". +" +" For more help see snipMate.txt; you can do this by using: +" :helptags ~/.vim/doc +" :h snipMate.txt + +if exists('loaded_snips') || &cp || version < 700 + finish +endif +let loaded_snips = 1 +if !exists('snips_author') | let snips_author = 'Me' | endif + +au BufRead,BufNewFile *.snippets\= set ft=snippet +au FileType snippet setl noet fdm=indent + +let s:snippets = {} | let s:multi_snips = {} + +if !exists('snippets_dir') + let snippets_dir = substitute(globpath(&rtp, 'snippets/'), "\n", ',', 'g') +endif + +fun! MakeSnip(scope, trigger, content, ...) + let multisnip = a:0 && a:1 != '' + let var = multisnip ? 's:multi_snips' : 's:snippets' + if !has_key({var}, a:scope) | let {var}[a:scope] = {} | endif + if !has_key({var}[a:scope], a:trigger) + let {var}[a:scope][a:trigger] = multisnip ? [[a:1, a:content]] : a:content + elseif multisnip | let {var}[a:scope][a:trigger] += [[a:1, a:content]] + else + echom 'Warning in snipMate.vim: Snippet '.a:trigger.' is already defined.' + \ .' See :h multi_snip for help on snippets with multiple matches.' + endif +endf + +fun! ExtractSnips(dir, ft) + for path in split(globpath(a:dir, '*'), "\n") + if isdirectory(path) + let pathname = fnamemodify(path, ':t') + for snipFile in split(globpath(path, '*.snippet'), "\n") + call s:ProcessFile(snipFile, a:ft, pathname) + endfor + elseif fnamemodify(path, ':e') == 'snippet' + call s:ProcessFile(path, a:ft) + endif + endfor +endf + +" Processes a single-snippet file; optionally add the name of the parent +" directory for a snippet with multiple matches. +fun s:ProcessFile(file, ft, ...) + let keyword = fnamemodify(a:file, ':t:r') + if keyword == '' | return | endif + try + let text = join(readfile(a:file), "\n") + catch /E484/ + echom "Error in snipMate.vim: couldn't read file: ".a:file + endtry + return a:0 ? MakeSnip(a:ft, a:1, text, keyword) + \ : MakeSnip(a:ft, keyword, text) +endf + +fun! ExtractSnipsFile(file, ft) + if !filereadable(a:file) | return | endif + let text = readfile(a:file) + let inSnip = 0 + for line in text + ["\n"] + if inSnip && (line[0] == "\t" || line == '') + let content .= strpart(line, 1)."\n" + continue + elseif inSnip + call MakeSnip(a:ft, trigger, content[:-2], name) + let inSnip = 0 + endif + + if line[:6] == 'snippet' + let inSnip = 1 + let trigger = strpart(line, 8) + let name = '' + let space = stridx(trigger, ' ') + 1 + if space " Process multi snip + let name = strpart(trigger, space) + let trigger = strpart(trigger, 0, space - 1) + endif + let content = '' + endif + endfor +endf + +fun! ResetSnippets() + let s:snippets = {} | let s:multi_snips = {} | let g:did_ft = {} +endf + +let g:did_ft = {} +fun! GetSnippets(dir, filetypes) + for ft in split(a:filetypes, '\.') + if has_key(g:did_ft, ft) | continue | endif + call s:DefineSnips(a:dir, ft, ft) + if ft == 'objc' || ft == 'cpp' || ft == 'cs' + call s:DefineSnips(a:dir, 'c', ft) + elseif ft == 'xhtml' + call s:DefineSnips(a:dir, 'html', 'xhtml') + endif + let g:did_ft[ft] = 1 + endfor +endf + +" Define "aliasft" snippets for the filetype "realft". +fun s:DefineSnips(dir, aliasft, realft) + for path in split(globpath(a:dir, a:aliasft.'/')."\n". + \ globpath(a:dir, a:aliasft.'-*/'), "\n") + call ExtractSnips(path, a:realft) + endfor + for path in split(globpath(a:dir, a:aliasft.'.snippets')."\n". + \ globpath(a:dir, a:aliasft.'-*.snippets'), "\n") + call ExtractSnipsFile(path, a:realft) + endfor +endf + +fun! TriggerSnippet() + if exists('g:SuperTabMappingForward') + if g:SuperTabMappingForward == "<tab>" + let SuperTabKey = "\<c-n>" + elseif g:SuperTabMappingBackward == "<tab>" + let SuperTabKey = "\<c-p>" + endif + endif + + if pumvisible() " Update snippet if completion is used, or deal with supertab + if exists('SuperTabKey') + call feedkeys(SuperTabKey) | return '' + endif + call feedkeys("\<esc>a", 'n') " Close completion menu + call feedkeys("\<tab>") | return '' + endif + + if exists('g:snipPos') | return snipMate#jumpTabStop(0) | endif + + let word = matchstr(getline('.'), '\S\+\%'.col('.').'c') + for scope in [bufnr('%')] + split(&ft, '\.') + ['_'] + let [trigger, snippet] = s:GetSnippet(word, scope) + " If word is a trigger for a snippet, delete the trigger & expand + " the snippet. + if snippet != '' + let col = col('.') - len(trigger) + sil exe 's/\V'.escape(trigger, '/.').'\%#//' + return snipMate#expandSnip(snippet, col) + endif + endfor + + if exists('SuperTabKey') + call feedkeys(SuperTabKey) + return '' + endif + return "\<tab>" +endf + +fun! BackwardsSnippet() + if exists('g:snipPos') | return snipMate#jumpTabStop(1) | endif + + if exists('g:SuperTabMappingForward') + if g:SuperTabMappingBackward == "<s-tab>" + let SuperTabKey = "\<c-p>" + elseif g:SuperTabMappingForward == "<s-tab>" + let SuperTabKey = "\<c-n>" + endif + endif + if exists('SuperTabKey') + call feedkeys(SuperTabKey) + return '' + endif + return "\<s-tab>" +endf + +" Check if word under cursor is snippet trigger; if it isn't, try checking if +" the text after non-word characters is (e.g. check for "foo" in "bar.foo") +fun s:GetSnippet(word, scope) + let word = a:word | let snippet = '' + while snippet == '' + if exists('s:snippets["'.a:scope.'"]["'.escape(word, '\"').'"]') + let snippet = s:snippets[a:scope][word] + elseif exists('s:multi_snips["'.a:scope.'"]["'.escape(word, '\"').'"]') + let snippet = s:ChooseSnippet(a:scope, word) + if snippet == '' | break | endif + else + if match(word, '\W') == -1 | break | endif + let word = substitute(word, '.\{-}\W', '', '') + endif + endw + if word == '' && a:word != '.' && stridx(a:word, '.') != -1 + let [word, snippet] = s:GetSnippet('.', a:scope) + endif + return [word, snippet] +endf + +fun s:ChooseSnippet(scope, trigger) + let snippet = [] + let i = 1 + for snip in s:multi_snips[a:scope][a:trigger] + let snippet += [i.'. '.snip[0]] + let i += 1 + endfor + if i == 2 | return s:multi_snips[a:scope][a:trigger][0][1] | endif + let num = inputlist(snippet) - 1 + return num == -1 ? '' : s:multi_snips[a:scope][a:trigger][num][1] +endf + +fun! ShowAvailableSnips() + let line = getline('.') + let col = col('.') + let word = matchstr(getline('.'), '\S\+\%'.col.'c') + let words = [word] + if stridx(word, '.') + let words += split(word, '\.', 1) + endif + let matchlen = 0 + let matches = [] + for scope in [bufnr('%')] + split(&ft, '\.') + ['_'] + let triggers = has_key(s:snippets, scope) ? keys(s:snippets[scope]) : [] + if has_key(s:multi_snips, scope) + let triggers += keys(s:multi_snips[scope]) + endif + for trigger in triggers + for word in words + if word == '' + let matches += [trigger] " Show all matches if word is empty + elseif trigger =~ '^'.word + let matches += [trigger] + let len = len(word) + if len > matchlen | let matchlen = len | endif + endif + endfor + endfor + endfor + + " This is to avoid a bug with Vim when using complete(col - matchlen, matches) + " (Issue#46 on the Google Code snipMate issue tracker). + call setline(line('.'), substitute(line, repeat('.', matchlen).'\%'.col.'c', '', '')) + call complete(col, matches) + return '' +endf +" vim:noet:sw=4:ts=4:ft=vim Added: configs/trunk/src/vim/snippets/_.snippets =================================================================== --- configs/trunk/src/vim/snippets/_.snippets (rev 0) +++ configs/trunk/src/vim/snippets/_.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,7 @@ +# Global snippets + +# (c) holds no legal value ;) +snippet c) + `&enc[:2] == "utf" ? "©" : "(c)"` Copyright `strftime("%Y")` ${1:`g:snips_author`}. All Rights Reserved.${2} +snippet date + `strftime("%Y-%m-%d")` Added: configs/trunk/src/vim/snippets/autoit.snippets =================================================================== --- configs/trunk/src/vim/snippets/autoit.snippets (rev 0) +++ configs/trunk/src/vim/snippets/autoit.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,66 @@ +snippet if + If ${1:condition} Then + ${2:; True code} + EndIf +snippet el + Else + ${1} +snippet elif + ElseIf ${1:condition} Then + ${2:; True code} +# If/Else block +snippet ifel + If ${1:condition} Then + ${2:; True code} + Else + ${3:; Else code} + EndIf +# If/ElseIf/Else block +snippet ifelif + If ${1:condition 1} Then + ${2:; True code} + ElseIf ${3:condition 2} Then + ${4:; True code} + Else + ${5:; Else code} + EndIf +# Switch block +snippet switch + Switch (${1:condition}) + Case {$2:case1}: + {$3:; Case 1 code} + Case Else: + {$4:; Else code} + EndSwitch +# Select block +snippet select + Select (${1:condition}) + Case {$2:case1}: + {$3:; Case 1 code} + Case Else: + {$4:; Else code} + EndSelect +# While loop +snippet while + While (${1:condition}) + ${2:; code...} + WEnd +# For loop +snippet for + For ${1:n} = ${3:1} to ${2:count} + ${4:; code...} + Next +# New Function +snippet func + Func ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + ${4:Return} + EndFunc +# Message box +snippet msg + MsgBox(${3:MsgType}, ${1:"Title"}, ${2:"Message Text"}) +# Debug Message +snippet debug + MsgBox(0, "Debug", ${1:"Debug Message"}) +# Show Variable Debug Message +snippet showvar + MsgBox(0, "${1:VarName}", $1) Added: configs/trunk/src/vim/snippets/c.snippets =================================================================== --- configs/trunk/src/vim/snippets/c.snippets (rev 0) +++ configs/trunk/src/vim/snippets/c.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,110 @@ +# main() +snippet main + int main(int argc, const char *argv[]) + { + ${1} + return 0; + } +# #include <...> +snippet inc + #include <${1:stdio}.h>${2} +# #include "..." +snippet Inc + #include "${1:`Filename("$1.h")`}"${2} +# #ifndef ... #define ... #endif +snippet Def + #ifndef $1 + #define ${1:SYMBOL} ${2:value} + #endif${3} +snippet def + #define +snippet ifdef + #ifdef ${1:FOO} + ${2:#define } + #endif +snippet #if + #if ${1:FOO} + ${2} + #endif +# Header Include-Guard +# (the randomizer code is taken directly from TextMate; it could probably be +# cleaner, I don't know how to do it in vim script) +snippet once + #ifndef ${1:`toupper(Filename('', 'UNTITLED').'_'.system("/usr/bin/ruby -e 'print (rand * 2821109907455).round.to_s(36)'"))`} + + #define $1 + + ${2} + + #endif /* end of include guard: $1 */ +# If Condition +snippet if + if (${1:/* condition */}) { + ${2:/* code */} + } +snippet el + else { + ${1} + } +# Tertiary conditional +snippet t + ${1:/* condition */} ? ${2:a} : ${3:b} +# Do While Loop +snippet do + do { + ${2:/* code */} + } while (${1:/* condition */}); +# While Loop +snippet wh + while (${1:/* condition */}) { + ${2:/* code */} + } +# For Loop +snippet for + for (${2:i} = 0; $2 < ${1:count}; $2${3:++}) { + ${4:/* code */} + } +# Custom For Loop +snippet forr + for (${1:i} = ${2:0}; ${3:$1 < 10}; $1${4:++}) { + ${5:/* code */} + } +# Function +snippet fun + ${1:void} ${2:function_name}(${3}) + { + ${4:/* code */} + } +# Function Declaration +snippet fund + ${1:void} ${2:function_name}(${3});${4} +# Typedef +snippet td + typedef ${1:int} ${2:MyCustomType};${3} +# Struct +snippet st + struct ${1:`Filename('$1_t', 'name')`} { + ${2:/* data */} + }${3: /* optional variable list */};${4} +# Typedef struct +snippet tds + typedef struct ${2:_$1 }{ + ${3:/* data */} + } ${1:`Filename('$1_t', 'name')`}; +# Typdef enum +snippet tde + typedef enum { + ${1:/* data */} + } ${2:foo}; +# printf +# unfortunately version this isn't as nice as TextMates's, given the lack of a +# dynamic `...` +snippet pr + printf("${1:%s}\n"${2});${3} +# fprintf (again, this isn't as nice as TextMate's version, but it works) +snippet fpr + fprintf(${1:stderr}, "${2:%s}\n"${3});${4} +snippet . + [${1}]${2} +snippet un + unsigned Added: configs/trunk/src/vim/snippets/cpp.snippets =================================================================== --- configs/trunk/src/vim/snippets/cpp.snippets (rev 0) +++ configs/trunk/src/vim/snippets/cpp.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,30 @@ +# Read File Into Vector +snippet readfile + std::vector<char> v; + if (FILE *${2:fp} = fopen(${1:"filename"}, "r")) { + char buf[1024]; + while (size_t len = fread(buf, 1, sizeof(buf), $2)) + v.insert(v.end(), buf, buf + len); + fclose($2); + }${3} +# std::map +snippet map + std::map<${1:key}, ${2:value}> map${3}; +# std::vector +snippet vector + std::vector<${1:char}> v${2}; +# Namespace +snippet ns + namespace ${1:`Filename('', 'my')`} { + ${2} + } /* $1 */ +# Class +snippet cl + class ${1:`Filename('$1_t', 'name')`} { + public: + $1 (${2:arguments}); + virtual ~$1 (); + + private: + ${3:/* data */} + }; Added: configs/trunk/src/vim/snippets/html.snippets =================================================================== --- configs/trunk/src/vim/snippets/html.snippets (rev 0) +++ configs/trunk/src/vim/snippets/html.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,190 @@ +# Some useful Unicode entities +# Non-Breaking Space +snippet nbs + +# ← +snippet left + ← +# → +snippet right + → +# ↑ +snippet up + ↑ +# ↓ +snippet down + ↓ +# ↩ +snippet return + ↩ +# ⇤ +snippet backtab + ⇤ +# ⇥ +snippet tab + ⇥ +# ⇧ +snippet shift + ⇧ +# ⌃ +snippet control + ⌃ +# ⌅ +snippet enter + ⌅ +# ⌘ +snippet command + ⌘ +# ⌥ +snippet option + ⌥ +# ⌦ +snippet delete + ⌦ +# ⌫ +snippet backspace + ⌫ +# ⎋ +snippet escape + ⎋ +# Generic Doctype +snippet doctype HTML 4.01 Strict + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"" + "http://www.w3.org/TR/html4/strict.dtd"> +snippet doctype HTML 4.01 Transitional + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"" + "http://www.w3.org/TR/html4/loose.dtd"> +snippet doctype HTML 5 + <!DOCTYPE HTML> +snippet doctype XHTML 1.0 Frameset + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +snippet doctype XHTML 1.0 Strict + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +snippet doctype XHTML 1.0 Transitional + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +snippet doctype XHTML 1.1 + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +# HTML Doctype 4.01 Strict +snippet docts + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"" + "http://www.w3.org/TR/html4/strict.dtd"> +# HTML Doctype 4.01 Transitional +snippet doct + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"" + "http://www.w3.org/TR/html4/loose.dtd"> +# HTML Doctype 5 +snippet doct5 + <!DOCTYPE HTML> +# XHTML Doctype 1.0 Frameset +snippet docxf + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> +# XHTML Doctype 1.0 Strict +snippet docxs + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +# XHTML Doctype 1.0 Transitional +snippet docxt + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +# XHTML Doctype 1.1 +snippet docx + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +snippet html + <html> + ${1} + </html> +snippet xhtml + <html xmlns="http://www.w3.org/1999/xhtml"> + ${1} + </html> +snippet body + <body> + ${1} + </body> +snippet head + <head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"`Close()`> + + <title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title> + ${2} + </head> +snippet title + <title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>${2} +snippet script + <script type="text/javascript" charset="utf-8"> + ${1} + </script>${2} +snippet scriptsrc + <script src="${1}.js" type="text/javascript" charset="utf-8"></script>${2} +snippet style + <style type="text/css" media="${1:screen}"> + ${2} + </style>${3} +snippet base + <base href="${1}" target="${2}"`Close()`> +snippet r + <br`Close()[1:]`> +snippet div + <div id="${1:name}"> + ${2} + </div> +# Embed QT Movie +snippet movie + <object width="$2" height="$3" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" + codebase="http://www.apple.com/qtactivex/qtplugin.cab"> + <param name="src" value="$1"`Close()`> + <param name="controller" value="$4"`Close()`> + <param name="autoplay" value="$5"`Close()`> + <embed src="${1:movie.mov}" + width="${2:320}" height="${3:240}" + controller="${4:true}" autoplay="${5:true}" + scale="tofit" cache="true" + pluginspage="http://www.apple.com/quicktime/download/" + `Close()[1:]`> + </object>${6} +snippet fieldset + <fieldset id="$1"> + <legend>${1:name}</legend> + + ${3} + </fieldset> +snippet form + <form action="${1:`Filename('$1_submit')`}" method="${2:get}" accept-charset="utf-8"> + ${3} + + + <p><input type="submit" value="Continue →"`Close()`></p> + </form> +snippet h1 + <h1 id="${1:heading}">${2:$1}</h1> +snippet input + <input type="${1:text/submit/hidden/button}" name="${2:some_name}" value="${3}"`Close()`>${4} +snippet label + <label for="${2:$1}">${1:name}</label><input type="${3:text/submit/hidden/button}" name="${4:$2}" value="${5}" id="${6:$2}"`Close()`>${7} +snippet link + <link rel="${1:stylesheet}" href="${2:/css/master.css}" type="text/css" media="${3:screen}" charset="utf-8"`Close()`>${4} +snippet mailto + <a href="mailto:${1:jo...@ex...}?subject=${2:feedback}">${3:email me}</a> +snippet meta + <meta name="${1:name}" content="${2:content}"`Close()`>${3} +snippet opt + <option value="${1:option}">${2:$1}</option>${3} +snippet optt + <option>${1:option}</option>${2} +snippet select + <select name="${1:some_name}" id="${2:$1}"> + <option value="${3:option}">${4:$3}</option> + </select>${5} +snippet table + <table border="${1:0}"> + <tr><th>${2:Header}</th></tr> + <tr><th>${3:Data}</th></tr> + </table>${4} +snippet textarea + <textarea name="${1:Name}" rows="${2:8}" cols="${3:40}">${4}</textarea>${5} Added: configs/trunk/src/vim/snippets/java.snippets =================================================================== --- configs/trunk/src/vim/snippets/java.snippets (rev 0) +++ configs/trunk/src/vim/snippets/java.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,78 @@ +snippet main + public static void main (String [] args) + { + ${1:/* code */} + } +snippet pu + public +snippet po + protected +snippet pr + private +snippet st + static +snippet fi + final +snippet ab + abstract +snippet re + return +snippet br + break; +snippet de + default: + ${1} +snippet ca + catch(${1:Exception} ${2:e}) ${3} +snippet th + throw +snippet sy + synchronized +snippet im + import +snippet j.u + java.util +snippet j.i + java.io. +snippet j.b + java.beans. +snippet j.n + java.net. +snippet j.m + java.math. +snippet if + if (${1}) ${2} +snippet el + else +snippet elif + else if (${1}) ${2} +snippet wh + while (${1}) ${2} +snippet for + for (${1}; ${2}; ${3}) ${4} +snippet fore + for (${1} : ${2}) ${3} +snippet sw + switch (${1}) ${2} +snippet cs + case ${1}: + ${2} + ${3} +snippet tc + public class ${1:`Filename()`} extends ${2:TestCase} +snippet t + public void test${1:Name}() throws Exception ${2} +snippet cl + class ${1:`Filename("", "untitled")`} ${2} +snippet in + interface ${1:`Filename("", "untitled")`} ${2:extends Parent}${3} +snippet m + ${1:void} ${2:method}(${3}) ${4:throws }${5} +snippet v + ${1:String} ${2:var}${3: = null}${4};${5} +snippet co + static public final ${1:String} ${2:var} = ${3};${4} +snippet cos + static public final String ${1:var} = "${2}";${3} +snippet as + assert ${1:test} : "${2:Failure message}";${3} Added: configs/trunk/src/vim/snippets/javascript.snippets =================================================================== --- configs/trunk/src/vim/snippets/javascript.snippets (rev 0) +++ configs/trunk/src/vim/snippets/javascript.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,74 @@ +# Prototype +snippet proto + ${1:class_name}.prototype.${2:method_name} = + function(${3:first_argument}) { + ${4:// body...} + }; +# Function +snippet fun + function ${1:function_name} (${2:argument}) { + ${3:// body...} + } +# Anonymous Function +snippet f + function(${1}) {${2}}; +# if +snippet if + if (${1:true}) {${2}}; +# if ... else +snippet ife + if (${1:true}) {${2}} + else{${3}}; +# tertiary conditional +snippet t + ${1:/* condition */} ? ${2:a} : ${3:b} +# switch +snippet switch + switch(${1:expression}) { + case '${3:case}': + ${4:// code} + break; + ${5} + default: + ${2:// code} + } +# case +snippet case + case '${1:case}': + ${2:// code} + break; + ${3} +# for (...) {...} +snippet for + for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3:++}) { + ${4:$1[$2]} + }; +# for (...) {...} (Improved Native For-Loop) +snippet forr + for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3:--}) { + ${4:$1[$2]} + }; +# while (...) {...} +snippet wh + while (${1:/* condition */}) { + ${2:/* code */} + } +# do...while +snippet do + do { + ${2:/* code */} + } while (${1:/* condition */}); +# Object Method +snippet :f + ${1:method_name}: function(${2:attribute}) { + ${4} + }${3:,} +# setTimeout function +snippet timeout + setTimeout(function() {${3}}${2}, ${1:10}; +# Get Elements +snippet get + getElementsBy${1:TagName}('${2}')${3} +# Get Element +snippet gett + getElementBy${1:Id}('${2}')${3} Added: configs/trunk/src/vim/snippets/mako.snippets =================================================================== --- configs/trunk/src/vim/snippets/mako.snippets (rev 0) +++ configs/trunk/src/vim/snippets/mako.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,54 @@ +snippet def + <%def name="${1:name}"> + ${2:} + </%def> +snippet call + <%call expr="${1:name}"> + ${2:} + </%call> +snippet doc + <%doc> + ${1:} + </%doc> +snippet text + <%text> + ${1:} + </%text> +snippet for + % for ${1:i} in ${2:iter}: + ${3:} + % endfor +snippet if if + % if ${1:condition}: + ${2:} + % endif +snippet if if/else + % if ${1:condition}: + ${2:} + % else: + ${3:} + % endif +snippet try + % try: + ${1:} + % except${2:}: + ${3:pass} + % endtry +snippet wh + % while ${1:}: + ${2:} + % endwhile +snippet $ + ${ ${1:} } +snippet <% + <% ${1:} %> +snippet <!% + <!% ${1:} %> +snippet inherit + <%inherit file="${1:filename}" /> +snippet include + <%include file="${1:filename}" /> +snippet namespace + <%namespace file="${1:name}" /> +snippet page + <%page args="${1:}" /> Added: configs/trunk/src/vim/snippets/objc.snippets =================================================================== --- configs/trunk/src/vim/snippets/objc.snippets (rev 0) +++ configs/trunk/src/vim/snippets/objc.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,184 @@ +# #import <...> +snippet Imp + #import <${1:Cocoa/Cocoa.h}>${2} +# #import "..." +snippet imp + #import "${1:`Filename()`.h}"${2} +# @selector(...) +snippet sel + @selector(${1:method}:)${3} +# @"..." string +snippet s + @"${1}"${2} +# Object +snippet o + ${1:NSObject} *${2:foo} = [${3:$1 alloc}]${4};${5} +# NSLog(...) +snippet log + NSLog(@"${1:%@}"${2});${3} +# Class +snippet objc + @interface ${1:`Filename('', 'someClass')`} : ${2:NSObject} + { + } + @end + + @implementation $1 + ${3} + @end +# Class Interface +snippet int + @interface ${1:`Filename('', 'someClass')`} : ${2:NSObject} + {${3} + } + ${4} + @end +# Class Implementation +snippet impl + @implementation ${1:`Filename('', 'someClass')`} + ${2} + @end +snippet init + - (id)init + { + [super init]; + return self; + } +snippet ifself + if (self = [super init]) { + ${1:/* code */} + } + return self; +snippet ibo + IBOutlet ${1:NSSomeClass} *${2:$1};${3} +# Category +snippet cat + @interface ${1:NSObject} (${2:Category}) + @end + + @implementation $1 ($2) + ${3} + @end +# Category Interface +snippet cath + @interface ${1:NSObject} (${2:Category}) + ${3} + @end +# NSArray +snippet array + NSMutableArray *${1:array} = [NSMutable array];${2} +# NSDictionary +snippet dict + NSMutableDictionary *${1:dict} = [NSMutableDictionary dictionary];${2} +# NSBezierPath +snippet bez + NSBezierPath *${1:path} = [NSBezierPath bezierPath];${2} +# Method +snippet m + - (${1:id})${2:method} + { + ${3} + } +# Method declaration +snippet md + - (${1:id})${2:method};${3} +# IBAction declaration +snippet ibad + - (IBAction)${1:method}:(${2:id})sender;${3} +# IBAction method +snippet iba + - (IBAction)${1:method}:(${2:id})sender + { + ${3} + } +# awakeFromNib method +snippet wake + - (void)awakeFromNib + { + ${1} + } +# Class Method +snippet M + + (${1:id})${2:method} + {${3} + return nil; + } +# Sub-method (Call super) +snippet sm + - (${1:id})${2:method} + { + [super $2];${3} + return self; + } +# Method: Initialize +snippet I + + (void) initialize + { + [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWIthObjectsAndKeys: + ${1}@"value", @"key", + nil]]; + } +# Accessor Methods For: +# Object +snippet objacc + - (${1:id})${2:thing} + { + return $2; + } + + - (void)set$2:($1)${3:new$2} + { + [$3 retain]; + [$2 release]; + $2 = $3; + }${4} +# for (object in array) +snippet forin + for (${1:Class} *${2:some$1} in ${3:array}) { + ${4} + } +snippet forarray + unsigned int ${1:object}Count = [${2:array} count]; + + for (unsigned int index = 0; index < $1Count; index++) { + ${3:id} $1 = [$2 $1AtIndex:index]; + ${4} + } +# IBOutlet +# @property (Objective-C 2.0) +snippet prop + @property (${1:retain}) ${2:NSSomeClass} ${3:*$2};${4} +# @synthesize (Objective-C 2.0) +snippet syn + @synthesize ${1:property};${2} +# [[ alloc] init] +snippet alloc + [[${1:foo} alloc] init${2}];${3} +# retain +snippet ret + [${1:foo} retain];${2} +# release +snippet rel + [${1:foo} release]; + ${2:$1 = nil;} +# autorelease +snippet arel + [${1:foo} autorelease]; +# autorelease pool +snippet pool + NSAutoreleasePool *${1:pool} = [[NSAutoreleasePool alloc] init]; + ${2:/* code */} + [$1 drain]; +# Throw an exception +snippet except + NSException *${1:badness}; + $1 = [NSException exceptionWithName:@"${2:$1Name}" + reason:@"${3}" + userInfo:nil]; + [$1 raise]; +snippet prag + #pragma mark ${1:foo} +snippet cl + @class ${1:Foo};${2} +snippet color + [[NSColor ${1:blackColor}] set]; Added: configs/trunk/src/vim/snippets/perl.snippets =================================================================== --- configs/trunk/src/vim/snippets/perl.snippets (rev 0) +++ configs/trunk/src/vim/snippets/perl.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,91 @@ +# #!/usr/bin/perl +snippet #! + #!/usr/bin/perl + +# Hash Pointer +snippet . + => +# Function +snippet sub + sub ${1:function_name} { + ${2:#body ...} + } +# Conditional +snippet if + if (${1}) { + ${2:# body...} + } +# Conditional if..else +snippet ife + if (${1}) { + ${2:# body...} + } else { + ${3:# else...} + } +# Conditional if..elsif..else +snippet ifee + if (${1}) { + ${2:# body...} + } elsif (${3}) { + ${4:# elsif...} + } else { + ${5:# else...} + } +# Conditional One-line +snippet xif + ${1:expression} if ${2:condition};${3} +# Unless conditional +snippet unless + unless (${1}) { + ${2:# body...} + } +# Unless conditional One-line +snippet xunless + ${1:expression} unless ${2:condition};${3} +# Try/Except +snippet eval + eval { + ${1:# do something risky...} + }; + if ($@) { + ${2:# handle failure...} + } +# While Loop +snippet wh + while (${1}) { + ${2:# body...} + } +# While Loop One-line +snippet xwh + ${1:expression} while ${2:condition};${3} +# For Loop +snippet for + for (my $${2:var} = 0; $$2 < ${1:count}; $$2${3:++}) { + ${4:# body...} + } +# Foreach Loop +snippet fore + foreach my $${1:x} (@${2:array}) { + ${3:# body...} + } +# Foreach Loop One-line +snippet xfore + ${1:expression} foreach @${2:array};${3} +# Package +snippet cl + package ${1:ClassName}; + + use base qw(${2:ParentClass}); + + sub new { + my $class = shift; + $class = ref $class if ref $class; + my $self = bless {}, $class; + $self; + } + + 1;${3} +# Read File +snippet slurp + my $${1:var}; + { local $/ = undef; local *FILE; open FILE, "<${2:file}"; $$1 = <FILE>; close FILE }${3} Added: configs/trunk/src/vim/snippets/php.snippets =================================================================== --- configs/trunk/src/vim/snippets/php.snippets (rev 0) +++ configs/trunk/src/vim/snippets/php.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,216 @@ +snippet php + <?php + ${1} + ?> +snippet ec + echo "${1:string}"${2}; +snippet inc + include '${1:file}';${2} +snippet inc1 + include_once '${1:file}';${2} +snippet req + require '${1:file}';${2} +snippet req1 + require_once '${1:file}';${2} +# $GLOBALS['...'] +snippet globals + $GLOBALS['${1:variable}']${2: = }${3:something}${4:;}${5} +snippet $_ COOKIE['...'] + $_COOKIE['${1:variable}']${2} +snippet $_ ENV['...'] + $_ENV['${1:variable}']${2} +snippet $_ FILES['...'] + $_FILES['${1:variable}']${2} +snippet $_ Get['...'] + $_GET['${1:variable}']${2} +snippet $_ POST['...'] + $_POST['${1:variable}']${2} +snippet $_ REQUEST['...'] + $_REQUEST['${1:variable}']${2} +snippet $_ SERVER['...'] + $_SERVER['${1:variable}']${2} +snippet $_ SESSION['...'] + $_SESSION['${1:variable}']${2} +# Start Docblock +snippet /* + /** + * ${1} + **/ +# Class - post doc +snippet doc_cp + /** + * ${1:undocumented class} + * + * @package ${2:default} + * @author ${3:`g:snips_author`} + **/${4} +# Class Variable - post doc +snippet doc_vp + /** + * ${1:undocumented class variable} + * + * @var ${2:string} + **/${3} +# Class Variable +snippet doc_v + /** + * ${3:undocumented class variable} + * + * @var ${4:string} + **/ + ${1:var} $${2};${5} +# Class +snippet doc_c + /** + * ${3:undocumented class} + * + * @packaged ${4:default} + * @author ${5:`g:snips_author`} + **/ + ${1:}class ${2:} + {${6} + } // END $1class $2 +# Constant Definition - post doc +snippet doc_dp + /** + * ${1:undocumented constant} + **/${2} +# Constant Definition +snippet doc_d + /** + * ${3:undocumented constant} + **/ + define(${1}, ${2});${4} +# Function - post doc +snippet doc_fp + /** + * ${1:undocumented function} + * + * @return ${2:void} + * @author ${3:`g:snips_author`} + **/${4} +# Function signature +snippet doc_s + /** + * ${4:undocumented function} + * + * @return ${5:void} + * @author ${6:`g:snips_author`} + **/ + ${1}function ${2}(${3});${7} +# Function +snippet doc_f + /** + * ${4:undocumented function} + * + * @return ${5:void} + * @author ${6:`g:snips_author`} + **/ + ${1}function ${2}(${3}) + {${7} + } +# Header +snippet doc_h + /** + * ${1} + * + * @author ${2:`g:snips_author`} + * @version ${3:$Id$} + * @copyright ${4:$2}, `strftime('%d %B, %Y')` + * @package ${5:default} + **/ + + /** + * Define DocBlock + *// +# Interface +snippet doc_i + /** + * ${2:undocumented class} + * + * @package ${3:default} + * @author ${4:`g:snips_author`} + **/ + interface ${1:} + {${5} + } // END interface $1 +# class ... +snippet class + /** + * ${1} + **/ + class ${2:ClassName} + { + ${3} + function ${4:__construct}(${5:argument}) + { + ${6:// code...} + } + } +# define(...) +snippet def + define('${1}'${2});${3} +# defined(...) +snippet def? + ${1}defined('${2}')${3} +snippet wh + while (${1:/* condition */}) { + ${2:// code...} + } +# do ... while +snippet do + do { + ${2:// code... } + } while (${1:/* condition */}); +snippet if + if (${1:/* condition */}) { + ${2:// code...} + } +snippet ife + if (${1:/* condition */}) { + ${2:// code...} + } else { + ${3:// code...} + } + ${4} +snippet else + else { + ${1:// code...} + } +snippet elseif + elseif (${1:/* condition */}) { + ${2:// code...} + } +# Tertiary conditional +snippet t + $${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b};${5} +snippet switch + switch ($${1:variable}) { + case '${2:value}': + ${3:// code...} + break; + ${5} + default: + ${4:// code...} + break; + } +snippet case + case '${1:value}': + ${2:// code...} + break;${3} +snippet for + for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) { + ${4: // code...} + } +snippet foreach + foreach ($${1:variable} as $${2:key}) { + ${3:// code...} + } +snippet fun + ${1:public }function ${2:FunctionName}(${3}) + { + ${4:// code...} + } +# $... = array (...) +snippet array + $${1:arrayName} = array('${2}' => ${3});${4} Added: configs/trunk/src/vim/snippets/python.snippets =================================================================== --- configs/trunk/src/vim/snippets/python.snippets (rev 0) +++ configs/trunk/src/vim/snippets/python.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,86 @@ +snippet #! + #!/usr/bin/python + +snippet imp + import ${1:module} +# Module Docstring +snippet docs + ''' + File: ${1:`Filename('$1.py', 'foo.py')`} + Author: ${2:`g:snips_author`} + Description: ${3} + ''' +snippet wh + while ${1:condition}: + ${2:# code...} +snippet for + for ${1:needle} in ${2:haystack}: + ${3:# code...} +# New Class +snippet cl + class ${1:ClassName}(${2:object}): + """${3:docstring for $1}""" + def __init__(self, ${4:arg}): + ${5:super($1, self).__init__()} + self.$4 = $4 + ${6} +# New Function +snippet def + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + """${3:docstring for $1}""" + ${4:pass} +snippet deff + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + ${3} +# New Method +snippet defs + def ${1:mname}(self, ${2:arg}): + ${3:pass} +# New Property +snippet property + def ${1:foo}(): + doc = "${2:The $1 property.}" + def fget(self): + ${3:return self._$1} + def fset(self, value): + ${4:self._$1 = value} +# Lambda +snippet ld + ${1:var} = lambda ${2:vars} : ${3:action} +snippet . + self. +snippet try Try/Except + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} +snippet try Try/Except/Else + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + else: + ${5:pass} +snippet try Try/Except/Finally + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + finally: + ${5:pass} +snippet try Try/Except/Else/Finally + try: + ${1:pass} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + else: + ${5:pass} + finally: + ${6:pass} +# if __name__ == '__main__': +snippet ifmain + if __name__ == '__main__': + ${1:main()} +# __magic__ +snippet _ + __${1:init}__${2} Added: configs/trunk/src/vim/snippets/ruby.snippets =================================================================== --- configs/trunk/src/vim/snippets/ruby.snippets (rev 0) +++ configs/trunk/src/vim/snippets/ruby.snippets 2010-01-25 03:39:43 UTC (rev 1551) @@ -0,0 +1,420 @@ +# #!/usr/bin/ruby +snippet #! + #!/usr/bin/ruby + +# New Block +snippet =b + =begin rdoc + ${1} + =end +snippet y + :yields: ${1:arguments} +snippet rb + #!/usr/bin/env ruby -wKU + +snippet req + require "${1}"${2} +snippet # + # => +snippet end + __END__ +snippet case + case ${1:object} + when ${2:condition} + ${3} + end +snippet when + when ${1:condition} + ${2} +snippet def + def ${1:method_name} + ${2} + end +snippet deft + def test_${1:case_name} + ${2} + end +snippet if + if ${1:condition} + ${2} + end +snippet ife + if ${1:condition} + ${2} + else + ${3} + end +snippet elsif + elsif ${1:condition} + ${2} +snippet unless + unless ${1:condition} + ${2} + end +snippet while + while ${1:condition} + ${2} + end +snippet until + until ${1:condition} + ${2} + end +snippet cla class .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} + ${2} + end +snippet cla class .. initialize .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} + def initialize(${2:args}) + ${3} + end + + + end +snippet cla class .. < ParentClass .. initialize .. end + class ${1:`substitute(Filename(), '^.', '\u&', '')`} < ${2:ParentClass} + def initialize(${3:args}) + ${4} + end + + + end +snippet cla ClassName = Struct .. do .. end + ${1:`substitute(Filename(), '^.', '\u&', '')`} = Struct.new(:${2:attr_names}) do + def ${3:method_name} + ${4} + end + + + end +snippet cla class BlankSlate .. initialize .. end + class ${1:BlankSlate} + instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ } +snippet cla class << self .. end + class << ${1:self} + ${2} + end +# class .. < DelegateClass .. initialize .. end +snippet cla- + class ${1:`substitute(Filename(), '^.', '\u&', '')`} < DelegateClass(${2:ParentClass}) + def initialize(${3:args}) + super(${4:del_obj}) + + ${5} + end + + + end +snippet mod module .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + ${2} + end +snippet mod module .. module_function .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + module_function + + ${2} + end +snippet mod module .. ClassMethods .. end + module ${1:`substitute(Filename(), '^.', '\u&', '')`} + module ClassMethods + ${2} + end + + module InstanceMethods + + end + + def self.included(receiver) + receiver.extend ClassMethods + receiver.send :include, InstanceMethods + end + end +# attr_reader +snippet r + attr_reader :${1:attr_names} +# attr_writer +snippet w + attr_writer :${1:attr_names} +# attr_accessor +snippet rw + attr_accessor :${1:attr_names} +# include Enumerable +snippet Enum + include Enumerable + + def each(&block) + ${1} + end +# include Comparable +snippet Comp + include Comparable + + def <=>(other) + ${1} + end +# extend Forwardable +snippet Forw- + extend Forwardable +# def self +snippet defs + def self.${1:class_method_name} + ${2} + end +# def method_missing +snippet defmm + def method_missing(meth, *args, &blk) + ${1} + end +snippet defd + def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name} +snippet defds + def_delegators :${1:@del_obj}, :${2:del_methods} +snippet am + alias_method :${1:new_name}, :${2:old_name} +snippet app + if __FILE__ == $PROGRAM_NAME + ${1} + end +# usage_if() +snippet usai + if ARGV.${1} + abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3} + end +# usage_unless() +snippet usau + unless ARGV.${1} + abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3} + end +snippet array + Array.new(${1:10}) { |${2:i}| ${3} } +snippet hash + Hash.new { |${1:hash}, ${2:key}| $1[$2] = ${3} } +snippet file File.foreach() { |line| .. } + File.foreach(${1:"path/to/file"}) { |${2:line}| ${3} } +snippet file File.read() + File.read(${1:"path/to/file"})${2} +snippet Dir Dir.global() { |file| .. } + Dir.glob(${1:"dir/glob/*"}) { |${2:file}| ${3} } +snippet Dir Dir[".."] + Dir[${1:"glob/**/*.rb"}]${2} +snippet dir + Filename.dirname(__FILE__) +snippet deli + delete_if { |${1:e}| ${2} } +snippet fil + fill(${1:range}) { |${2:i}| ${3} } +# flatten_once() +snippet flao + inject(Array.new) { |${1:arr}, ${2:a}| $1.push(*$2)}${3} +snippet zip + zip(${1:enums}) { |${2:row}| ${3} } +# downto(0) { |n| .. } +snippet dow + downto(${1:0}) { |${2:n}| ${3} } +snippet ste + step(${1:2}) { |${2:n}| ${3} } +snippet tim + times { |${1:n}| ${2} } +snippet upt + upto(${1:1.0/0.0}) { |${2:n}| ${3} } +snippet loo + loop { ${1} } +snippet ea + each { |${1:e}| ${2} } +snippet eab + each_byte { |${1:byte}| ${2} } +snippet eac- each_char { |chr| .. } + each_char { |${1:chr}| ${2} } +snippet eac- each_cons(..) { |group| .. } + each_cons(${1:2}) { |${2:group}| ${3} } +snippet eai + each_index { |${1:i}| ${2} } +snippet eak + each_key { |${1:key}| ${2} } +snippet eal + each_line { |${1:line}| ${2} } +snippet eap + each_pair { |${1:name}, ${2:val}| ${3} } +snippet eas- + each_slice(${1:2}) { |${2:group}| ${3} } +snippet eav + each_value { |${1:val}| ${2} } +snippet eawi + each_with_index { |${1:e}, ${2:i}| ${3} } +snippet reve + reverse_each { |${1:e}| ${2} } +snippet inj + inject(${1:init}) { |${2:mem}, ${3:var}| ${4} } +snippet map + map { |${1:e}| ${2} } +snippet mapwi- + enum_with_index.map { |${1:e}, ${2:i}| ${3} } +snippet sor + sort { |a, b| ${1} } +snippet sorb + sort_by { |${1:e}| ${2} } +snippet ran + sort_by { rand } +snippet all + all? { |${1:e}| ${2} } +snippet any + any? { |${1:e}| ${2} } +snippet cl + classify { |${1:e}| ${2} } +snippet col + collect { |${1:e}| ${2} } +snippet det + detect { |${1:e}| ${2} } +snippet fet + fetch(${1:name}) { |${2:key}| ${3} } +snippet fin + find { |${1:e}| ${2} } +snippet fina + find_all { |${1:e}| ${2} } +snippet gre + grep(${1:/pattern/}) { |${2:match}| ${3} } +snippet sub + ${1:g}sub(${2:/pattern/}) { |${3:match}| ${4} } +snippet sca + scan(${1:/pattern/}) { |${2:match}| ${3} } +snippet max + max { |a, b|, ${1} } +snippet min + min { |a, b|, ${1} } +snippet par + partition { |${1:e}|, ${2} } +snippet rej + reject { |${1:e}|, ${2} } +snippet sel + select { |${1:e}|, ${2} } +snippet lam + lambda { |${1:args}| ${2} } +snippet do + do |${1:variable}| + ${2} + end +snippet : + :${1:key} => ${2:"value"}${3} +snippet ope + open(${1:"path/or/url/or/pipe"}, "${2:w}") { |${3:io}| ${4} } +# path_from_here() +snippet patfh + File.join(File.dirname(__FILE__), *%2[${1:rel path here}])${2} +# unix_filter {} +snippet unif + ARGF.each_line${1} do |${2:line}| + ${3} + end +# opti... [truncated message content] |
From: <yan...@us...> - 2010-01-25 03:38:54
|
Revision: 1550 http://assorted.svn.sourceforge.net/assorted/?rev=1550&view=rev Author: yangzhang Date: 2010-01-25 03:38:43 +0000 (Mon, 25 Jan 2010) Log Message: ----------- added nerdtree for vim Added Paths: ----------- configs/trunk/src/vim/doc/NERD_tree.txt configs/trunk/src/vim/nerdtree_plugin/ configs/trunk/src/vim/nerdtree_plugin/exec_menuitem.vim configs/trunk/src/vim/nerdtree_plugin/fs_menu.vim configs/trunk/src/vim/plugin/NERD_tree.vim Added: configs/trunk/src/vim/doc/NERD_tree.txt =================================================================== --- configs/trunk/src/vim/doc/NERD_tree.txt (rev 0) +++ configs/trunk/src/vim/doc/NERD_tree.txt 2010-01-25 03:38:43 UTC (rev 1550) @@ -0,0 +1,1222 @@ +*NERD_tree.txt* A tree explorer plugin that owns your momma! + + + + omg its ... ~ + + ________ ________ _ ____________ ____ __________ ____________~ + /_ __/ / / / ____/ / | / / ____/ __ \/ __ \ /_ __/ __ \/ ____/ ____/~ + / / / /_/ / __/ / |/ / __/ / /_/ / / / / / / / /_/ / __/ / __/ ~ + / / / __ / /___ / /| / /___/ _, _/ /_/ / / / / _, _/ /___/ /___ ~ + /_/ /_/ /_/_____/ /_/ |_/_____/_/ |_/_____/ /_/ /_/ |_/_____/_____/ ~ + + + Reference Manual~ + + + + +============================================================================== +CONTENTS *NERDTree-contents* + + 1.Intro...................................|NERDTree| + 2.Functionality provided..................|NERDTreeFunctionality| + 2.1.Global commands...................|NERDTreeGlobalCommands| + 2.2.Bookmarks.........................|NERDTreeBookmarks| + 2.2.1.The bookmark table..........|NERDTreeBookmarkTable| + 2.2.2.Bookmark commands...........|NERDTreeBookmarkCommands| + 2.2.3.Invalid bookmarks...........|NERDTreeInvalidBookmarks| + 2.3.NERD tree mappings................|NERDTreeMappings| + 2.4.The NERD tree menu................|NERDTreeMenu| + 3.Options.................................|NERDTreeOptions| + 3.1.Option summary....................|NERDTreeOptionSummary| + 3.2.Option details....................|NERDTreeOptionDetails| + 4.The NERD tree API.......................|NERDTreeAPI| + 4.1.Key map API.......................|NERDTreeKeymapAPI| + 4.2.Menu API..........................|NERDTreeMenuAPI| + 5.About...................................|NERDTreeAbout| + 6.Changelog...............................|NERDTreeChangelog| + 7.Credits.................................|NERDTreeCredits| + 8.License.................................|NERDTreeLicense| + +============================================================================== +1. Intro *NERDTree* + +What is this "NERD tree"?? + +The NERD tree allows you to explore your filesystem and to open files and +directories. It presents the filesystem to you in the form of a tree which you +manipulate with the keyboard and/or mouse. It also allows you to perform +simple filesystem operations. + +The following features and functionality are provided by the NERD tree: + * Files and directories are displayed in a hierarchical tree structure + * Different highlighting is provided for the following types of nodes: + * files + * directories + * sym-links + * windows .lnk files + * read-only files + * executable files + * Many (customisable) mappings are provided to manipulate the tree: + * Mappings to open/close/explore directory nodes + * Mappings to open files in new/existing windows/tabs + * Mappings to change the current root of the tree + * Mappings to navigate around the tree + * ... + * Directories and files can be bookmarked. + * Most NERD tree navigation can also be done with the mouse + * Filtering of tree content (can be toggled at runtime) + * custom file filters to prevent e.g. vim backup files being displayed + * optional displaying of hidden files (. files) + * files can be "turned off" so that only directories are displayed + * The position and size of the NERD tree window can be customised + * The order in which the nodes in the tree are listed can be customised. + * A model of your filesystem is created/maintained as you explore it. This + has several advantages: + * All filesystem information is cached and is only re-read on demand + * If you revisit a part of the tree that you left earlier in your + session, the directory nodes will be opened/closed as you left them + * The script remembers the cursor position and window position in the NERD + tree so you can toggle it off (or just close the tree window) and then + reopen it (with NERDTreeToggle) the NERD tree window will appear exactly + as you left it + * You can have a separate NERD tree for each tab, share trees across tabs, + or a mix of both. + * By default the script overrides the default file browser (netw), so if + you :edit a directory a (slighly modified) NERD tree will appear in the + current window + * A programmable menu system is provided (simulates right clicking on a + node) + * one default menu plugin is provided to perform basic filesytem + operations (create/delete/move/copy files/directories) + * There's an API for adding your own keymappings + + +============================================================================== +2. Functionality provided *NERDTreeFunctionality* + +------------------------------------------------------------------------------ +2.1. Global Commands *NERDTreeGlobalCommands* + +:NERDTree [<start-directory> | <bookmark>] *:NERDTree* + Opens a fresh NERD tree. The root of the tree depends on the argument + given. There are 3 cases: If no argument is given, the current directory + will be used. If a directory is given, that will be used. If a bookmark + name is given, the corresponding directory will be used. For example: > + :NERDTree /home/marty/vim7/src + :NERDTree foo (foo is the name of a bookmark) +< +:NERDTreeFromBookmark <bookmark> *:NERDTreeFromBookmark* + Opens a fresh NERD tree with the root initialized to the dir for + <bookmark>. This only reason to use this command over :NERDTree is for + the completion (which is for bookmarks rather than directories). + +:NERDTreeToggle [<start-directory> | <bookmark>] *:NERDTreeToggle* + If a NERD tree already exists for this tab, it is reopened and rendered + again. If no NERD tree exists for this tab then this command acts the + same as the |:NERDTree| command. + +:NERDTreeMirror *:NERDTreeMirror* + Shares an existing NERD tree, from another tab, in the current tab. + Changes made to one tree are reflected in both as they are actually the + same buffer. + + If only one other NERD tree exists, that tree is automatically mirrored. If + more than one exists, the script will ask which tree to mirror. + +:NERDTreeClose *:NERDTreeClose* + Close the NERD tree in this tab. + +:NERDTreeFind *:NERDTreeFind* + Find the current file in the tree. If no tree exists for the current tab, + or the file is not under the current root, then initialize a new tree where + the root is the directory of the current file. + +------------------------------------------------------------------------------ +2.2. Bookmarks *NERDTreeBookmarks* + +Bookmarks in the NERD tree are a way to tag files or directories of interest. +For example, you could use bookmarks to tag all of your project directories. + +------------------------------------------------------------------------------ +2.2.1. The Bookmark Table *NERDTreeBookmarkTable* + +If the bookmark table is active (see |NERDTree-B| and +|'NERDTreeShowBookmarks'|), it will be rendered above the tree. You can double +click bookmarks or use the |NERDTree-o| mapping to activate them. See also, +|NERDTree-t| and |NERDTree-T| + +------------------------------------------------------------------------------ +2.2.2. Bookmark commands *NERDTreeBookmarkCommands* + +Note that the following commands are only available in the NERD tree buffer. + +:Bookmark <name> + Bookmark the current node as <name>. If there is already a <name> + bookmark, it is overwritten. <name> must not contain spaces. + +:BookmarkToRoot <bookmark> + Make the directory corresponding to <bookmark> the new root. If a treenode + corresponding to <bookmark> is already cached somewhere in the tree then + the current tree will be used, otherwise a fresh tree will be opened. + Note that if <bookmark> points to a file then its parent will be used + instead. + +:RevealBookmark <bookmark> + If the node is cached under the current root then it will be revealed + (i.e. directory nodes above it will be opened) and the cursor will be + placed on it. + +:OpenBookmark <bookmark> + <bookmark> must point to a file. The file is opened as though |NERDTree-o| + was applied. If the node is cached under the current root then it will be + revealed and the cursor will be placed on it. + +:ClearBookmarks [<bookmarks>] + Remove all the given bookmarks. If no bookmarks are given then remove all + bookmarks on the current node. + +:ClearAllBookmarks + Remove all bookmarks. + +:ReadBookmarks + Re-read the bookmarks in the |'NERDTreeBookmarksFile'|. + +See also |:NERDTree| and |:NERDTreeFromBookmark|. + +------------------------------------------------------------------------------ +2.2.3. Invalid Bookmarks *NERDTreeInvalidBookmarks* + +If invalid bookmarks are detected, the script will issue an error message and +the invalid bookmarks will become unavailable for use. + +These bookmarks will still be stored in the bookmarks file (see +|'NERDTreeBookmarksFile'|), down the bottom. There will always be a blank line +after the valid bookmarks but before the invalid ones. + +Each line in the bookmarks file represents one bookmark. The proper format is: +<bookmark name><space><full path to the bookmark location> + +After you have corrected any invalid bookmarks, either restart vim, or go +:ReadBookmarks from the NERD tree window. + +------------------------------------------------------------------------------ +2.3. NERD tree Mappings *NERDTreeMappings* + +Default Description~ help-tag~ +Key~ + +o.......Open files, directories and bookmarks....................|NERDTree-o| +go......Open selected file, but leave cursor in the NERDTree.....|NERDTree-go| +t.......Open selected node/bookmark in a new tab.................|NERDTree-t| +T.......Same as 't' but keep the focus on the current tab........|NERDTree-T| +i.......Open selected file in a split window.....................|NERDTree-i| +gi......Same as i, but leave the cursor on the NERDTree..........|NERDTree-gi| +s.......Open selected file in a new vsplit.......................|NERDTree-s| +gs......Same as s, but leave the cursor on the NERDTree..........|NERDTree-gs| +O.......Recursively open the selected directory..................|NERDTree-O| +x.......Close the current nodes parent...........................|NERDTree-x| +X.......Recursively close all children of the current node.......|NERDTree-X| +e.......Edit the current dif.....................................|NERDTree-e| + +<CR>...............same as |NERDTree-o|. +double-click.......same as the |NERDTree-o| map. +middle-click.......same as |NERDTree-i| for files, same as + |NERDTree-e| for dirs. + +D.......Delete the current bookmark .............................|NERDTree-D| + +P.......Jump to the root node....................................|NERDTree-P| +p.......Jump to current nodes parent.............................|NERDTree-p| +K.......Jump up inside directories at the current tree depth.....|NERDTree-K| +J.......Jump down inside directories at the current tree depth...|NERDTree-J| +<C-J>...Jump down to the next sibling of the current directory...|NERDTree-C-J| +<C-K>...Jump up to the previous sibling of the current directory.|NERDTree-C-K| + +C.......Change the tree root to the selected dir.................|NERDTree-C| +u.......Move the tree root up one directory......................|NERDTree-u| +U.......Same as 'u' except the old root node is left open........|NERDTree-U| +r.......Recursively refresh the current directory................|NERDTree-r| +R.......Recursively refresh the current root.....................|NERDTree-R| +m.......Display the NERD tree menu...............................|NERDTree-m| +cd......Change the CWD to the dir of the selected node...........|NERDTree-cd| + +I.......Toggle whether hidden files displayed....................|NERDTree-I| +f.......Toggle whether the file filters are used.................|NERDTree-f| +F.......Toggle whether files are displayed.......................|NERDTree-F| +B.......Toggle whether the bookmark table is displayed...........|NERDTree-B| + +q.......Close the NERDTree window................................|NERDTree-q| +A.......Zoom (maximize/minimize) the NERDTree window.............|NERDTree-A| +?.......Toggle the display of the quick help.....................|NERDTree-?| + +------------------------------------------------------------------------------ + *NERDTree-o* +Default key: o +Map option: NERDTreeMapActivateNode +Applies to: files and directories. + +If a file node is selected, it is opened in the previous window. + +If a directory is selected it is opened or closed depending on its current +state. + +If a bookmark that links to a directory is selected then that directory +becomes the new root. + +If a bookmark that links to a file is selected then that file is opened in the +previous window. + +------------------------------------------------------------------------------ + *NERDTree-go* +Default key: go +Map option: None +Applies to: files. + +If a file node is selected, it is opened in the previous window, but the +cursor does not move. + +The key combo for this mapping is always "g" + NERDTreeMapActivateNode (see +|NERDTree-o|). + +------------------------------------------------------------------------------ + *NERDTree-t* +Default key: t +Map option: NERDTreeMapOpenInTab +Applies to: files and directories. + +Opens the selected file in a new tab. If a directory is selected, a fresh +NERD Tree for that directory is opened in a new tab. + +If a bookmark which points to a directory is selected, open a NERD tree for +that directory in a new tab. If the bookmark points to a file, open that file +in a new tab. + +------------------------------------------------------------------------------ + *NERDTree-T* +Default key: T +Map option: NERDTreeMapOpenInTabSilent +Applies to: files and directories. + +The same as |NERDTree-t| except that the focus is kept in the current tab. + +------------------------------------------------------------------------------ + *NERDTree-i* +Default key: i +Map option: NERDTreeMapOpenSplit +Applies to: files. + +Opens the selected file in a new split window and puts the cursor in the new +window. + +------------------------------------------------------------------------------ + *NERDTree-gi* +Default key: gi +Map option: None +Applies to: files. + +The same as |NERDTree-i| except that the cursor is not moved. + +The key combo for this mapping is always "g" + NERDTreeMapOpenSplit (see +|NERDTree-i|). + +------------------------------------------------------------------------------ + *NERDTree-s* +Default key: s +Map option: NERDTreeMapOpenVSplit +Applies to: files. + +Opens the selected file in a new vertically split window and puts the cursor in +the new window. + +------------------------------------------------------------------------------ + *NERDTree-gs* +Default key: gs +Map option: None +Applies to: files. + +The same as |NERDTree-s| except that the cursor is not moved. + +The key combo for this mapping is always "g" + NERDTreeMapOpenVSplit (see +|NERDTree-s|). + +------------------------------------------------------------------------------ + *NERDTree-O* +Default key: O +Map option: NERDTreeMapOpenRecursively +Applies to: directories. + +Recursively opens the selelected directory. + +All files and directories are cached, but if a directory would not be +displayed due to file filters (see |'NERDTreeIgnore'| |NERDTree-f|) or the +hidden file filter (see |'NERDTreeShowHidden'|) then its contents are not +cached. This is handy, especially if you have .svn directories. + +------------------------------------------------------------------------------ + *NERDTree-x* +Default key: x +Map option: NERDTreeMapCloseDir +Applies to: files and directories. + +Closes the parent of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-X* +Default key: X +Map option: NERDTreeMapCloseChildren +Applies to: directories. + +Recursively closes all children of the selected directory. + +Tip: To quickly "reset" the tree, use |NERDTree-P| with this mapping. + +------------------------------------------------------------------------------ + *NERDTree-e* +Default key: e +Map option: NERDTreeMapOpenExpl +Applies to: files and directories. + +|:edit|s the selected directory, or the selected file's directory. This could +result in a NERD tree or a netrw being opened, depending on +|'NERDTreeHijackNetrw'|. + +------------------------------------------------------------------------------ + *NERDTree-D* +Default key: D +Map option: NERDTreeMapDeleteBookmark +Applies to: lines in the bookmarks table + +Deletes the currently selected bookmark. + +------------------------------------------------------------------------------ + *NERDTree-P* +Default key: P +Map option: NERDTreeMapJumpRoot +Applies to: no restrictions. + +Jump to the tree root. + +------------------------------------------------------------------------------ + *NERDTree-p* +Default key: p +Map option: NERDTreeMapJumpParent +Applies to: files and directories. + +Jump to the parent node of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-K* +Default key: K +Map option: NERDTreeMapJumpFirstChild +Applies to: files and directories. + +Jump to the first child of the current nodes parent. + +If the cursor is already on the first node then do the following: + * loop back thru the siblings of the current nodes parent until we find an + open dir with children + * go to the first child of that node + +------------------------------------------------------------------------------ + *NERDTree-J* +Default key: J +Map option: NERDTreeMapJumpLastChild +Applies to: files and directories. + +Jump to the last child of the current nodes parent. + +If the cursor is already on the last node then do the following: + * loop forward thru the siblings of the current nodes parent until we find + an open dir with children + * go to the last child of that node + +------------------------------------------------------------------------------ + *NERDTree-C-J* +Default key: <C-J> +Map option: NERDTreeMapJumpNextSibling +Applies to: files and directories. + +Jump to the next sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C-K* +Default key: <C-K> +Map option: NERDTreeMapJumpPrevSibling +Applies to: files and directories. + +Jump to the previous sibling of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-C* +Default key: C +Map option: NERDTreeMapChdir +Applies to: directories. + +Make the selected directory node the new tree root. If a file is selected, its +parent is used. + +------------------------------------------------------------------------------ + *NERDTree-u* +Default key: u +Map option: NERDTreeMapUpdir +Applies to: no restrictions. + +Move the tree root up a dir (like doing a "cd .."). + +------------------------------------------------------------------------------ + *NERDTree-U* +Default key: U +Map option: NERDTreeMapUpdirKeepOpen +Applies to: no restrictions. + +Like |NERDTree-u| except that the old tree root is kept open. + +------------------------------------------------------------------------------ + *NERDTree-r* +Default key: r +Map option: NERDTreeMapRefresh +Applies to: files and directories. + +If a dir is selected, recursively refresh that dir, i.e. scan the filesystem +for changes and represent them in the tree. + +If a file node is selected then the above is done on it's parent. + +------------------------------------------------------------------------------ + *NERDTree-R* +Default key: R +Map option: NERDTreeMapRefreshRoot +Applies to: no restrictions. + +Recursively refresh the tree root. + +------------------------------------------------------------------------------ + *NERDTree-m* +Default key: m +Map option: NERDTreeMapMenu +Applies to: files and directories. + +Display the NERD tree menu. See |NERDTreeMenu| for details. + +------------------------------------------------------------------------------ + *NERDTree-cd* +Default key: cd +Map option: NERDTreeMapChdir +Applies to: files and directories. + +Change vims current working directory to that of the selected node. + +------------------------------------------------------------------------------ + *NERDTree-I* +Default key: I +Map option: NERDTreeMapToggleHidden +Applies to: no restrictions. + +Toggles whether hidden files (i.e. "dot files") are displayed. + +------------------------------------------------------------------------------ + *NERDTree-f* +Default key: f +Map option: NERDTreeMapToggleFilters +Applies to: no restrictions. + +Toggles whether file filters are used. See |'NERDTreeIgnore'| for details. + +------------------------------------------------------------------------------ + *NERDTree-F* +Default key: F +Map option: NERDTreeMapToggleFiles +Applies to: no restrictions. + +Toggles whether file nodes are displayed. + +------------------------------------------------------------------------------ + *NERDTree-B* +Default key: B +Map option: NERDTreeMapToggleBookmarks +Applies to: no restrictions. + +Toggles whether the bookmarks table is displayed. + +------------------------------------------------------------------------------ + *NERDTree-q* +Default key: q +Map option: NERDTreeMapQuit +Applies to: no restrictions. + +Closes the NERDtree window. + +------------------------------------------------------------------------------ + *NERDTree-A* +Default key: A +Map option: NERDTreeMapToggleZoom +Applies to: no restrictions. + +Maximize (zoom) and minimize the NERDtree window. + +------------------------------------------------------------------------------ + *NERDTree-?* +Default key: ? +Map option: NERDTreeMapHelp +Applies to: no restrictions. + +Toggles whether the quickhelp is displayed. + +------------------------------------------------------------------------------ +2.3. The NERD tree menu *NERDTreeMenu* + +The NERD tree has a menu that can be programmed via the an API (see +|NERDTreeMenuAPI|). The idea is to simulate the "right click" menus that most +file explorers have. + +The script comes with two default menu plugins: exec_menuitem.vim and +fs_menu.vim. fs_menu.vim adds some basic filesystem operations to the menu for +creating/deleting/moving/copying files and dirs. exec_menuitem.vim provides a +menu item to execute executable files. + +Related tags: |NERDTree-m| |NERDTreeApi| + +============================================================================== +3. Customisation *NERDTreeOptions* + + +------------------------------------------------------------------------------ +3.1. Customisation summary *NERDTreeOptionSummary* + +The script provides the following options that can customise the behaviour the +NERD tree. These options should be set in your vimrc. + +|'loaded_nerd_tree'| Turns off the script. + +|'NERDChristmasTree'| Tells the NERD tree to make itself colourful + and pretty. + +|'NERDTreeAutoCenter'| Controls whether the NERD tree window centers + when the cursor moves within a specified + distance to the top/bottom of the window. +|'NERDTreeAutoCenterThreshold'| Controls the sensitivity of autocentering. + +|'NERDTreeCaseSensitiveSort'| Tells the NERD tree whether to be case + sensitive or not when sorting nodes. + +|'NERDTreeChDirMode'| Tells the NERD tree if/when it should change + vim's current working directory. + +|'NERDTreeHighlightCursorline'| Tell the NERD tree whether to highlight the + current cursor line. + +|'NERDTreeHijackNetrw'| Tell the NERD tree whether to replace the netrw + autocommands for exploring local directories. + +|'NERDTreeIgnore'| Tells the NERD tree which files to ignore. + +|'NERDTreeBookmarksFile'| Where the bookmarks are stored. + +|'NERDTreeMouseMode'| Tells the NERD tree how to handle mouse + clicks. + +|'NERDTreeQuitOnOpen'| Closes the tree window after opening a file. + +|'NERDTreeShowBookmarks'| Tells the NERD tree whether to display the + bookmarks table on startup. + +|'NERDTreeShowFiles'| Tells the NERD tree whether to display files + in the tree on startup. + +|'NERDTreeShowHidden'| Tells the NERD tree whether to display hidden + files on startup. + +|'NERDTreeShowLineNumbers'| Tells the NERD tree whether to display line + numbers in the tree window. + +|'NERDTreeSortOrder'| Tell the NERD tree how to sort the nodes in + the tree. + +|'NERDTreeStatusline'| Set a statusline for NERD tree windows. + +|'NERDTreeWinPos'| Tells the script where to put the NERD tree + window. + +|'NERDTreeWinSize'| Sets the window size when the NERD tree is + opened. + +------------------------------------------------------------------------------ +3.2. Customisation details *NERDTreeOptionDetails* + +To enable any of the below options you should put the given line in your +~/.vimrc + + *'loaded_nerd_tree'* +If this plugin is making you feel homicidal, it may be a good idea to turn it +off with this line in your vimrc: > + let loaded_nerd_tree=1 +< +------------------------------------------------------------------------------ + *'NERDChristmasTree'* +Values: 0 or 1. +Default: 1. + +If this option is set to 1 then some extra syntax highlighting elements are +added to the nerd tree to make it more colourful. + +Set it to 0 for a more vanilla looking tree. + +------------------------------------------------------------------------------ + *'NERDTreeAutoCenter'* +Values: 0 or 1. +Default: 1 + +If set to 1, the NERD tree window will center around the cursor if it moves to +within |'NERDTreeAutoCenterThreshold'| lines of the top/bottom of the window. + +This is ONLY done in response to tree navigation mappings, +i.e. |NERDTree-J| |NERDTree-K| |NERDTree-C-J| |NERDTree-C-K| |NERDTree-p| +|NERDTree-P| + +The centering is done with a |zz| operation. + +------------------------------------------------------------------------------ + *'NERDTreeAutoCenterThreshold'* +Values: Any natural number. +Default: 3 + +This option controls the "sensitivity" of the NERD tree auto centering. See +|'NERDTreeAutoCenter'| for details. + +------------------------------------------------------------------------------ + *'NERDTreeCaseSensitiveSort'* +Values: 0 or 1. +Default: 0. + +By default the NERD tree does not sort nodes case sensitively, i.e. nodes +could appear like this: > + bar.c + Baz.c + blarg.c + boner.c + Foo.c +< +But, if you set this option to 1 then the case of the nodes will be taken into +account. The above nodes would then be sorted like this: > + Baz.c + Foo.c + bar.c + blarg.c + boner.c +< +------------------------------------------------------------------------------ + *'NERDTreeChDirMode'* + +Values: 0, 1 or 2. +Default: 0. + +Use this option to tell the script when (if at all) to change the current +working directory (CWD) for vim. + +If it is set to 0 then the CWD is never changed by the NERD tree. + +If set to 1 then the CWD is changed when the NERD tree is first loaded to the +directory it is initialized in. For example, if you start the NERD tree with > + :NERDTree /home/marty/foobar +< +then the CWD will be changed to /home/marty/foobar and will not be changed +again unless you init another NERD tree with a similar command. + +If the option is set to 2 then it behaves the same as if set to 1 except that +the CWD is changed whenever the tree root is changed. For example, if the CWD +is /home/marty/foobar and you make the node for /home/marty/foobar/baz the new +root then the CWD will become /home/marty/foobar/baz. + +------------------------------------------------------------------------------ + *'NERDTreeHighlightCursorline'* +Values: 0 or 1. +Default: 1. + +If set to 1, the current cursor line in the NERD tree buffer will be +highlighted. This is done using the |'cursorline'| option. + +------------------------------------------------------------------------------ + *'NERDTreeHijackNetrw'* +Values: 0 or 1. +Default: 1. + +If set to 1, doing a > + :edit <some directory> +< +will open up a "secondary" NERD tree instead of a netrw in the target window. + +Secondary NERD trees behaves slighly different from a regular trees in the +following respects: + 1. 'o' will open the selected file in the same window as the tree, + replacing it. + 2. you can have as many secondary tree as you want in the same tab. + +------------------------------------------------------------------------------ + *'NERDTreeIgnore'* +Values: a list of regular expressions. +Default: ['\~$']. + +This option is used to specify which files the NERD tree should ignore. It +must be a list of regular expressions. When the NERD tree is rendered, any +files/dirs that match any of the regex's in 'NERDTreeIgnore' wont be +displayed. + +For example if you put the following line in your vimrc: > + let NERDTreeIgnore=['\.vim$', '\~$'] +< +then all files ending in .vim or ~ will be ignored. + +Note: to tell the NERD tree not to ignore any files you must use the following +line: > + let NERDTreeIgnore=[] +< + +The file filters can be turned on and off dynamically with the |NERDTree-f| +mapping. + +------------------------------------------------------------------------------ + *'NERDTreeBookmarksFile'* +Values: a path +Default: $HOME/.NERDTreeBookmarks + +This is where bookmarks are saved. See |NERDTreeBookmarkCommands|. + +------------------------------------------------------------------------------ + *'NERDTreeMouseMode'* +Values: 1, 2 or 3. +Default: 1. + +If set to 1 then a double click on a node is required to open it. +If set to 2 then a single click will open directory nodes, while a double +click will still be required for file nodes. +If set to 3 then a single click will open any node. + +Note: a double click anywhere on a line that a tree node is on will +activate it, but all single-click activations must be done on name of the node +itself. For example, if you have the following node: > + | | |-application.rb +< +then (to single click activate it) you must click somewhere in +'application.rb'. + +------------------------------------------------------------------------------ + *'NERDTreeQuitOnOpen'* + +Values: 0 or 1. +Default: 0 + +If set to 1, the NERD tree window will close after opening a file with the +|NERDTree-o|, |NERDTree-i|, |NERDTree-t| and |NERDTree-T| mappings. + +------------------------------------------------------------------------------ + *'NERDTreeShowBookmarks'* +Values: 0 or 1. +Default: 0. + +If this option is set to 1 then the bookmarks table will be displayed. + +This option can be toggled dynamically, per tree, with the |NERDTree-B| +mapping. + +------------------------------------------------------------------------------ + *'NERDTreeShowFiles'* +Values: 0 or 1. +Default: 1. + +If this option is set to 1 then files are displayed in the NERD tree. If it is +set to 0 then only directories are displayed. + +This option can be toggled dynamically, per tree, with the |NERDTree-F| +mapping and is useful for drastically shrinking the tree when you are +navigating to a different part of the tree. + +------------------------------------------------------------------------------ + *'NERDTreeShowHidden'* +Values: 0 or 1. +Default: 0. + +This option tells vim whether to display hidden files by default. This option +can be dynamically toggled, per tree, with the |NERDTree-I| mapping. Use one +of the follow lines to set this option: > + let NERDTreeShowHidden=0 + let NERDTreeShowHidden=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeShowLineNumbers'* +Values: 0 or 1. +Default: 0. + +This option tells vim whether to display line numbers for the NERD tree +window. Use one of the follow lines to set this option: > + let NERDTreeShowLineNumbers=0 + let NERDTreeShowLineNumbers=1 +< + +------------------------------------------------------------------------------ + *'NERDTreeSortOrder'* +Values: a list of regular expressions. +Default: ['\/$', '*', '\.swp$', '\.bak$', '\~$'] + +This option is set to a list of regular expressions which are used to +specify the order of nodes under their parent. + +For example, if the option is set to: > + ['\.vim$', '\.c$', '\.h$', '*', 'foobar'] +< +then all .vim files will be placed at the top, followed by all .c files then +all .h files. All files containing the string 'foobar' will be placed at the +end. The star is a special flag: it tells the script that every node that +doesnt match any of the other regexps should be placed here. + +If no star is present in 'NERDTreeSortOrder' then one is automatically +appended to the array. + +The regex '\/$' should be used to match directory nodes. + +After this sorting is done, the files in each group are sorted alphabetically. + +Other examples: > + (1) ['*', '\/$'] + (2) [] + (3) ['\/$', '\.rb$', '\.php$', '*', '\.swp$', '\.bak$', '\~$'] +< +1. Directories will appear last, everything else will appear above. +2. Everything will simply appear in alphabetical order. +3. Dirs will appear first, then ruby and php. Swap files, bak files and vim + backup files will appear last with everything else preceding them. + +------------------------------------------------------------------------------ + *'NERDTreeStatusline'* +Values: Any valid statusline setting. +Default: %{b:NERDTreeRoot.path.strForOS(0)} + +Tells the script what to use as the |'statusline'| setting for NERD tree +windows. + +Note that the statusline is set using |:let-&| not |:set| so escaping spaces +isn't necessary. + +Setting this option to -1 will will deactivate it so that your global +statusline setting is used instead. + +------------------------------------------------------------------------------ + *'NERDTreeWinPos'* +Values: "left" or "right" +Default: "left". + +This option is used to determine where NERD tree window is placed on the +screen. + +This option makes it possible to use two different explorer plugins +simultaneously. For example, you could have the taglist plugin on the left of +the window and the NERD tree on the right. + +------------------------------------------------------------------------------ + *'NERDTreeWinSize'* +Values: a positive integer. +Default: 31. + +This option is used to change the size of the NERD tree when it is loaded. + +============================================================================== +4. The NERD tree API *NERDTreeAPI* + +The NERD tree script allows you to add custom key mappings and menu items via +a set of API calls. Any scripts that use this API should be placed in +~/.vim/nerdtree_plugin/ (*nix) or ~/vimfiles/nerdtree_plugin (windows). + +The script exposes some prototype objects that can be used to manipulate the +tree and/or get information from it: > + g:NERDTreePath + g:NERDTreeDirNode + g:NERDTreeFileNode + g:NERDTreeBookmark +< +See the code/comments in NERD_tree.vim to find how to use these objects. The +following code conventions are used: + * class members start with a capital letter + * instance members start with a lower case letter + * private members start with an underscore + +See this blog post for more details: + http://got-ravings.blogspot.com/2008/09/vim-pr0n-prototype-based-objects.html + +------------------------------------------------------------------------------ +4.1. Key map API *NERDTreeKeymapAPI* + +NERDTreeAddKeyMap({options}) *NERDTreeAddKeyMap()* + Adds a new keymapping for all NERD tree buffers. + {options} must be a dictionary, and must contain the following keys: + "key" - the trigger key for the new mapping + "callback" - the function the new mapping will be bound to + "quickhelpText" - the text that will appear in the quickhelp (see + |NERDTree-?|) + + Example: > + call NERDTreeAddKeyMap({ + \ 'key': 'b', + \ 'callback': 'NERDTreeEchoCurrentNode', + \ 'quickhelpText': 'echo full path of current node' }) + + function! NERDTreeEchoCurrentNode() + let n = g:NERDTreeFileNode.GetSelected() + if n != {} + echomsg 'Current node: ' . n.path.str() + endif + endfunction +< + This code should sit in a file like ~/.vim/nerdtree_plugin/mymapping.vim. + It adds a (rather useless) mapping on 'b' which echos the full path to the + current node. + +------------------------------------------------------------------------------ +4.2. Menu API *NERDTreeMenuAPI* + +NERDTreeAddSubmenu({options}) *NERDTreeAddSubmenu()* + Creates and returns a new submenu. + + {options} must be a dictionary and must contain the following keys: + "text" - the text of the submenu that the user will see + "shortcut" - a shortcut key for the submenu (need not be unique) + + The following keys are optional: + "isActiveCallback" - a function that will be called to determine whether + this submenu item will be displayed or not. The callback function must return + 0 or 1. + "parent" - the parent submenu of the new submenu (returned from a previous + invocation of NERDTreeAddSubmenu()). If this key is left out then the new + submenu will sit under the top level menu. + + See below for an example. + +NERDTreeAddMenuItem({options}) *NERDTreeAddMenuItem()* + Adds a new menu item to the NERD tree menu (see |NERDTreeMenu|). + + {options} must be a dictionary and must contain the + following keys: + "text" - the text of the menu item which the user will see + "shortcut" - a shortcut key for the menu item (need not be unique) + "callback" - the function that will be called when the user activates the + menu item. + + The following keys are optional: + "isActiveCallback" - a function that will be called to determine whether + this menu item will be displayed or not. The callback function must return + 0 or 1. + "parent" - if the menu item belongs under a submenu then this key must be + specified. This value for this key will be the object that + was returned when the submenu was created with |NERDTreeAddSubmenu()|. + + See below for an example. + +NERDTreeAddMenuSeparator([{options}]) *NERDTreeAddMenuSeparator()* + Adds a menu separator (a row of dashes). + + {options} is an optional dictionary that may contain the following keys: + "isActiveCallback" - see description in |NERDTreeAddMenuItem()|. + +Below is an example of the menu API in action. > + call NERDTreeAddMenuSeparator() + + call NERDTreeAddMenuItem({ + \ 'text': 'a (t)op level menu item', + \ 'shortcut': 't', + \ 'callback': 'SomeFunction' }) + + let submenu = NERDTreeAddSubmenu({ + \ 'text': 'a (s)ub menu', + \ 'shortcut': 's' }) + + call NERDTreeAddMenuItem({ + \ 'text': '(n)ested item 1', + \ 'shortcut': 'n', + \ 'callback': 'SomeFunction', + \ 'parent': submenu }) + + call NERDTreeAddMenuItem({ + \ 'text': '(n)ested item 2', + \ 'shortcut': 'n', + \ 'callback': 'SomeFunction', + \ 'parent': submenu }) +< +This will create the following menu: > + -------------------- + a (t)op level menu item + a (s)ub menu +< +Where selecting "a (s)ub menu" will lead to a second menu: > + (n)ested item 1 + (n)ested item 2 +< +When any of the 3 concrete menu items are selected the function "SomeFunction" +will be called. + +------------------------------------------------------------------------------ +NERDTreeRender() *NERDTreeRender()* + Re-renders the NERD tree buffer. Useful if you change the state of the + tree and you want to it to be reflected in the UI. + +============================================================================== +5. About *NERDTreeAbout* + +The author of the NERD tree is a terrible terrible monster called Martyzilla +who gobbles up small children with milk and sugar for breakfast. + +He can be reached at martin.grenfell at gmail dot com. He would love to hear +from you, so feel free to send him suggestions and/or comments about this +plugin. Don't be shy --- the worst he can do is slaughter you and stuff you in +the fridge for later ;) + +The latest stable versions can be found at + http://www.vim.org/scripts/script.php?script_id=1658 + +The latest dev versions are on github + http://github.com/scrooloose/nerdtree + + +============================================================================== +6. Changelog *NERDTreeChangelog* + +4.1.0 + features: + - NERDTreeFind to reveal the node for the current buffer in the tree, + see |NERDTreeFind|. This effectively merges the FindInNERDTree plugin (by + Doug McInnes) into the script. + - make NERDTreeQuitOnOpen apply to the t/T keymaps too. Thanks to Stefan + Ritter and Rémi Prévost. + - truncate the root node if wider than the tree window. Thanks to Victor + Gonzalez. + + bugfixes: + - really fix window state restoring + - fix some win32 path escaping issues. Thanks to Stephan Baumeister, Ricky, + jfilip1024, and Chris Chambers + +4.0.0 + - add a new programmable menu system (see :help NERDTreeMenu). + - add new APIs to add menus/menu-items to the menu system as well as + custom key mappings to the NERD tree buffer (see :help NERDTreeAPI). + - removed the old API functions + - added a mapping to maximize/restore the size of nerd tree window, thanks + to Guillaume Duranceau for the patch. See :help NERDTree-A for details. + + - fix a bug where secondary nerd trees (netrw hijacked trees) and + NERDTreeQuitOnOpen didnt play nicely, thanks to Curtis Harvey. + - fix a bug where the script ignored directories whose name ended in a dot, + thanks to Aggelos Orfanakos for the patch. + - fix a bug when using the x mapping on the tree root, thanks to Bryan + Venteicher for the patch. + - fix a bug where the cursor position/window size of the nerd tree buffer + wasnt being stored on closing the window, thanks to Richard Hart. + - fix a bug where NERDTreeMirror would mirror the wrong tree + +3.1.1 + - fix a bug where a non-listed no-name buffer was getting created every + time the tree windows was created, thanks to Derek Wyatt and owen1 + - make <CR> behave the same as the 'o' mapping + - some helptag fixes in the doc, thanks strull + - fix a bug when using :set nohidden and opening a file where the previous + buf was modified. Thanks iElectric + - other minor fixes + +3.1.0 + New features: + - add mappings to open files in a vsplit, see :help NERDTree-s and :help + NERDTree-gs + - make the statusline for the nerd tree window default to something + hopefully more useful. See :help 'NERDTreeStatusline' + Bugfixes: + - make the hijack netrw functionality work when vim is started with "vim + <some dir>" (thanks to Alf Mikula for the patch). + - fix a bug where the CWD wasnt being changed for some operations even when + NERDTreeChDirMode==2 (thanks to Lucas S. Buchala) + - add -bar to all the nerd tree :commands so they can chain with other + :commands (thanks to tpope) + - fix bugs when ignorecase was set (thanks to nach) + - fix a bug with the relative path code (thanks to nach) + - fix a bug where doing a :cd would cause :NERDTreeToggle to fail (thanks nach) + + +3.0.1 + Bugfixes: + - fix bugs with :NERDTreeToggle and :NERDTreeMirror when 'hidden + was not set + - fix a bug where :NERDTree <path> would fail if <path> was relative and + didnt start with a ./ or ../ Thanks to James Kanze. + - make the q mapping work with secondary (:e <dir> style) trees, + thanks to jamessan + - fix a bunch of small bugs with secondary trees + + More insane refactoring. + +3.0.0 + - hijack netrw so that doing an :edit <directory> will put a NERD tree in + the window rather than a netrw browser. See :help 'NERDTreeHijackNetrw' + - allow sharing of trees across tabs, see :help :NERDTreeMirror + - remove "top" and "bottom" as valid settings for NERDTreeWinPos + - change the '<tab>' mapping to 'i' + - change the 'H' mapping to 'I' + - lots of refactoring + +============================================================================== +7. Credits *NERDTreeCredits* + +Thanks to the following people for testing, bug reports, ideas etc. Without +you I probably would have got bored of the hacking the NERD tree and +just downloaded pr0n instead. + + Tim Carey-Smith (halorgium) + Vigil + Nick Brettell + Thomas Scott Urban + Terrance Cohen + Yegappan Lakshmanan + Jason Mills + Michael Geddes (frogonwheels) + Yu Jun + Michael Madsen + AOYAMA Shotaro + Zhang Weiwu + Niels Aan de Brugh + Olivier Yiptong + Zhang Shuhan + Cory Echols + Piotr Czachur + Yuan Jiang + Matan Nassau + Maxim Kim + Charlton Wang + Matt Wozniski (godlygeek) + knekk + Sean Chou + Ryan Penn + Simon Peter Nicholls + Michael Foobar + Tomasz Chomiuk + Denis Pokataev + Tim Pope (tpope) + James Kanze + James Vega (jamessan) + Frederic Chanal (nach) + Alf Mikula + Lucas S. Buchala + Curtis Harvey + Guillaume Duranceau + Richard Hart (hates) + Doug McInnes + Stefan Ritter + Rémi Prévost + Victor Gonzalez + Stephan Baumeister + Ricky + jfilip1024 + Chris Chambers + +============================================================================== +8. License *NERDTreeLicense* + +The NERD tree is released under the wtfpl. +See http://sam.zoy.org/wtfpl/COPYING. Added: configs/trunk/src/vim/nerdtree_plugin/exec_menuitem.vim =================================================================== --- configs/trunk/src/vim/nerdtree_plugin/exec_menuitem.vim (rev 0) +++ configs/trunk/src/vim/nerdtree_plugin/exec_menuitem.vim 2010-01-25 03:38:43 UTC (rev 1550) @@ -0,0 +1,41 @@ +" ============================================================================ +" File: exec_menuitem.vim +" Description: plugin for NERD Tree that provides an execute file menu item +" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com> +" Last Change: 22 July, 2009 +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +if exists("g:loaded_nerdtree_exec_menuitem") + finish +endif +let g:loaded_nerdtree_exec_menuitem = 1 + +call NERDTreeAddMenuItem({ + \ 'text': '(!)Execute file', + \ 'shortcut': '!', + \ 'callback': 'NERDTreeExecFile', + \ 'isActiveCallback': 'NERDTreeExecFileActive' }) + +function! NERDTreeExecFileActive() + let node = g:NERDTreeFileNode.GetSelected() + return !node.path.isDirectory && node.path.isExecutable +endfunction + +function! NERDTreeExecFile() + let treenode = g:NERDTreeFileNode.GetSelected() + echo "==========================================================\n" + echo "Complete the command to execute (add arguments etc):\n" + let cmd = treenode.path.str({'escape': 1}) + let cmd = input(':!', cmd . ' ') + + if cmd != '' + exec ':!' . cmd + else + echo "Aborted" + endif +endfunction Added: configs/trunk/src/vim/nerdtree_plugin/fs_menu.vim =================================================================== --- configs/trunk/src/vim/nerdtree_plugin/fs_menu.vim (rev 0) +++ configs/trunk/src/vim/nerdtree_plugin/fs_menu.vim 2010-01-25 03:38:43 UTC (rev 1550) @@ -0,0 +1,194 @@ +" ============================================================================ +" File: fs_menu.vim +" Description: plugin for the NERD Tree that provides a file system menu +" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com> +" Last Change: 17 July, 2009 +" License: This program is free software. It comes without any warranty, +" to the extent permitted by applicable law. You can redistribute +" it and/or modify it under the terms of the Do What The Fuck You +" Want To Public License, Version 2, as published by Sam Hocevar. +" See http://sam.zoy.org/wtfpl/COPYING for more details. +" +" ============================================================================ +if exists("g:loaded_nerdtree_fs_menu") + finish +endif +let g:loaded_nerdtree_fs_menu = 1 + +call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'}) +call NERDTreeAddMenuItem({'text': '(m)ove the curent node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'}) +call NERDTreeAddMenuItem({'text': '(d)elete the curent node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'}) +if g:NERDTreePath.CopyingSupported() + call NERDTreeAddMenuItem({'text': '(c)copy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'}) +endif + +"FUNCTION: s:echo(msg){{{1 +function! s:echo(msg) + redraw + echomsg "NERDTree: " . a:msg +endfunction + +"FUNCTION: s:echoWarning(msg){{{1 +function! s:echoWarning(msg) + echohl warningmsg + call s:echo(a:msg) + echohl normal +endfunction + +"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{1 +"prints out the given msg and, if the user responds by pushing 'y' then the +"buffer with the given bufnum is deleted +" +"Args: +"bufnum: the buffer that may be deleted +"msg: a message that will be echoed to the user asking them if they wish to +" del the buffer +function! s:promptToDelBuffer(bufnum, msg) + echo a:msg + if nr2char(getchar()) ==# 'y' + exec "silent bdelete! " . a:bufnum + endif +endfunction + +"FUNCTION: NERDTreeAddNode(){{{1 +function! NERDTreeAddNode() + let curDirNode = g:NERDTreeDirNode.GetSelected() + + let newNodeName = input("Add a childnode\n". + \ "==========================================================\n". + \ "Enter the dir/file name to be created. Dirs end with a '/'\n" . + \ "", curDirNode.path.str({'format': 'Glob'}) . g:NERDTreePath.Slash()) + + if newNodeName ==# '' + call s:echo("Node Creation Aborted.") + return + endif + + try + let newPath = g:NERDTreePath.Create(newNodeName) + let parentNode = b:NERDTreeRoot.findNode(newPath.getParent()) + + let newTreeNode = g:NERDTreeFileNode.New(newPath) + if parentNode.isOpen || !empty(parentNode.children) + call parentNode.addChild(newTreeNode, 1) + call NERDTreeRender() + call newTreeNode.putCursorHere(1, 0) + endif + catch /^NERDTree/ + call s:echoWarning("Node Not Created.") + endtry +endfunction + +"FUNCTION: NERDTreeMoveNode(){{{1 +function! NERDTreeMoveNode() + let curNode = g:NERDTreeFileNode.GetSelected() + let newNodePath = input("Rename the current node\n" . + \ "==========================================================\n" . + \ "Enter the new path for the node: \n" . + \ "", curNode.path.str()) + + if newNodePath ==# '' + call s:echo("Node Renaming Aborted.") + return + endif + + try + let bufnum = bufnr(curNode.path.str()) + + call curNode.rename(newNodePath) + call NERDTreeRender() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + if bufnum != -1 + let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" + call s:promptToDelBuffer(bufnum, prompt) + endif + + call curNode.putCursorHere(1, 0) + + redraw + catch /^NERDTree/ + call s:echoWarning("Node Not Renamed.") + endtry +endfunction + +" FUNCTION: NERDTreeDeleteNode() {{{1 +function! NERDTreeDeleteNode() + let currentNode = g:NERDTreeFileNode.GetSelected() + let confirmed = 0 + + if currentNode.path.isDirectory + let choice =input("Delete the current node\n" . + \ "==========================================================\n" . + \ "STOP! To delete this entire directory, type 'yes'\n" . + \ "" . currentNode.path.str() . ": ") + let confirmed = choice ==# 'yes' + else + echo "Delete the current node\n" . + \ "==========================================================\n". + \ "Are you sure you wish to delete the node:\n" . + \ "" . currentNode.path.str() . " (yN):" + let choice = nr2char(getchar()) + let confirmed = choice ==# 'y' + endif + + + if confirmed + try + call currentNode.delete() + call NERDTreeRender() + + "if the node is open in a buffer, ask the user if they want to + "close that buffer + let bufnum = bufnr(currentNode.path.str()) + if buflisted(bufnum) + let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)" + call s:promptToDelBuffer(bufnum, prompt) + endif + + redraw + catch /^NERDTree/ + call s:echoWarning("Could not remove node") + endtry + else + call s:echo("delete aborted") + endif + +endfunction + +" FUNCTION: NERDTreeCopyNode() {{{1 +function! NERDTreeCopyNode() + let currentNode = g:NERDTreeFileNode.GetSelected() + let newNodePath = input("Copy the current node\n" . + \ "==========================================================\n" . + \ "Enter the new path to copy the node to: \n" . + \ "", currentNode.path.str()) + + if newNodePat... [truncated message content] |
From: <yan...@us...> - 2010-01-23 20:57:54
|
Revision: 1549 http://assorted.svn.sourceforge.net/assorted/?rev=1549&view=rev Author: yangzhang Date: 2010-01-23 20:57:45 +0000 (Sat, 23 Jan 2010) Log Message: ----------- removed mlf Removed Paths: ------------- configs/trunk/src/cron/mlf.bash Deleted: configs/trunk/src/cron/mlf.bash =================================================================== --- configs/trunk/src/cron/mlf.bash 2010-01-21 04:00:45 UTC (rev 1548) +++ configs/trunk/src/cron/mlf.bash 2010-01-23 20:57:45 UTC (rev 1549) @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -FORCE_BASHRC=1 . ~/.bashrc && . common.bash || exit 1 -exec mlf.py --debug main yan...@gm... 'imap.gmail.com/[Gmail]/All Mail' >& /tmp/mlf-log This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2010-01-21 04:01:03
|
Revision: 1548 http://assorted.svn.sourceforge.net/assorted/?rev=1548&view=rev Author: yangzhang Date: 2010-01-21 04:00:45 +0000 (Thu, 21 Jan 2010) Log Message: ----------- switched back to colorscheme desert Modified Paths: -------------- configs/trunk/src/vim/plugin/_yang.vim Modified: configs/trunk/src/vim/plugin/_yang.vim =================================================================== --- configs/trunk/src/vim/plugin/_yang.vim 2010-01-21 02:30:29 UTC (rev 1547) +++ configs/trunk/src/vim/plugin/_yang.vim 2010-01-21 04:00:45 UTC (rev 1548) @@ -143,7 +143,8 @@ hi User4 guibg=#000000 guifg=LightBlue gui=bold hi LineNr guibg=grey30 -colorscheme ir_black " desert +" colorscheme ir_black +colorscheme desert syntax enable " set number " number lines This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2010-01-21 02:30:52
|
Revision: 1547 http://assorted.svn.sourceforge.net/assorted/?rev=1547&view=rev Author: yangzhang Date: 2010-01-21 02:30:29 +0000 (Thu, 21 Jan 2010) Log Message: ----------- added svn to PS1 Modified Paths: -------------- shell-tools/trunk/src/bash-commons/bashrc.bash Modified: shell-tools/trunk/src/bash-commons/bashrc.bash =================================================================== --- shell-tools/trunk/src/bash-commons/bashrc.bash 2010-01-21 02:30:15 UTC (rev 1546) +++ shell-tools/trunk/src/bash-commons/bashrc.bash 2010-01-21 02:30:29 UTC (rev 1547) @@ -777,8 +777,12 @@ then git_ps1="\[$fg_yellow\]\$( __git_ps1 'git(%s) ' )\[$normal_color\]" else git_ps1='' fi + if type svn >& /dev/null + then svn_ps1="\[$fg_yellow\]\$( svn info 2> /dev/null | sed -n -e '/^Revision: \([0-9]*\).*$/ s//svn(\1)/p' || true )\[$normal_color\]" + else svn_ps1='' + fi - PS1="$titlebar\n$user_host $exitstatus$datetime $path $git_ps1\n\$ " + PS1="$titlebar\n$user_host $exitstatus$datetime $path $git_ps1$svn_ps1\n\$ " # \[\] is for PS1/PS2 only; lets bash calculate word wrapping correctly. # it's not for general terminal usage. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2010-01-21 02:30:21
|
Revision: 1546 http://assorted.svn.sourceforge.net/assorted/?rev=1546&view=rev Author: yangzhang Date: 2010-01-21 02:30:15 +0000 (Thu, 21 Jan 2010) Log Message: ----------- made bootstrap-cabal executable Property Changed: ---------------- shell-tools/trunk/src/bootstrap-cabal.bash Property changes on: shell-tools/trunk/src/bootstrap-cabal.bash ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2010-01-21 02:29:24
|
Revision: 1545 http://assorted.svn.sourceforge.net/assorted/?rev=1545&view=rev Author: yangzhang Date: 2010-01-21 02:29:13 +0000 (Thu, 21 Jan 2010) Log Message: ----------- removed mlf.bash; relying just on gmail threading and outbound filters Modified Paths: -------------- configs/trunk/src/cron/mlf.bash Modified: configs/trunk/src/cron/mlf.bash =================================================================== --- configs/trunk/src/cron/mlf.bash 2010-01-21 02:28:48 UTC (rev 1544) +++ configs/trunk/src/cron/mlf.bash 2010-01-21 02:29:13 UTC (rev 1545) @@ -1,9 +1,3 @@ #!/usr/bin/env bash - FORCE_BASHRC=1 . ~/.bashrc && . common.bash || exit 1 - -try mv ~/.mlf.cache/yan...@gm...{,-$(date +'%Y%m%d')} - -exec mlf.py --debug main --debug star --debug unstar \ - yan...@gm... 'imap.gmail.com/[Gmail]/All Mail' - +exec mlf.py --debug main yan...@gm... 'imap.gmail.com/[Gmail]/All Mail' >& /tmp/mlf-log This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2010-01-21 02:29:02
|
Revision: 1544 http://assorted.svn.sourceforge.net/assorted/?rev=1544&view=rev Author: yangzhang Date: 2010-01-21 02:28:48 +0000 (Thu, 21 Jan 2010) Log Message: ----------- added appficio Modified Paths: -------------- configs/trunk/src/ssh/config Modified: configs/trunk/src/ssh/config =================================================================== --- configs/trunk/src/ssh/config 2010-01-17 17:56:04 UTC (rev 1543) +++ configs/trunk/src/ssh/config 2010-01-21 02:28:48 UTC (rev 1544) @@ -6,6 +6,14 @@ # StrictHostKeyChecking no # +# appficio +# + +Host af + HostName appficio.com + User yang + +# # Yahoo # This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2010-01-17 17:56:15
|
Revision: 1543 http://assorted.svn.sourceforge.net/assorted/?rev=1543&view=rev Author: yangzhang Date: 2010-01-17 17:56:04 +0000 (Sun, 17 Jan 2010) Log Message: ----------- always viewing on dark background by default Modified Paths: -------------- configs/trunk/src/vim/plugin/_yang.vim Modified: configs/trunk/src/vim/plugin/_yang.vim =================================================================== --- configs/trunk/src/vim/plugin/_yang.vim 2009-12-31 01:16:05 UTC (rev 1542) +++ configs/trunk/src/vim/plugin/_yang.vim 2010-01-17 17:56:04 UTC (rev 1543) @@ -465,5 +465,6 @@ " central path without removing the . path) set directory^=~/.vim/swap +set bg=dark " vim:et:sw=2:ts=2 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-31 01:16:13
|
Revision: 1542 http://assorted.svn.sourceforge.net/assorted/?rev=1542&view=rev Author: yangzhang Date: 2009-12-31 01:16:05 +0000 (Thu, 31 Dec 2009) Log Message: ----------- only show git status if avail; fixed color for exit status Modified Paths: -------------- shell-tools/trunk/src/bash-commons/bashrc.bash Modified: shell-tools/trunk/src/bash-commons/bashrc.bash =================================================================== --- shell-tools/trunk/src/bash-commons/bashrc.bash 2009-12-31 01:05:58 UTC (rev 1541) +++ shell-tools/trunk/src/bash-commons/bashrc.bash 2009-12-31 01:16:05 UTC (rev 1542) @@ -763,10 +763,20 @@ if [ $status != 0 ] then echo '"$(quote "\[$bg_dark_red\]")\$status$(quote "\[$normal_color\] ")"' fi )' + if bash --version | fgrep 'version 3' >& /dev/null ; then + local exitstatus='$( status=$? + if [ $status != 0 ] + then echo -e '"$(quote "$bg_dark_red")\$status$(quote "$normal_color ")"' + fi )' + fi local user_host="\[$fg_dark_green\]\u@\h\[$normal_color\]" local path="\[$fg_brown\]\w\[$normal_color\]" - local git_ps1="\[$fg_yellow\]\$( __git_ps1 'git(%s) ' )\[$normal_color\]" + local git_ps1 + if type __git_ps1 >& /dev/null + then git_ps1="\[$fg_yellow\]\$( __git_ps1 'git(%s) ' )\[$normal_color\]" + else git_ps1='' + fi PS1="$titlebar\n$user_host $exitstatus$datetime $path $git_ps1\n\$ " This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-31 01:06:05
|
Revision: 1541 http://assorted.svn.sourceforge.net/assorted/?rev=1541&view=rev Author: yangzhang Date: 2009-12-31 01:05:58 +0000 (Thu, 31 Dec 2009) Log Message: ----------- initialize python path for PYTHONVERSION if avail otherwise autodetect Modified Paths: -------------- shell-tools/trunk/src/bash-commons/bashrc.bash Modified: shell-tools/trunk/src/bash-commons/bashrc.bash =================================================================== --- shell-tools/trunk/src/bash-commons/bashrc.bash 2009-12-31 01:04:22 UTC (rev 1540) +++ shell-tools/trunk/src/bash-commons/bashrc.bash 2009-12-31 01:05:58 UTC (rev 1541) @@ -131,6 +131,9 @@ prepend_std CPLUS_INCLUDE_PATH include prepend_std OBJC_INCLUDE_PATH include +# TODO Move this further up? +. common.bash -n + # bash # don't put duplicate lines in the history @@ -140,8 +143,6 @@ shopt -s checkwinsize # TODO check this hist size (for sanity) -shopt -s extglob - # perl prepend_std PERL5LIB lib/perl5/site_perl lib/perl share/perl @@ -150,11 +151,11 @@ export PYTHONSTARTUP="$HOME/.pythonrc.py" pythonpath_prepend= -ver=${PYTHONVERSION} -if [[ ! "$ver" ]] && type python >& /dev/null -then ver="$( python -c 'import sys; print ".".join(map(str,sys.version_info[0:2]))' )" +PYTHONVERSION=${PYTHONVERSION:-} +if [[ ! "$PYTHONVERSION" ]] && type python >& /dev/null +then PYTHONVERSION="$(python-version)" fi -for ver in $ver ; do +for ver in $PYTHONVERSION ; do pythonpath_prepend="$USER_PREFIX/lib/python$ver/site-packages:$pythonpath_prepend" pythonpath_prepend="$USER_TOAST_PREFIX/lib/python$ver/site-packages:$pythonpath_prepend" pythonpath_prepend="/usr/local/lib/python$ver/site-packages:$pythonpath_prepend" @@ -186,8 +187,7 @@ export UNISONBACKUPDIR=~/.unison/backup export UNISON=~/.unison -# TODO Move this further up? -. common.bash -n +# less if ! have less.sh ; then export PATH="/usr/local/share/vim/vim71/macros/:$PATH" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-31 01:04:32
|
Revision: 1540 http://assorted.svn.sourceforge.net/assorted/?rev=1540&view=rev Author: yangzhang Date: 2009-12-31 01:04:22 +0000 (Thu, 31 Dec 2009) Log Message: ----------- added python-version; fixed refresh-opt to use `pkg` user only if avail; enabled extglob Modified Paths: -------------- shell-tools/trunk/src/bash-commons/common.bash Modified: shell-tools/trunk/src/bash-commons/common.bash =================================================================== --- shell-tools/trunk/src/bash-commons/common.bash 2009-12-31 01:02:05 UTC (rev 1539) +++ shell-tools/trunk/src/bash-commons/common.bash 2009-12-31 01:04:22 UTC (rev 1540) @@ -49,6 +49,8 @@ normal_color="\e[0m" +shopt -s extglob + # Don't use 'error' to print the message because error might be a special # logging facility. Our intent is to actual produce some plain output for the # user here. @@ -455,12 +457,16 @@ done } +python-version() { + python -c 'import sys; print ".".join(map(str,sys.version_info[0:2]))' +} + # Install a python package to the specified directory. Takes care of creating # the dir and setting the PYTHONPATH appropriately for the setup process. pyinstall() { - local prefix="$1" pkgdir="$1/lib/python2.5/site-packages" + local prefix="$1" pkgdir="$1/lib/python$(python-version)/site-packages" mkdir -p $pkgdir - PYTHONPATH="$pkgdir:$PYTHONPATH" ./setup.py install --prefix "$prefix" + PYTHONPATH="$pkgdir:$PYTHONPATH" python setup.py install --prefix "$prefix" } # Check that a file exists and has private permissions. @@ -524,9 +530,17 @@ } refresh-opt() { - ( sudo -u pkg mkdir -p "$GLOBAL_PREFIX" && + local pkg_user= + if [[ "$PKG_USER" ]] ; then + pkg_user="$PKG_USER" + elif sudo -u pkg echo -n ; then + pkg_user=pkg + else + pkg_user=root + fi + ( sudo -u "$pkg_user" mkdir -p "$GLOBAL_PREFIX" && cd "$GLOBAL_PKG" && - sudo -u pkg stow -t "$GLOBAL_PREFIX" !(armed) ) + sudo -u "$pkg_user" stow -t "$GLOBAL_PREFIX" !(armed) ) } cabal-install-all() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-31 01:02:22
|
Revision: 1539 http://assorted.svn.sourceforge.net/assorted/?rev=1539&view=rev Author: yangzhang Date: 2009-12-31 01:02:05 +0000 (Thu, 31 Dec 2009) Log Message: ----------- added agpl3 Modified Paths: -------------- shell-tools/trunk/src/bash-commons/assorted.bash Modified: shell-tools/trunk/src/bash-commons/assorted.bash =================================================================== --- shell-tools/trunk/src/bash-commons/assorted.bash 2009-12-31 00:59:53 UTC (rev 1538) +++ shell-tools/trunk/src/bash-commons/assorted.bash 2009-12-31 01:02:05 UTC (rev 1539) @@ -108,6 +108,9 @@ local license_text license_links case $license in + agpl3 ) + license_text='the [GNU AGPL3]' + license_links='[GNU AGPL3]: http://www.gnu.org/licenses/agpl-3.0.html' ;; boost ) license_text='the [Boost Software License][BSL]' license_links='[BSL]: http://www.boost.org/LICENSE_1_0.txt' ;; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-31 01:00:01
|
Revision: 1538 http://assorted.svn.sourceforge.net/assorted/?rev=1538&view=rev Author: yangzhang Date: 2009-12-31 00:59:53 +0000 (Thu, 31 Dec 2009) Log Message: ----------- added recover-vim Added Paths: ----------- shell-tools/trunk/src/recover-vim.bash Added: shell-tools/trunk/src/recover-vim.bash =================================================================== --- shell-tools/trunk/src/recover-vim.bash (rev 0) +++ shell-tools/trunk/src/recover-vim.bash 2009-12-31 00:59:53 UTC (rev 1538) @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +# Finds vim swap files and tries to recover from them. Note: make sure you're +# not working on actual in-use swap files. + +. common.bash || exit 1 + +set -o errexit -o nounset + +# This function is useful if you don't have `set directory=<something other +# than .>`. + +old() { + local a= + while read -r i ; do + a=( "${a[@]}" "$i" ) + done < <( echo "$@" | sed 's/ /\n/g' | # find . -name '*.swp' | + sed 's/\(.*\/\)\.\(.\+\)\.swp/\1\2/' ) + for i in "${a[@]}" ; do + if [[ "$i" == '' ]] ; then continue ; fi + rm -f "$i.recovered" + if [[ ! -f "$i" ]] ; then + echo -e "${fg_bright_red}$i not found${normal_color}" ; read + else + local del=false + vim -r "$i" -X -c "sav $i.recovered | q" || true + if is-empty-file "$i.recovered" ; then + echo -e "${fg_yellow}$i.recovered is empty; deleting swp${normal_color}" + del=true + fi + if diff -q "$i" "$i.recovered" ; then + echo -e "${fg_bright_green}$i.recovered no diff than $i; deleting swp${normal_color}" + del=true + fi + if $del + then rm "$(dirname "$i")/.$(basename "$i").swp" "$i.recovered" + else echo -e "${fg_bright_red}NOT DELETING${normal_color}" ; read + fi + fi + done +} + +old "$@" +exit + +# <http://stackoverflow.com/questions/63104/smarter-vim-recovery> +TMPDIR=$(mktemp -d) || exit 1 +RECTXT="$TMPDIR/vim.recovery.$USER.txt" +RECFN="$TMPDIR/vim.recovery.$USER.fn" +trap 'rm -f "$RECTXT" "$RECFN"; rmdir "$TMPDIR"' 0 1 2 3 15 +for q in ~/.vim/swap/.*sw? ~/.vim/swap/*; do + [[ -f $q ]] || continue + rm -f "$RECTXT" "$RECFN" + vim -X -r "$q" \ + -c "w! $RECTXT" \ + -c "let fn=expand('%')" \ + -c "new $RECFN" \ + -c "exec setline( 1, fn )" \ + -c w\! \ + -c "qa" + if [[ ! -f $RECFN ]]; then + echo "nothing to recover from $q" + rm -f "$q" + continue + fi + CRNT="$(cat $RECFN)" + if diff --strip-trailing-cr --brief "$CRNT" "$RECTXT"; then + echo "removing redundant $q" + echo " for $CRNT" + rm -f "$q" + else + echo $q contains changes + vim -n -d "$CRNT" "$RECTXT" + rm -i "$q" || exit + fi +done Property changes on: shell-tools/trunk/src/recover-vim.bash ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-31 00:59:36
|
Revision: 1537 http://assorted.svn.sourceforge.net/assorted/?rev=1537&view=rev Author: yangzhang Date: 2009-12-31 00:59:26 +0000 (Thu, 31 Dec 2009) Log Message: ----------- new PS1 prompt shows exit status, git status, date/time; fixed asd, aoe; updated for renamed colors Modified Paths: -------------- shell-tools/trunk/src/bash-commons/bashrc.bash Modified: shell-tools/trunk/src/bash-commons/bashrc.bash =================================================================== --- shell-tools/trunk/src/bash-commons/bashrc.bash 2009-12-31 00:57:00 UTC (rev 1536) +++ shell-tools/trunk/src/bash-commons/bashrc.bash 2009-12-31 00:59:26 UTC (rev 1537) @@ -226,12 +226,12 @@ # switch to Dvorak function asd { - use-dvorak-keyboard + dvorak } # switch from Dvorak function aoe { - use-normal-keyboard + qwerty } # unison on home directory @@ -326,7 +326,7 @@ # TODO fix function g { #grep --color=always -r "$@" | sed "$( echo -e "s/\([^:]*\):/$bright_blue\1$normal_color:/" )" | less -F - grep --color=always -r "$@" | GREP_COLOR="$( echo -e "\e$bright_blue" )" grep --color=always -r '^[^:]*:' | less -F + grep --color=always -r "$@" | GREP_COLOR="$( echo -e "$fg_bright_blue" )" grep --color=always -r '^[^:]*:' | less -F } function runemacs { @@ -744,6 +744,37 @@ eval "$( dircolors -b )" +setup_prompt() { + # TODO add elapsed time, running jobs + + # Current date and time + local datetime="\[$fg_dark_gray\]\d \t\[$normal_color\]" + local elapsed= + + # Screen name (if inside a screen) + local screenname + if [ -n "$STY" ] + then screenname="\[$fg_dark_cyan\]$STY\[$normal_color\]" + else screenname= + fi + + # Display status on failure + local exitstatus='$( status=$? + if [ $status != 0 ] + then echo '"$(quote "\[$bg_dark_red\]")\$status$(quote "\[$normal_color\] ")"' + fi )' + + local user_host="\[$fg_dark_green\]\u@\h\[$normal_color\]" + local path="\[$fg_brown\]\w\[$normal_color\]" + local git_ps1="\[$fg_yellow\]\$( __git_ps1 'git(%s) ' )\[$normal_color\]" + + PS1="$titlebar\n$user_host $exitstatus$datetime $path $git_ps1\n\$ " + + # \[\] is for PS1/PS2 only; lets bash calculate word wrapping correctly. + # it's not for general terminal usage. + # <http://www.ibm.com/developerworks/linux/library/l-tip-prompt/> +} + # -t 1 checks if fd 1 (stdout) is a terminal; if so then we're running # interactively. if [[ -t 1 ]] @@ -774,7 +805,6 @@ # ;; #esac - # TODO add timetamp and elapsed time for previous command and any other - # info you can find (eg running jobs) - PS1="$titlebar\n\[$dark_green\]\u@\h \[$brown\]\w\n\[$normal_color\]$ " + setup_prompt + fi This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-31 00:57:10
|
Revision: 1536 http://assorted.svn.sourceforge.net/assorted/?rev=1536&view=rev Author: yangzhang Date: 2009-12-31 00:57:00 +0000 (Thu, 31 Dec 2009) Log Message: ----------- added pdfsplit, capitalize; renamed colors Modified Paths: -------------- shell-tools/trunk/src/bash-commons/common.bash Modified: shell-tools/trunk/src/bash-commons/common.bash =================================================================== --- shell-tools/trunk/src/bash-commons/common.bash 2009-12-30 18:31:32 UTC (rev 1535) +++ shell-tools/trunk/src/bash-commons/common.bash 2009-12-31 00:57:00 UTC (rev 1536) @@ -23,15 +23,30 @@ # \e = \E = \033 # 0;34m = 34m # 30's are foregrounds, 40's are backgrounds +# Escape sequences begin with \e[ and end with m. +# Each is a sequence of commands, separated by ;. +# 0 and 1 set the lightness, but 0 also resets everything (fg/bg). +# 3x sets the foreground. +# 4x sets the background. -dark_blue="\e[0;34m"; bright_blue="\e[1;34m" -dark_green="\e[0;32m"; bright_green="\e[1;32m" -dark_cyan="\e[0;36m"; bright_cyan="\e[1;36m" -dark_red="\e[0;31m"; bright_red="\e[1;31m" -dark_magenta="\e[0;35m"; bright_magenta="\e[1;35m" -brown="\e[0;33m"; yellow="\e[1;33m" -black="\e[0;30m"; dark_gray="\e[1;30m"; -bold_white="\e[1;37m" white="\e[0;37m" +fg_dark_blue="\e[0;34m"; fg_bright_blue="\e[1;34m" +fg_dark_green="\e[0;32m"; fg_bright_green="\e[1;32m" +fg_dark_cyan="\e[0;36m"; fg_bright_cyan="\e[1;36m" +fg_dark_red="\e[0;31m"; fg_bright_red="\e[1;31m" +fg_dark_magenta="\e[0;35m"; fg_bright_magenta="\e[1;35m" +fg_brown="\e[0;33m"; fg_yellow="\e[1;33m" +fg_black="\e[0;30m"; fg_dark_gray="\e[1;30m" +fg_white="\e[0;37m"; fg_bold_white="\e[1;37m" + +bg_dark_blue="\e[0;44m"; bg_bright_blue="\e[1;44m" +bg_dark_green="\e[0;42m"; bg_bright_green="\e[1;42m" +bg_dark_cyan="\e[0;46m"; bg_bright_cyan="\e[1;46m" +bg_dark_red="\e[0;41m"; bg_bright_red="\e[1;41m" +bg_dark_magenta="\e[0;45m"; bg_bright_magenta="\e[1;45m" +bg_brown="\e[0;43m"; bg_yellow="\e[1;43m" +bg_black="\e[0;40m"; bg_dark_gray="\e[1;40m" +bg_white="\e[0;47m"; bg_bold_white="\e[1;47m" + normal_color="\e[0m" # Don't use 'error' to print the message because error might be a special @@ -559,6 +574,19 @@ done } +pdfsplit() { + local f="$@" + for i in $( seq $( pdfpages "$f" ) ) + do pdftk "$f" cat $i output "${f%.pdf}-$i.pdf" + done +} + +# capitalize the first letter of the given arg +capitalize() { + echo -n "${1:0:1}" | tr '[:lower:]' '[:upper:]' + echo "${1:1}" +} + # Add keys if not already added. maybe-ssh-add() { if ( ssh-add -l && ! ssh-add -l | fgrep $1 ) >& /dev/null This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-30 18:31:40
|
Revision: 1535 http://assorted.svn.sourceforge.net/assorted/?rev=1535&view=rev Author: yangzhang Date: 2009-12-30 18:31:32 +0000 (Wed, 30 Dec 2009) Log Message: ----------- try using centralized swap file directory Modified Paths: -------------- configs/trunk/src/vim/plugin/_yang.vim Modified: configs/trunk/src/vim/plugin/_yang.vim =================================================================== --- configs/trunk/src/vim/plugin/_yang.vim 2009-12-30 18:31:06 UTC (rev 1534) +++ configs/trunk/src/vim/plugin/_yang.vim 2009-12-30 18:31:32 UTC (rev 1535) @@ -434,4 +434,36 @@ highlight DiffDelete cterm=bold ctermbg=6 ctermfg=gray highlight DiffText cterm=bold ctermbg=1 +""""""""""""""""""""""""""""""""" + +" ,---- +" | " A statusbar function, that provides a visual scrollbar (courtesy of A.Politz) +" | func! STL() +" | let stl = '%f [%{(&fenc==""?&enc:&fenc).((exists("+bomb") && &bomb)?",B":"")}%M%R%H%W] %y [%l/%L,%v] [%p%%]' +" | let barWidth = &columns - 65 " <-- wild guess +" | let barWidth = barWidth < 3 ? 3 : barWidth +" | +" | if line('$') > 1 +" | let progress = (line('.')-1) * (barWidth-1) / (line('$')-1) +" | else +" | let progress = barWidth/2 +" | endif +" | +" | " line + vcol + % +" | let pad = strlen(line('$'))-strlen(line('.')) + 3 - strlen(virtcol('.')) + 3 - strlen(line('.')*100/line('$')) +" | let bar = repeat(' ',pad).' [%1*%'.barWidth.'.'.barWidth.'(' +" | \.repeat('-',progress ) +" | \.'%2*0%1*' +" | \.repeat('-',barWidth - progress - 1).'%0*%)%<]' +" | +" | return stl.bar +" + +" this centralizes all vim swap files to avoid polluting the file system, but +" means that other users won't be able to detect your concurrent editing +" session (though you can still pick up others', since this only prepends the +" central path without removing the . path) + +set directory^=~/.vim/swap + " vim:et:sw=2:ts=2 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-30 18:31:16
|
Revision: 1534 http://assorted.svn.sourceforge.net/assorted/?rev=1534&view=rev Author: yangzhang Date: 2009-12-30 18:31:06 +0000 (Wed, 30 Dec 2009) Log Message: ----------- datapository ssh uses emulab login Modified Paths: -------------- configs/trunk/src/ssh/config Modified: configs/trunk/src/ssh/config =================================================================== --- configs/trunk/src/ssh/config 2009-12-30 18:27:47 UTC (rev 1533) +++ configs/trunk/src/ssh/config 2009-12-30 18:31:06 UTC (rev 1534) @@ -290,6 +290,10 @@ HostName pdos.csail.mit.edu User yang +Host sn + HostName sn002.datapository.net + User yaaang + # # Cartel # This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-30 18:27:57
|
Revision: 1533 http://assorted.svn.sourceforge.net/assorted/?rev=1533&view=rev Author: yangzhang Date: 2009-12-30 18:27:47 +0000 (Wed, 30 Dec 2009) Log Message: ----------- gitit: verbose logging Modified Paths: -------------- configs/trunk/src/gitit/config Modified: configs/trunk/src/gitit/config =================================================================== --- configs/trunk/src/gitit/config 2009-12-30 18:27:13 UTC (rev 1532) +++ configs/trunk/src/gitit/config 2009-12-30 18:27:47 UTC (rev 1533) @@ -72,7 +72,7 @@ # specifies the path of gitit's log file. If it does not exist, # gitit will create it. The log is in Apache combined log format. -log-level: WARNING +log-level: INFO # determines how much information is logged. # Possible values (from most to least verbose) are DEBUG, INFO, # NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-30 18:27:23
|
Revision: 1532 http://assorted.svn.sourceforge.net/assorted/?rev=1532&view=rev Author: yangzhang Date: 2009-12-30 18:27:13 +0000 (Wed, 30 Dec 2009) Log Message: ----------- more git aliases and user config Modified Paths: -------------- configs/trunk/src/gitconfig Modified: configs/trunk/src/gitconfig =================================================================== --- configs/trunk/src/gitconfig 2009-12-29 04:53:21 UTC (rev 1531) +++ configs/trunk/src/gitconfig 2009-12-30 18:27:13 UTC (rev 1532) @@ -2,10 +2,17 @@ b = branch ci = commit -a co = checkout - com = commit + com = commit + d = diff + dc = diff --cached h = help + llog = log --date=local pr = pull --rebase - llog = log --date=local st = status + sta = stash + up = pull [core] excludesfile = /home/yang/.gitignore +[user] + name = Yang Zhang + email = ya...@gm... This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-29 04:53:33
|
Revision: 1531 http://assorted.svn.sourceforge.net/assorted/?rev=1531&view=rev Author: yangzhang Date: 2009-12-29 04:53:21 +0000 (Tue, 29 Dec 2009) Log Message: ----------- tagged 0.2.1 Added Paths: ----------- mailing-list-filter/tags/0.2.1/ mailing-list-filter/tags/0.2.1/README mailing-list-filter/tags/0.2.1/publish.bash mailing-list-filter/tags/0.2.1/setup.py mailing-list-filter/tags/0.2.1/src/mlf.py Removed Paths: ------------- mailing-list-filter/tags/0.2.1/README mailing-list-filter/tags/0.2.1/publish.bash mailing-list-filter/tags/0.2.1/setup.py mailing-list-filter/tags/0.2.1/src/mlf.py Deleted: mailing-list-filter/tags/0.2.1/README =================================================================== --- mailing-list-filter/trunk/README 2009-06-03 17:52:11 UTC (rev 1451) +++ mailing-list-filter/tags/0.2.1/README 2009-12-29 04:53:21 UTC (rev 1531) @@ -1,62 +0,0 @@ -Overview --------- - -I have a Gmail account that I use for subscribing to and posting to mailing -lists. When dealing with high-volume mailing lists, I am typically only -interested in those threads that I participated in. This is a simple filter -for starring and marking unread any messages belonging to such threads. - -This is accomplished by looking at the set of messages that were either sent -from me or explicitly addressed to me. From this "root set" of messages, we -can use the `Message-ID`, `References`, and `In-Reply-To` headers to determine -threads, and thus the other messages that we care about. - -I have found this to be more accurate than my two original approaches. I used -to have Gmail filters that starred/marked unread any messages containing my -name anywhere in the message. This worked OK since my name is not too common, -but it produced some false positives (not that bad, just unstar messages) and -some false negatives (much harder to detect). - -A second approach is to tag all subjects with some signature string. This -usually is fine, but it doesn't work when you did not start the thread (and -thus determine the subject). You can try to change the subject line, but this -is (1) poor netiquette, (2) unreliable because your reply may not register in -other mail clients as being part of the same thread (and thus other -participants may miss your reply), and (3) unreliable because replies might not -directly referencing your post (either intentionally or unintentionally). It -also fails when others change the subject. Finally, this approach is -unsatisfactory because it pollutes subject lines, and it essentially replicates -exactly what Message-ID was intended for. - -This script is not intended to be a replacement for the Gmail filters. I still -keep those active so that I can get immediate first-pass filtering. I execute -this script on a daily basis to perform second-pass filtering/unfiltering to -catch those false negatives that may have been missed. - -Setup ------ - -Requirements: - -- [argparse](http://argparse.python-hosting.com/) 0.8.0 -- [Python Commons](http://assorted.sf.net/python-commons/) 0.6 - -Install the program using the standard `setup.py` program. - -Todo ----- - -- Currently, we assume that the server specification points to a mailbox - containing all messages (both sent and received), and a message is determined - to have been sent by you by looking at the From: header field. This works - well with Gmail. An alternative strategy is to look through two folders, one - that's the Inbox and one that's the Sent mailbox, and treat all messages in - Sent as having been sent by you. This is presumably how most other IMAP - servers work. - -- Implement incremental maintenance of local cache. - -- Accept custom operations for filtered/unfiltered messages - (trashing/untrashing, labeling/unlabeling, etc.). - -- Refactor the message fetching/management part out into its own library. Copied: mailing-list-filter/tags/0.2.1/README (from rev 1530, mailing-list-filter/trunk/README) =================================================================== --- mailing-list-filter/tags/0.2.1/README (rev 0) +++ mailing-list-filter/tags/0.2.1/README 2009-12-29 04:53:21 UTC (rev 1531) @@ -0,0 +1,76 @@ +Overview +-------- + +I have a Gmail account that I use for subscribing to and posting to mailing +lists. When dealing with high-volume mailing lists, I am typically only +interested in those threads that I participated in. This is a simple filter +for starring and marking unread any messages belonging to such threads. + +This is accomplished by looking at the set of messages that were either sent +from me or explicitly addressed to me. From this "root set" of messages, we +can use the `Message-ID`, `References`, and `In-Reply-To` headers to determine +threads, and thus the other messages that we care about. + +I have found this to be more accurate than my two original approaches. I used +to have Gmail filters that starred/marked unread any messages containing my +name anywhere in the message. This worked OK since my name is not too common, +but it produced some false positives (not that bad, just unstar messages) and +some false negatives (much harder to detect). + +A second approach is to tag all subjects with some signature string. This +usually is fine, but it doesn't work when you did not start the thread (and +thus determine the subject). You can try to change the subject line, but this +is (1) poor netiquette, (2) unreliable because your reply may not register in +other mail clients as being part of the same thread (and thus other +participants may miss your reply), and (3) unreliable because replies might not +directly referencing your post (either intentionally or unintentionally). It +also fails when others change the subject. Finally, this approach is +unsatisfactory because it pollutes subject lines, and it essentially replicates +exactly what Message-ID was intended for. + +This script is not intended to be a replacement for the Gmail filters. I still +keep those active so that I can get immediate first-pass filtering. I execute +this script on a daily basis to perform second-pass filtering/unfiltering to +catch those false negatives that may have been missed. + +Setup +----- + +Requirements: + +- [argparse](http://argparse.python-hosting.com/) 0.8.0 +- [Python Commons](http://assorted.sf.net/python-commons/) 0.6 + +Install the program using the standard `setup.py` program. + +Todo +---- + +- Currently, we assume that the server specification points to a mailbox + containing all messages (both sent and received), and a message is determined + to have been sent by you by looking at the From: header field. This works + well with Gmail. An alternative strategy is to look through two folders, one + that's the Inbox and one that's the Sent mailbox, and treat all messages in + Sent as having been sent by you. This is presumably how most other IMAP + servers work. + +- Accept custom operations for filtered/unfiltered messages + (trashing/untrashing, labeling/unlabeling, etc.). + +- Refactor the message fetching/management part out into its own library. + +Changes +------- + +v0.2.1 + +- Bug fixes. + +v0.2 + +- Added disk-based operation to remove memory capacity limit. +- Added incremental updates to local cache. + +v0.1 + +- Initial release: fully in-memory operation and no incremental updates. Deleted: mailing-list-filter/tags/0.2.1/publish.bash =================================================================== --- mailing-list-filter/trunk/publish.bash 2009-06-03 17:52:11 UTC (rev 1451) +++ mailing-list-filter/tags/0.2.1/publish.bash 2009-12-29 04:53:21 UTC (rev 1531) @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -fullname='Mailing List Filter' -version=0.1 -license=gpl -websrcs=( README ) -rels=( pypi: ) -. assorted.bash "$@" Copied: mailing-list-filter/tags/0.2.1/publish.bash (from rev 1530, mailing-list-filter/trunk/publish.bash) =================================================================== --- mailing-list-filter/tags/0.2.1/publish.bash (rev 0) +++ mailing-list-filter/tags/0.2.1/publish.bash 2009-12-29 04:53:21 UTC (rev 1531) @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +fullname='Mailing List Filter' +version=0.2.1 +license=gpl3 +websrcs=( README ) +rels=( pypi: ) +. assorted.bash "$@" Deleted: mailing-list-filter/tags/0.2.1/setup.py =================================================================== --- mailing-list-filter/trunk/setup.py 2009-06-03 17:52:11 UTC (rev 1451) +++ mailing-list-filter/tags/0.2.1/setup.py 2009-12-29 04:53:21 UTC (rev 1531) @@ -1,28 +0,0 @@ -#!/usr/bin/env python - -from commons.setup import run_setup - -pkg_info_text = """ -Metadata-Version: 1.1 -Name: mailing-list-filter -Version: 0.1 -Author: Yang Zhang -Author-email: yaaang NOSPAM at REMOVECAPS gmail -Home-page: http://assorted.sourceforge.net/mailing-list-filter/ -Download-url: http://pypi.python.org/pypi/mailing-list-filter/ -Summary: Mailing List Filter -License: Python Software Foundation License -Description: Filter mailing list email for relevant threads only. -Keywords: mailing,list,email,filter,IMAP,Gmail -Platform: any -Provides: commons -Classifier: Development Status :: 4 - Beta -Classifier: Environment :: No Input/Output (Daemon) -Classifier: Intended Audience :: End Users/Desktop -Classifier: License :: OSI Approved :: Python Software Foundation License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Topic :: Communications :: Email -""" - -run_setup(pkg_info_text, scripts = ['src/mlf.py']) Copied: mailing-list-filter/tags/0.2.1/setup.py (from rev 1530, mailing-list-filter/trunk/setup.py) =================================================================== --- mailing-list-filter/tags/0.2.1/setup.py (rev 0) +++ mailing-list-filter/tags/0.2.1/setup.py 2009-12-29 04:53:21 UTC (rev 1531) @@ -0,0 +1,28 @@ +#!/usr/bin/env python + +from commons.setup import run_setup + +pkg_info_text = """ +Metadata-Version: 1.1 +Name: mailing-list-filter +Version: 0.2.1 +Author: Yang Zhang +Author-email: yaaang NOSPAM at REMOVECAPS gmail +Home-page: http://assorted.sourceforge.net/mailing-list-filter/ +Download-url: http://pypi.python.org/pypi/mailing-list-filter/ +Summary: Mailing List Filter +License: Python Software Foundation License +Description: Filter mailing list email for relevant threads only. +Keywords: mailing,list,email,filter,IMAP,Gmail +Platform: any +Provides: commons +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: No Input/Output (Daemon) +Classifier: Intended Audience :: End Users/Desktop +Classifier: License :: OSI Approved :: Python Software Foundation License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Communications :: Email +""" + +run_setup(pkg_info_text, scripts = ['src/mlf.py']) Deleted: mailing-list-filter/tags/0.2.1/src/mlf.py =================================================================== --- mailing-list-filter/trunk/src/mlf.py 2009-06-03 17:52:11 UTC (rev 1451) +++ mailing-list-filter/tags/0.2.1/src/mlf.py 2009-12-29 04:53:21 UTC (rev 1531) @@ -1,315 +0,0 @@ -#!/usr/bin/env python - -# See RFC 3501. - -""" -Given a Gmail IMAP mailbox, star all messages in which you were a participant -(either a sender or an explicit recipient in To: or Cc:), where thread grouping -is performed via the In-Reply-To and References headers. -""" - -from __future__ import with_statement -from functools import partial -from commons.log import * -from contextlib import closing, contextmanager -import getpass, logging, shelve, email, re, os, imaplib, itertools -import argparse, collections, subprocess, shutil -from commons import log, startup, seqs, networking, files, sqlhash -from commons.path import path - -info = partial(log.info, 'main') -debug = partial(log.debug, 'main') -warning = partial(log.warning, 'main') -error = partial(log.error, 'main') -die = partial(log.die, 'main') -exception = partial(log.exception, 'main') - -# -# Functions for getting local file paths and opening them. -# - -def dbpath(cfg, suffix): - return ( cfg.cachedir / - files.cleanse_filename(cfg.sender) + '-' + suffix ) - -def opendb(cfg, suffix, flags = 'r'): - return sqlhash.Shelf(sqlhash.SQLhash(dbpath(cfg, suffix), - flags = flags), - protocol = 2, - writeback = flags == 'w', - cache = flags == 'w') - -# -# Functions for working with the server. -# - -@contextmanager -def login_imap(cfg): - info('connecting and logging in') - with networking.logout(imaplib.IMAP4_SSL(cfg.host, cfg.port)) as imap: - imap.login(cfg.user, cfg.passwd) - # Close is only valid in the authenticated state. - with closing(imap) as imap: - info('selecting mailbox') - imap.select(cfg.mailbox) - yield imap - -# -# Functions for fetching messages from the server. -# - -def getmaxuid(imap): - info( 'finding max UID' ) - # We use UIDs rather than the default of sequence numbers because UIDs are - # guaranteed to be persistent across sessions. This means that we can, for - # instance, fetch messages in one session and operate on this locally cached - # data before marking messages in a separate session. - ok, [uids] = imap.uid('SEARCH', None, 'ALL') - maxuid = int( uids.split()[-1] ) - del uids - return maxuid - -def fetch_range(imap, minuid, maxuid): - info( 'fetching messages', minuid, 'to', maxuid ) - # The syntax/fields of the FETCH command is documented in RFC 2060. Also, - # this article contains a brief overview: - # http://www.devshed.com/c/a/Python/Python-Email-Libraries-part-2-IMAP/3/ - # BODY.PEEK prevents the message from automatically being flagged as \Seen. - query = '(FLAGS BODY.PEEK[HEADER.FIELDS ' \ - '(Message-ID References In-Reply-To From To Cc Subject)])' - step = 1000 - for start in xrange(minuid, maxuid + 1, step): - range = '%d:%d' % (start, min(maxuid, start + step - 1)) - while True: - try: - info('fetching', range) - ok, chunk = imap.uid('FETCH', range, query) - except imaplib.abort, ex: - error('fetch failed:', ex.message) - if 'System Error' not in ex.message: raise - except: - exception('fetch failed') - raise - else: - break - for row in chunk: - yield row - -def fetch_new_mail(cfg, imap): - if cfg.refresh: - try: os.remove(dbpath(cfg, 'fetched')) - except: pass - - with closing(opendb(cfg, 'fetched', 'w')) as mid2msg: - - minuid = mid2msg.get('maxuid', 0) + 1 - maxuid = getmaxuid(imap) - - # Every second item is just a closing paren. - # Example data: - # [('13300 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {67}', - # 'Message-ID: <mai...@py...>\r\n\r\n'), - # ')', - # ('13301 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {59}', - # 'Message-Id: <200...@hv...>\r\n\r\n'), - # ')', - # ('13302 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {92}', - # 'Message-ID: <C43EAFC0.2E3AE%ni...@ya...>\r\nIn-Reply-To: <481...@gm...>\r\n\r\n')] - pat = re.compile(r"(?P<seqno>\d+) \(UID (?P<uid>\d+) FLAGS \((?P<flags>[^)]+)\)") - for i, ((envelope, data), paren) in enumerate(seqs.grouper(2, fetch_range(imap, minuid, maxuid))): - # Parse the body. - msg = email.message_from_string(data) - - # Parse the envelope. - m = pat.match(envelope) - if m is None: raise Exception('envelope: %r' % envelope) - msg.seqno = m.group('seqno') - msg.uid = m.group('uid') - msg.flags = m.group('flags').split() - - # Prepare a container for references to other msgs, and initialize the - # thread ID. - msg.refs = set() - msg.tid = None - - # Add these to the map. - if msg['Message-ID'] in mid2msg: - log.warning( 'dups', 'duplicate message IDs:', - msg['Message-ID'], msg['Subject'] ) - mid2msg[ msg['Message-ID'] ] = msg - - # Periodically sync to disk. - if len(mid2msg.cache) > 1000: mid2msg.sync() - - mid2msg['maxuid'] = maxuid - # XXX - mid2msg['procuid'] = mid2msg['maxuid'] - -# -# Function for analyzing messages. -# - -def itermsgs(mid2msg, minuid, midsrc = None): - if midsrc is None: midsrc = mid2msg - special_keys = ['maxuid', 'procuid'] - for i, (mid, msg) in enumerate(midsrc.iteritems()): - if mid not in special_keys and msg.uid >= minuid: - if midsrc is mid2msg: yield msg - else: yield mid2msg[mid] - # Periodically sync to disk. - if mid2msg.cache is not None and len(mid2msg.cache) > 10000: - debug( 'syncing; now at i', i, 'mid', mid ) - mid2msg.sync() - debug( 'syncing; finished after i', i, 'mid', mid ) - mid2msg.sync() - -def thread_dfs(msg, tid, mid2msg): - assert msg.tid is None - msg.tid = tid - for refmid in msg.refs: - try: - refmsg = mid2msg[refmid] - except KeyError: - log.warning('badref', 'no message with mid', refmid) - else: - if refmsg.tid is None: thread_dfs(refmsg, tid, mid2msg) - else: assert refmsg.tid == tid - -def mark_relevant_threads(cfg): - - shutil.copy(dbpath(cfg, 'fetched'), dbpath(cfg, 'bidir')) - - with closing(opendb(cfg, 'fetched')) as midsrc: - with closing(opendb(cfg, 'bidir', 'w')) as mid2msg: - procuid = mid2msg.get('procuid', 0) - minuid = procuid + 1 - info( 'maxuid', midsrc['maxuid'], 'procuid', procuid ) - del procuid - info( 'constructing bidirectional ref graph' ) - for msg in itermsgs(mid2msg, minuid, midsrc): - debug('processing', msg['Message-ID']) - irt = msg.get_all('In-Reply-To', []) - refs = msg.get_all('References', []) - newrefs = ' '.join( irt + refs ).replace('><', '> <').split() - msg.refs.update( newrefs ) - - # Connect nodes in graph bidirectionally. Ignore references to MIDs - # that don't exist. - for ref in newrefs: - debug('adding', ref, '<->', msg['Message-ID']) - try: mid2msg[ref].refs.add( msg['Message-ID'] ) - except KeyError: log.warning( 'badref', 'no message with mid', ref ) - - shutil.copy(dbpath(cfg, 'bidir'), dbpath(cfg, 'threaded')) - - with closing(opendb(cfg, 'bidir')) as midsrc: - with closing(opendb(cfg, 'threaded', 'w')) as mid2msg: - info( 'looking for relevant msgs (grouping them into threads)' ) - tids = itertools.count() - for msg in itermsgs(mid2msg, minuid, midsrc): - debug('threading', msg['Message-ID']) - if ( msg.tid is None and - ( cfg.sender in msg.get('From', '') or - cfg.sender in msg.get('To', '') or - cfg.sender in msg.get('Cc', '') ) ): - thread_dfs(msg, tids.next(), mid2msg) - -# -# Functions for storing metadata changes back to the server. -# - -def flag_relevant_msgs(cfg, imap, mid2msg): - - info( 'starring/unstarring relevant/irrelevant threads' ) - - for msg in itermsgs(mid2msg, 0): - if msg.tid is not None: # is a relevant msgs - if r'\Flagged' not in msg.flags: # not already flagged - mark_unseen = not cfg.no_mark_unseen and r'\Seen' in msg.flags - log.info( 'star', '\n', - 'star' + (' and mark unseen' if mark_unseen else ''), - msg ) - if not cfg.pretend: - imap.uid('STORE', msg.uid, '+FLAGS', r'\Flagged') - if mark_unseen: imap.uid('STORE', msg.uid, '-FLAGS', r'\Seen') - else: # is not a relevant msg - if r'\Flagged' in msg.flags: # was inadvertently flagged - mark_seen = not cfg.no_mark_seen and r'\Seen' not in msg.flags - log.info( 'unstar', '\n', - 'unstar' + (' and mark seen' if mark_seen else ''), - msg ) - if not cfg.pretend: - imap.uid('STORE', msg.uid, '-FLAGS', r'\Flagged') - if mark_seen: imap.uid('STORE', msg.uid, '+FLAGS', r'\Seen') - - mid2msg['procuid'] = mid2msg['maxuid'] - -# -# Main function. -# - -def main(argv): - p = argparse.ArgumentParser(description = __doc__) - p.add_argument('--credfile', default = path( '~/.mlf.auth' ).expanduser(), - help = """File containing your login credentials, with the username on the - first line and the password on the second line. Ignored iff --prompt.""") - p.add_argument('--cachedir', default = path( '~/.mlf.cache' ).expanduser(), - help = "Directory to use for caching our data.") - p.add_argument('--refresh', action = 'store_true', - help = "Re-fetch all messages, wiping out existing cache.") - p.add_argument('--prompt', action = 'store_true', - help = "Interactively prompt for the username and password.") - p.add_argument('--pretend', action = 'store_true', - help = """Do not actually carry out any updates to the server. Use in - conjunction with --debug to observe what would happen.""") - p.add_argument('--no-mark-unseen', action = 'store_true', - help = "Do not mark newly revelant threads as unread.") - p.add_argument('--no-mark-seen', action = 'store_true', - help = "Do not mark newly irrevelant threads as read.") - p.add_argument('--no-fetch', action = 'store_true', - help = "Do not fetch new messages; just process already-fetched messages.") - p.add_argument('--debug', action = 'append', default = [], - help = """Enable logging for messages of the given flags. Flags include: - refs (references to missing Message-IDs), dups (duplicate Message-IDs), - main (the main program logic), and star (which messages are being - starred), unstar (which messages are being unstarred).""") - p.add_argument('sender', - help = "Your email address.") - p.add_argument('server', - help = "The server in the format: <host>[:<port>][/<mailbox>].") - - cfg = p.parse_args(argv[1:]) - - config_logging(level = logging.ERROR, do_console = True, flags = cfg.debug) - - if cfg.prompt: - print "username:", - cfg.user = raw_input() - print "password:", - cfg.passwd = getpass.getpass() - else: - with file(cfg.credfile) as f: - [cfg.user, cfg.passwd] = map(lambda x: x.strip('\r\n'), f.readlines()) - - try: - m = re.match( r'(?P<host>[^:/]+)(:(?P<port>\d+))?(/(?P<mailbox>.+))?$', - cfg.server ) - cfg.host = m.group('host') - cfg.port = int( m.group('port') or 993 ) - cfg.mailbox = m.group('mailbox') or 'INBOX' - except: - p.error('Need to specify the server in the correct format.') - - files.soft_makedirs(cfg.cachedir) - - if not cfg.no_fetch: - with login_imap(cfg) as imap: - fetch_new_mail(cfg, imap) - - mark_relevant_threads(cfg) - - with login_imap(cfg) as imap: - with closing(opendb(cfg, 'threaded')) as mid2msg: - flag_relevant_msgs(cfg, imap, mid2msg) - -startup.run_main() Copied: mailing-list-filter/tags/0.2.1/src/mlf.py (from rev 1530, mailing-list-filter/trunk/src/mlf.py) =================================================================== --- mailing-list-filter/tags/0.2.1/src/mlf.py (rev 0) +++ mailing-list-filter/tags/0.2.1/src/mlf.py 2009-12-29 04:53:21 UTC (rev 1531) @@ -0,0 +1,334 @@ +#!/usr/bin/env python + +# See RFC 3501. + +""" +Given a Gmail IMAP mailbox, star all messages in which you were a participant +(either a sender or an explicit recipient in To: or Cc:), where thread grouping +is performed via the In-Reply-To and References headers. +""" + +from __future__ import with_statement +from functools import partial +from commons.log import * +from contextlib import closing, contextmanager +import getpass, logging, shelve, email, re, os, imaplib, itertools +import argparse, collections, subprocess, shutil +from commons import log, startup, seqs, networking, files, sqlhash +from commons.path import path + +info = partial(log.info, 'main') +debug = partial(log.debug, 'main') +warning = partial(log.warning, 'main') +error = partial(log.error, 'main') +die = partial(log.die, 'main') +exception = partial(log.exception, 'main') + +# +# Functions for getting local file paths and opening them. +# + +def dbpath(cfg, suffix): + return ( cfg.cachedir / + files.cleanse_filename(cfg.sender) + '-' + suffix ) + +def opendb(cfg, suffix, flags = 'r'): + return sqlhash.Shelf(sqlhash.SQLhash(dbpath(cfg, suffix), + flags = flags), + protocol = 2, + writeback = flags == 'w', + cache = flags == 'w') + +# +# Functions for working with the server. +# + +@contextmanager +def login_imap(cfg): + info('connecting and logging in') + imap = imaplib.IMAP4_SSL(cfg.host, cfg.port) + try: + imap.login(cfg.user, cfg.passwd) + # Close is only valid in the authenticated state. + try: + info('selecting mailbox') + imap.select(cfg.mailbox) + yield imap + except Exception, ex: + try: imap.close() + except imaplib.abort: raise ex + else: + imap.close() + except Exception, ex: + try: imap.logout() + except imaplib.abort: raise ex + else: + imap.logout() + +# +# Functions for fetching messages from the server. +# + +def getmaxuid(imap): + info( 'finding max UID' ) + # We use UIDs rather than the default of sequence numbers because UIDs are + # guaranteed to be persistent across sessions. This means that we can, for + # instance, fetch messages in one session and operate on this locally cached + # data before marking messages in a separate session. + ok, [uids] = imap.uid('SEARCH', None, 'ALL') + maxuid = int( uids.split()[-1] ) + del uids + return maxuid + +def fetch_range(imap, minuid, maxuid): + info( 'fetching messages', minuid, 'to', maxuid ) + # The syntax/fields of the FETCH command is documented in RFC 2060. Also, + # this article contains a brief overview: + # http://www.devshed.com/c/a/Python/Python-Email-Libraries-part-2-IMAP/3/ + # BODY.PEEK prevents the message from automatically being flagged as \Seen. + query = '(FLAGS BODY.PEEK[HEADER.FIELDS ' \ + '(Message-ID References In-Reply-To From To Cc Subject)])' + step = 1000 + for start in xrange(minuid, maxuid + 1, step): + range = '%d:%d' % (start, min(maxuid, start + step - 1)) + while True: + try: + info('fetching', range) + ok, chunk = imap.uid('FETCH', range, query) + except imaplib.abort, ex: + error('fetch failed:', ex.message) + if 'System Error' not in ex.message: raise + except: + exception('fetch failed') + raise + else: + break + for row in chunk: + yield row + +def fetch_new_mail(cfg, imap): + if cfg.refresh: + try: os.remove(dbpath(cfg, 'fetched')) + except: pass + + with closing(opendb(cfg, 'fetched', 'w')) as mid2msg: + + minuid = mid2msg.get('maxuid', 0) + 1 + maxuid = getmaxuid(imap) + + # Every second item is just a closing paren. + # Example data: + # [('13300 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {67}', + # 'Message-ID: <mai...@py...>\r\n\r\n'), + # ')', + # ('13301 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {59}', + # 'Message-Id: <200...@hv...>\r\n\r\n'), + # ')', + # ('13302 (BODY[HEADER.FIELDS (Message-ID References In-Reply-To)] {92}', + # 'Message-ID: <C43EAFC0.2E3AE%ni...@ya...>\r\nIn-Reply-To: <481...@gm...>\r\n\r\n')] + pat = re.compile(r"(?P<seqno>\d+) \(UID (?P<uid>\d+) FLAGS \((?P<flags>[^)]+)\)") + for i, ((envelope, data), paren) in enumerate(seqs.grouper(2, fetch_range(imap, minuid, maxuid))): + # Parse the body. + msg = email.message_from_string(data) + + # Parse the envelope. + m = pat.match(envelope) + if m is None: raise Exception('envelope: %r' % envelope) + msg.seqno = m.group('seqno') + msg.uid = m.group('uid') + msg.flags = m.group('flags').split() + + # Prepare a container for references to other msgs, and initialize the + # thread ID. + msg.refs = set() + msg.tid = None + + # Add these to the map. + if msg['Message-ID'] in mid2msg: + log.warning( 'dups', 'duplicate message IDs:', + msg['Message-ID'], msg['Subject'] ) + mid2msg[ msg['Message-ID'] ] = msg + + # Periodically sync to disk. + if len(mid2msg.cache) > 1000: mid2msg.sync() + + mid2msg['maxuid'] = maxuid + +# +# Function for analyzing messages. +# + +def itermsgs(mid2msg, minuid, midsrc = None): + if midsrc is None: midsrc = mid2msg + special_keys = ['maxuid', 'procuid'] + for i, (mid, msg) in enumerate(midsrc.iteritems()): + if mid not in special_keys and msg.uid >= minuid: + if midsrc is mid2msg: yield msg + else: yield mid2msg[mid] + # Periodically sync to disk. + if mid2msg.cache is not None and len(mid2msg.cache) > 10000: + debug( 'syncing; now at i', i, 'mid', mid ) + mid2msg.sync() + debug( 'syncing; finished after i', i, 'mid', mid ) + mid2msg.sync() + +def thread_dfs(msg, tid, mid2msg): + assert msg.tid is None + msg.tid = tid + for refmid in msg.refs: + try: + refmsg = mid2msg[refmid] + except KeyError: + log.warning('badref', 'no message with mid', refmid) + else: + if refmsg.tid is None: thread_dfs(refmsg, tid, mid2msg) + else: assert refmsg.tid == tid + +def mark_relevant_threads(cfg): + + shutil.copy(dbpath(cfg, 'fetched'), dbpath(cfg, 'bidir')) + + with closing(opendb(cfg, 'fetched')) as midsrc: + with closing(opendb(cfg, 'bidir', 'w')) as mid2msg: + procuid = mid2msg.get('procuid', 0) + minuid = procuid + 1 + info( 'maxuid', midsrc['maxuid'], 'procuid', procuid ) + del procuid + info( 'constructing bidirectional ref graph' ) + for msg in itermsgs(mid2msg, minuid, midsrc): + debug('processing', msg['Message-ID']) + irt = msg.get_all('In-Reply-To', []) + refs = msg.get_all('References', []) + newrefs = ' '.join( irt + refs ).replace('><', '> <').split() + msg.refs.update( newrefs ) + + # Connect nodes in graph bidirectionally. Ignore references to MIDs + # that don't exist. + for ref in newrefs: + debug('adding', ref, '<->', msg['Message-ID']) + try: mid2msg[ref].refs.add( msg['Message-ID'] ) + except KeyError: log.warning( 'badref', 'no message with mid', ref ) + + shutil.copy(dbpath(cfg, 'bidir'), dbpath(cfg, 'threaded')) + + with closing(opendb(cfg, 'bidir')) as midsrc: + with closing(opendb(cfg, 'threaded', 'w')) as mid2msg: + info( 'looking for relevant msgs (grouping them into threads)' ) + tids = itertools.count() + for msg in itermsgs(mid2msg, minuid, midsrc): + debug('threading', msg['Message-ID']) + if ( msg.tid is None and + ( cfg.sender in msg.get('From', '') or + cfg.sender in msg.get('To', '') or + cfg.sender in msg.get('Cc', '') ) ): + thread_dfs(msg, tids.next(), mid2msg) + +# +# Functions for storing metadata changes back to the server. +# + +def flag_relevant_msgs(cfg, imap, midsrc, mid2msg): + + info( 'starring/unstarring relevant/irrelevant threads' ) + + for msg in itermsgs(mid2msg, 0, midsrc): + if msg.tid is not None: # is a relevant msgs + if r'\Flagged' not in msg.flags: # not already flagged + mark_unseen = not cfg.no_mark_unseen and r'\Seen' in msg.flags + log.info( 'star', '\n', + 'star' + (' and mark unseen' if mark_unseen else ''), + msg ) + if not cfg.pretend: + imap.uid('STORE', msg.uid, '+FLAGS', r'\Flagged') + msg.flags.append(r'\Flagged') + if mark_unseen: + imap.uid('STORE', msg.uid, '-FLAGS', r'\Seen') + msg.flags.remove(r'\Seen') + else: # is not a relevant msg + if r'\Flagged' in msg.flags: # was inadvertently flagged + mark_seen = not cfg.no_mark_seen and r'\Seen' not in msg.flags + log.info( 'unstar', '\n', + 'unstar' + (' and mark seen' if mark_seen else ''), + msg ) + if not cfg.pretend: + imap.uid('STORE', msg.uid, '-FLAGS', r'\Flagged') + msg.flags.remove(r'\Flagged') + if mark_seen: + imap.uid('STORE', msg.uid, '+FLAGS', r'\Seen') + msg.flags.append(r'\Seen') + + mid2msg['procuid'] = mid2msg['maxuid'] + +# +# Main function. +# + +def main(argv): + p = argparse.ArgumentParser(description = __doc__) + p.add_argument('--credfile', default = path( '~/.mlf.auth' ).expanduser(), + help = """File containing your login credentials, with the username on the + first line and the password on the second line. Ignored iff --prompt.""") + p.add_argument('--cachedir', default = path( '~/.mlf.cache' ).expanduser(), + help = "Directory to use for caching our data.") + p.add_argument('--refresh', action = 'store_true', + help = "Re-fetch all messages, wiping out existing cache.") + p.add_argument('--prompt', action = 'store_true', + help = "Interactively prompt for the username and password.") + p.add_argument('--pretend', action = 'store_true', + help = """Do not actually carry out any updates to the server. Use in + conjunction with --debug to observe what would happen.""") + p.add_argument('--no-mark-unseen', action = 'store_true', + help = "Do not mark newly revelant threads as unread.") + p.add_argument('--no-mark-seen', action = 'store_true', + help = "Do not mark newly irrevelant threads as read.") + p.add_argument('--no-fetch', action = 'store_true', + help = "Do not fetch new messages; just process already-fetched messages.") + p.add_argument('--debug', action = 'append', default = [], + help = """Enable logging for messages of the given flags. Flags include: + refs (references to missing Message-IDs), dups (duplicate Message-IDs), + main (the main program logic), and star (which messages are being + starred), unstar (which messages are being unstarred).""") + p.add_argument('sender', + help = "Your email address.") + p.add_argument('server', + help = "The server in the format: <host>[:<port>][/<mailbox>].") + + cfg = p.parse_args(argv[1:]) + + config_logging(level = logging.ERROR, do_console = True, flags = cfg.debug) + + if cfg.prompt: + print "username:", + cfg.user = raw_input() + print "password:", + cfg.passwd = getpass.getpass() + else: + with file(cfg.credfile) as f: + [cfg.user, cfg.passwd] = map(lambda x: x.strip('\r\n'), f.readlines()) + + try: + m = re.match( r'(?P<host>[^:/]+)(:(?P<port>\d+))?(/(?P<mailbox>.+))?$', + cfg.server ) + cfg.host = m.group('host') + cfg.port = int( m.group('port') or 993 ) + cfg.mailbox = m.group('mailbox') or 'INBOX' + except: + p.error('Need to specify the server in the correct format.') + + files.soft_makedirs(cfg.cachedir) + + if not cfg.no_fetch: + with login_imap(cfg) as imap: + fetch_new_mail(cfg, imap) + + mark_relevant_threads(cfg) + + shutil.copy(dbpath(cfg, 'threaded'), dbpath(cfg, 'flagged')) + with login_imap(cfg) as imap: + with closing(opendb(cfg, 'threaded')) as midsrc: + with closing(opendb(cfg, 'flagged', 'w')) as mid2msg: + flag_relevant_msgs(cfg, imap, midsrc, mid2msg) + os.rename(dbpath(cfg, 'fetched'), dbpath(cfg, 'fetched-old')) + os.rename(dbpath(cfg, 'flagged'), dbpath(cfg, 'fetched')) + +startup.run_main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-29 04:53:03
|
Revision: 1530 http://assorted.svn.sourceforge.net/assorted/?rev=1530&view=rev Author: yangzhang Date: 2009-12-29 04:52:52 +0000 (Tue, 29 Dec 2009) Log Message: ----------- - distinguish between failures requiring logout and failures requiring close - remove procuid - use separate read and write databases in flag_relevant_msgs - fixed: updates to the imap store are also applied to our local cache - release v0.2.1 Modified Paths: -------------- mailing-list-filter/trunk/README mailing-list-filter/trunk/publish.bash mailing-list-filter/trunk/setup.py mailing-list-filter/trunk/src/mlf.py Modified: mailing-list-filter/trunk/README =================================================================== --- mailing-list-filter/trunk/README 2009-12-22 19:20:10 UTC (rev 1529) +++ mailing-list-filter/trunk/README 2009-12-29 04:52:52 UTC (rev 1530) @@ -62,6 +62,10 @@ Changes ------- +v0.2.1 + +- Bug fixes. + v0.2 - Added disk-based operation to remove memory capacity limit. Modified: mailing-list-filter/trunk/publish.bash =================================================================== --- mailing-list-filter/trunk/publish.bash 2009-12-22 19:20:10 UTC (rev 1529) +++ mailing-list-filter/trunk/publish.bash 2009-12-29 04:52:52 UTC (rev 1530) @@ -1,7 +1,7 @@ #!/usr/bin/env bash fullname='Mailing List Filter' -version=0.2 +version=0.2.1 license=gpl3 websrcs=( README ) rels=( pypi: ) Modified: mailing-list-filter/trunk/setup.py =================================================================== --- mailing-list-filter/trunk/setup.py 2009-12-22 19:20:10 UTC (rev 1529) +++ mailing-list-filter/trunk/setup.py 2009-12-29 04:52:52 UTC (rev 1530) @@ -5,7 +5,7 @@ pkg_info_text = """ Metadata-Version: 1.1 Name: mailing-list-filter -Version: 0.2 +Version: 0.2.1 Author: Yang Zhang Author-email: yaaang NOSPAM at REMOVECAPS gmail Home-page: http://assorted.sourceforge.net/mailing-list-filter/ Modified: mailing-list-filter/trunk/src/mlf.py =================================================================== --- mailing-list-filter/trunk/src/mlf.py 2009-12-22 19:20:10 UTC (rev 1529) +++ mailing-list-filter/trunk/src/mlf.py 2009-12-29 04:52:52 UTC (rev 1530) @@ -46,13 +46,24 @@ @contextmanager def login_imap(cfg): info('connecting and logging in') - with networking.logout(imaplib.IMAP4_SSL(cfg.host, cfg.port)) as imap: + imap = imaplib.IMAP4_SSL(cfg.host, cfg.port) + try: imap.login(cfg.user, cfg.passwd) # Close is only valid in the authenticated state. - with closing(imap) as imap: + try: info('selecting mailbox') imap.select(cfg.mailbox) yield imap + except Exception, ex: + try: imap.close() + except imaplib.abort: raise ex + else: + imap.close() + except Exception, ex: + try: imap.logout() + except imaplib.abort: raise ex + else: + imap.logout() # # Functions for fetching messages from the server. @@ -142,8 +153,6 @@ if len(mid2msg.cache) > 1000: mid2msg.sync() mid2msg['maxuid'] = maxuid - # XXX - mid2msg['procuid'] = mid2msg['maxuid'] # # Function for analyzing messages. @@ -218,11 +227,11 @@ # Functions for storing metadata changes back to the server. # -def flag_relevant_msgs(cfg, imap, mid2msg): +def flag_relevant_msgs(cfg, imap, midsrc, mid2msg): info( 'starring/unstarring relevant/irrelevant threads' ) - for msg in itermsgs(mid2msg, 0): + for msg in itermsgs(mid2msg, 0, midsrc): if msg.tid is not None: # is a relevant msgs if r'\Flagged' not in msg.flags: # not already flagged mark_unseen = not cfg.no_mark_unseen and r'\Seen' in msg.flags @@ -231,7 +240,10 @@ msg ) if not cfg.pretend: imap.uid('STORE', msg.uid, '+FLAGS', r'\Flagged') - if mark_unseen: imap.uid('STORE', msg.uid, '-FLAGS', r'\Seen') + msg.flags.append(r'\Flagged') + if mark_unseen: + imap.uid('STORE', msg.uid, '-FLAGS', r'\Seen') + msg.flags.remove(r'\Seen') else: # is not a relevant msg if r'\Flagged' in msg.flags: # was inadvertently flagged mark_seen = not cfg.no_mark_seen and r'\Seen' not in msg.flags @@ -240,7 +252,10 @@ msg ) if not cfg.pretend: imap.uid('STORE', msg.uid, '-FLAGS', r'\Flagged') - if mark_seen: imap.uid('STORE', msg.uid, '+FLAGS', r'\Seen') + msg.flags.remove(r'\Flagged') + if mark_seen: + imap.uid('STORE', msg.uid, '+FLAGS', r'\Seen') + msg.flags.append(r'\Seen') mid2msg['procuid'] = mid2msg['maxuid'] @@ -308,8 +323,12 @@ mark_relevant_threads(cfg) + shutil.copy(dbpath(cfg, 'threaded'), dbpath(cfg, 'flagged')) with login_imap(cfg) as imap: - with closing(opendb(cfg, 'threaded')) as mid2msg: - flag_relevant_msgs(cfg, imap, mid2msg) + with closing(opendb(cfg, 'threaded')) as midsrc: + with closing(opendb(cfg, 'flagged', 'w')) as mid2msg: + flag_relevant_msgs(cfg, imap, midsrc, mid2msg) + os.rename(dbpath(cfg, 'fetched'), dbpath(cfg, 'fetched-old')) + os.rename(dbpath(cfg, 'flagged'), dbpath(cfg, 'fetched')) startup.run_main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-22 19:20:21
|
Revision: 1529 http://assorted.svn.sourceforge.net/assorted/?rev=1529&view=rev Author: yangzhang Date: 2009-12-22 19:20:10 +0000 (Tue, 22 Dec 2009) Log Message: ----------- added websockets example Added Paths: ----------- sandbox/trunk/src/web/ sandbox/trunk/src/web/websocket/ sandbox/trunk/src/web/websocket/client.html sandbox/trunk/src/web/websocket/server.py Added: sandbox/trunk/src/web/websocket/client.html =================================================================== --- sandbox/trunk/src/web/websocket/client.html (rev 0) +++ sandbox/trunk/src/web/websocket/client.html 2009-12-22 19:20:10 UTC (rev 1529) @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>Web Socket Example</title> + <meta charset="UTF-8"> + <script> + window.onload = function() { + var s = new WebSocket("ws://localhost:9876/"); + var data = []; + s.onmessage = function(e) { + var parts = e.data.split(' '); + var x = parseFloat(parts[0]), y = parseFloat(parts[1]); + data.push([x,y]); + $.plot( $("#holder"), + [ { data: data } ], + { + series: { + lines: { show: true, fill: true }, + points: { show: true }, + }, + xaxis: { min: 0, max: 10 }, + yaxis: { min: 0, max: 10 }, + } ); + }; + }; + </script> + </head> + <body> + <div id="holder" style="width:600px; height:300px"></div> + </body> +</html> Added: sandbox/trunk/src/web/websocket/server.py =================================================================== --- sandbox/trunk/src/web/websocket/server.py (rev 0) +++ sandbox/trunk/src/web/websocket/server.py 2009-12-22 19:20:10 UTC (rev 1529) @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +import socket, threading, time + +def handle(s): + print repr(s.recv(4096)) + s.send(''' +HTTP/1.1 101 Web Socket Protocol Handshake\r +Upgrade: WebSocket\r +Connection: Upgrade\r +WebSocket-Origin: http://localhost:8888\r +WebSocket-Location: ws://localhost:9876/\r +WebSocket-Protocol: sample + '''.strip() + '\r\n\r\n') + time.sleep(1) + s.send('\x00hello\xff') + time.sleep(1) + s.send('\x00world\xff') + s.close() + +s = socket.socket() +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +s.bind(('', 9876)); +s.listen(1); +while 1: + t,_ = s.accept(); + threading.Thread(target = handle, args = (t,)).start() Property changes on: sandbox/trunk/src/web/websocket/server.py ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <yan...@us...> - 2009-12-18 00:37:20
|
Revision: 1528 http://assorted.svn.sourceforge.net/assorted/?rev=1528&view=rev Author: yangzhang Date: 2009-12-18 00:37:04 +0000 (Fri, 18 Dec 2009) Log Message: ----------- added real-time plotter Added Paths: ----------- real-time-plotter/ real-time-plotter/trunk/ real-time-plotter/trunk/src/ real-time-plotter/trunk/src/rtp.html real-time-plotter/trunk/src/server.py Added: real-time-plotter/trunk/src/rtp.html =================================================================== --- real-time-plotter/trunk/src/rtp.html (rev 0) +++ real-time-plotter/trunk/src/rtp.html 2009-12-18 00:37:04 UTC (rev 1528) @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>Real Time Plotter</title> + <meta charset="UTF-8"> + <script src="http://people.iola.dk/olau/flot/jquery.js"></script> + <script src="http://people.iola.dk/olau/flot/jquery.flot.js"></script> + <script> + window.onload = function() { + var s = new WebSocket("ws://hammer.csail.mit.edu:9877/"); + var data = {}; + s.onmessage = function(e) { + //alert('got ' + e.data); + var lines = e.data.split('\n'); + for (var i = 0; i < lines.length - 1; i++) { + var parts = lines[i].split(' '); + var d = parts[0], x = parseFloat(parts[1]), y = parseFloat(parts[2]); + if (!(d in data)) data[d] = []; + data[d].push([x,y]); + } + + var plots = []; + for (var d in data) plots.push( { data: data[d].slice(data[d].length - 200) } ); + $.plot( $("#holder"), plots, + { + series: { + lines: { show: true, fill: true }, + //points: { show: true }, + }, + //xaxis: { min: 0, max: 10 }, + //yaxis: { min: 0, max: 10 }, + xaxis: { min: 0 }, + yaxis: { min: 0 }, + } ); + + s.send(''); + }; + }; + </script> + </head> + <body> + <div id="holder" style="width:600px;height:300px"></div> + </body> +</html> Added: real-time-plotter/trunk/src/server.py =================================================================== --- real-time-plotter/trunk/src/server.py (rev 0) +++ real-time-plotter/trunk/src/server.py 2009-12-18 00:37:04 UTC (rev 1528) @@ -0,0 +1,120 @@ +#!/usr/bin/env python + +# I group the x values by the 1000s and only keep one distinct point from each +# such unique value. This is because I was written expecting millisecond +# timestamps for x values, and I only need to plot second granularity. This is +# easy to adjust/remove. + +from __future__ import with_statement +import contextlib, Queue as queue, socket, threading, time + +...@co...ntextmanager +def locking(lock): + lock.acquire() + try: yield + finally: lock.release() + +def listen(port, handler): + s = socket.socket() + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind(('', port)); + s.listen(1); + while 1: + t,_ = s.accept(); + threading.Thread(target = handler, args = (t,)).start() + +q = queue.Queue() + +def handle_source(s): + f = s.makefile() + name = f.readline().strip() + print 'new source', name + try: + while 1: + line = f.readline() + if line == '': break + x, y = map(float, line.split()) + q.put(('source', (name, (x, y)))) + finally: + q.put(('source', (name, None))) + print 'source', name, 'stopped' + +def first(xs, x): return xs[0] if len(xs) > 0 else x +def last(xs, x): return xs[-1] if len(xs) > 0 else x + +def pump(): + active = set() + sinks = [] + data = {} + ordered_names = [] + start_time = None + while 1: + msgtype, msg = q.get() + if msgtype == 'source': + name, value = msg + if name not in active: + active.add(name) + data[name] = (last(ordered_names, None), []) + ordered_names.append(name) + #start_time = None + if value is None: # source stopped + ordered_names.remove(name) + active.remove(name) + for n in data: + if data[n][0] == name: + data[n] = (data[name][0], data[n][1]) + break + else: # source append + x, y = value + x = int(x) / 1000 + if start_time is None: + start_time = min([x] + [first(series, (x,y))[0] for pred, series in data.itervalues()]) + x -= start_time + pred, series = data[name] + if len(series) == 0 or series[-1][0] != x: + y += data[pred][1][-1][1] if pred is not None else 0 + series.append((x, y)) + for sink in sinks: sink.put((name, (x, y))) + elif msgtype == 'sink': + sink = msg + sink.put( dict( (name, series + []) + for name, (pred,series) in data.iteritems() ) ) + sinks.append(sink) + +def handle_sink(s): + print 'new sink', repr(s.recv(4096)) + s.send(''' +HTTP/1.1 101 Web Socket Protocol Handshake\r +Upgrade: WebSocket\r +Connection: Upgrade\r +WebSocket-Origin: http://hammer.csail.mit.edu:8888\r +WebSocket-Location: ws://hammer.csail.mit.edu:9877/ + '''.strip()) + s.send('\r\n\r\n') + qq = queue.Queue() + q.put(('sink', qq)) + data = qq.get() + if True: + s.send('\x00') + for d in data: + for x, y in data[d]: + s.send('%s %s %s\n' % (d, x, y)) + s.send('\xff') + print 'sent historical data' + while 1: + if s.recv(4096) == '': break + s.send('\x00') + sent_sthg = False + while 1: + if qq.empty() and sent_sthg: break + msg = qq.get() + d, (x, y) = msg + s.send('%s %s %s\n' % (d, x, y)) + sent_sthg = True + s.send('\xff') + print 'client closed' + s.close() + +threading.Thread(target = listen, args = (9876, handle_source)).start() +threading.Thread(target = listen, args = (9877, handle_sink)).start() +pump() Property changes on: real-time-plotter/trunk/src/server.py ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |