" " Filename: cream-lib " " Cream -- An easy-to-use configuration of the famous Vim text editor " [ http://cream.sourceforge.net ] Copyright (C) 2001-2007 Steve Hall " " License " GNU General Public License (GPL) {{{1 " " This program is free software; you can redistribute it and/or modify " it under the terms of the GNU General Public License as published by " the Free Software Foundation; either version 2 of the License, or " (at your option) any later version. [ " http://www.gnu.org/licenses/gpl.html ] " " This program is distributed in the hope that it will be useful, but " WITHOUT ANY WARRANTY; without even the implied warranty of " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU " General Public License for more details. " " You should have received a copy of the GNU General Public License " along with this program; if not, write to the Free Software " Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA " 02111-1307, USA. " " 1}}} " General " Path and Files {{{1 function! Cream_browse_pathfile() " uses dialog to return a path/filename let mypathfile = browse(0, "Select file", getcwd(), '*.*') " remove filename let mypathfile = fnamemodify(mypathfile, ":p") " handle spaces let mypathfile = escape(mypathfile, ' \') return mypathfile endfunction function! Cream_browse_path(...) " Return a directory (full path) via dialog (back/slashes and escaping " not guaranteed to be correct for system call). " o Returns "" on cancel or error. " o Verifies return is a directory. " o Does not verify return is writable. " o Argument 1: optional start path " o Argument 2: (requires arg 1) optional file filter " NOTE: THIS FUNCTION IS GOING TO BECOME OBSOLETE WITH " THE INTRODUCTION OF browsedir(). ""*** DEBUG: "let n = confirm( " \ "DEBUG:\n" . " \ " a:0 = \"" . a:0 . "\"\n" . " \ " a:1 = \"" . a:1 . "\"\n" . " \ " a:2 = \"" . a:2 . "\"\n" . " \ "\n", "&Ok\n&Cancel", 1, "Info") " if n != 1 " return "endif ""*** if a:0 > 0 if a:0 == 1 "call confirm( " \ "Error: Incorrect number of arguments passed to Cream_browse_path().\n" . " \ "\n" . " \ "Quitting...\n" . " \ "\n", "&Ok", 1, "Info") "return "" let initpath = a:1 let filefilter = "*.*" else let initpath = a:1 let filefilter = a:2 endif else let initpath = getcwd() let filefilter = "*.*" endif " TODO: filters broken. "if exists("g:browsefilter") " unlet g:browsefilter "endif "let g:browsefilter = "Directories\t*\*;*\*\nVim Files\t*.vim;*.vim\nAll Files\t*.*;*.*\n" "let g:browsefilter = "Directories\t*\\*;*\\*\nVim Files\t*.vim;*.vim\nAll Files\t*.*;*.*\n" "let g:browsefilter = "Directories (*.)\nVim Files (*.vim)\nAll Files (*.*)\n" "let g:browsefilter = "Bob Files\t*.bob\nVim Files\t*.vim\nAll Files\t*.*\n" "let g:browsefilter = "Directories\t*.\nVim Files\t*.vim\nAll Files\t*.*\n" let mypath = browse(0, "Select directory", initpath, filefilter) " cancel or error, return empty if mypath == "" return "" endif ""*** DEBUG: "if exists("g:cream_dev") " let n = confirm( " \ "DEBUG: in Cream_browse_path()\n" . " \ " mypath = \"" . mypath . "\"\n" . " \ "\n", "&Ok\n&Cancel", 1, "Info") " if n != 1 " return " endif "endif ""*** " expand to full path, subtract filename let mypath = fnamemodify(mypath, ":p:h") " handle escaping and spaces if Cream_has("ms") let mypath = substitute(mypath, '/', '\', 'g') else let mypath = escape(mypath, ' \') endif " append final slash back let mypath = mypath . "/" " test and return if isdirectory(mypath) != 0 return mypath else if exists("g:cream_dev") " failed call Cream_error_warning("Cream Devel: Cream_browse_path() failed to find object.") endif return "" endif endfunction function! Cream_get_dir_above(mypath) " returns a directory one level above value or empty if doesn't exist " remove filename let mystr = fnamemodify(a:mypath, ":h") " remove lowest subdirectory let mystr = fnamemodify(mystr, ":h") if !Cream_has("ms") " handle spaces let mystr = escape(mystr, ' \') endif " append final slash let mystr = mystr . "/" " test and return if isdirectory(mystr) != 0 return mystr else " failed call Cream_error_warning("Cream_get_dir_above() failed to get directory") return 0 endif endfunction function! Cream_getfilelist(path) " Return a file list based on path, including wildcards. The number of " newlines equals the number of files. If no file matches {path}, "" " is returned. " Notes: " o Separator between file names returned is a newline ("\n"). A " trailing newline is added if doesn't exist. " o Wildcard "*" for filename won't return files beginning with dot. " (Must use ".*" to obtain.) " o To optain directories, trail with "*/" " o Regexp support is available, e.g., to restrict extensions " beginning with "b" and "r", pass "*.[^br]*". " get file list let myfiles = glob(a:path) . "\n" " change paths to forward slashes to avoid escaping if Cream_has("ms") return substitute(myfiles, '\\', '/', 'g') endif " (from explorer.vim) " Add the dot files now, making sure "." is not included! "let myfiles = substitute(glob(g:rmpath), "[^\n]*/./\\=\n", '' , '') " ensure a return at the end if not empty if myfiles != "" && myfiles !~ '\n$' let myfiles = myfiles . "\n" endif return myfiles endfunction function! Cream_path_addtrailingslash(path) " Confirms {path} has a trailing slash appropriate for the system. let path = a:path if path !~ '/$' && path !~ '\$' if Cream_has("ms") let path = path . '\' else let path = path . '/' endif endif return path endfunction function! Cream_get_creamrc() if filereadable($CREAM . "creamrc") > 0 return $CREAM . "creamrc" else call Cream_error_warning("Cream_get_creamrc() failed to find vimrc") endif endfunction function! Cream_cmd_on_files(path, cmd) " do a particular command within the files in a series of paths " * If file is not modified as a result of the operation, it is closed " without saving. "let myfiles = glob(a:path) "" change paths to forward slashes to avoid escaping "if Cream_has("ms") " let myfiles = substitute(myfiles, '\\', '/', 'g') "endif "" ensure last has ending "if strlen(myfiles) > 0 " let myfiles = myfiles . "\n" "endif let myfiles = Cream_getfilelist(a:path) let i = 0 let max = MvNumberOfElements(myfiles, "\n") while i < max " get file let myfile = MvElementAt(myfiles, "\n", i) " save options {{{2 " turn off redraw let mylazyredraw = &lazyredraw set lazyredraw " turn off swap let myswapfile = &swapfile set noswapfile " turn off undo let myundolevels = &undolevels set undolevels=-1 " ignore autocmds let myeventignore = &eventignore set eventignore=all " unload buffers let myhidden = &hidden set nohidden " 2}}} " progress indication let mycmdheight = &cmdheight set cmdheight=2 echo " Progress: " . i . " of " . max . " (" . ((i*100) / max) . "%)" let &cmdheight = mycmdheight " open file execute "silent! edit! " . myfile " do it! execute a:cmd if &modified == 1 " save file execute "silent! write! " . myfile endif " close file (delete from buffer as is our preference ;) execute "silent! bwipeout!" " restore options {{{2 let &lazyredraw = mylazyredraw let &swapfile = myswapfile let &undolevels = myundolevels let &eventignore = myeventignore let &hidden = myhidden " 2}}} let i = i + 1 endwhile endfunction function! Cream_appendext(pathfile, ext) " save a file with an appended extension (good for temp files) " * return -1 if unable " append extension let myfilename = a:pathfile . "." . a:ext " open file as new buffer, if doesn't exist if filereadable(myfilename) == "TRUE" execute "saveas " . myfilename return else call confirm("Can not continue, a file named \"" . myfilename . "\" already exists here.", "&Ok", 1, "Warning") return -1 endif endfunction function! Cream_buffers_pathfile() " Initialize all buffers' b:cream_pathfilename var. " page through each buffer let i = 0 while i <= bufnr('$') let i = i + 1 if Cream_buffer_isspecial(i) == 0 \ && Cream_buffer_isnewunmod(i) == 0 if bufexists(i) let bufname = Cream_path_fullsystem(fnamemodify(bufname(i), ':p')) call setbufvar(i, "cream_pathfilename", bufname) endif endif endwhile endfunction function! Cream_buffer_pathfile() " Determine b:cream_pathfilename for the current buffer. (Used for " display in statusline and window title.) " o Set as text " o Proper according to the platform. " verify if !exists("b:cream_nr") call Cream_buffer_nr() endif if !exists("b:cream_pathfilename") || b:cream_pathfilename == "" let b:cream_pathfilename = Cream_path_fullsystem(expand('%:p')) " is directory if isdirectory(b:cream_pathfilename) let b:cream_pathfilename = "" " doesn't exist elseif bufexists(b:cream_nr) == 0 let b:cream_pathfilename = "[doesn't exist]" endif endif " keep testing if doesn't exist (in case SaveAs) if b:cream_pathfilename == "[doesn't exist]" if bufexists(b:cream_nr) != 0 let b:cream_pathfilename = Cream_path_fullsystem(expand('%:p')) endif endif endfunction function! Cream_buffer_nr() " Determine's the current buffer's number. if !exists("b:cream_nr") let b:cream_nr = bufnr("%") endif endfunction " Path and Files, User {{{1 function! Cream_load_user() " loads cream-user if present " Note: Cream_userdir() must be called prior to here to establish " g:cream_user if available (currently handled in autocmds). " load system cream-user call Cream_source($CREAM . "cream-user.vim") " load $HOME's cream-user if exists("g:cream_user") call Cream_source(g:cream_user . "cream-user.vim") endif endfunction " Debug and Error Handling {{{1 "function! Cream_debug() "" insert debug template " let mystr = "" " let mystr = mystr . "\"*** DEBUG:\n" " let mystr = mystr . "let n = confirm(\n" " let mystr = mystr . "\t\\ \"DEBUG:\\n\" .\n" " let mystr = mystr . "\t\\ \" myvar = \" . myvar . \"\\n\" .\n" " let mystr = mystr . "\t\\ \"\\n\", \"&Ok\\n&Cancel\", 1, \"Info\")\n" " let mystr = mystr . "if n != 1\n" " let mystr = mystr . "\treturn\n" " let mystr = mystr . "endif\n" " let mystr = mystr . "\"***\n" " let mystr = mystr . "\n" " let @x = mystr " normal "xp "endfunction function! Debug(...) " Handle debug requests " * accepts any number of quoted variables, and displays name and value let myarg = "DEBUG:\n\n" let i = 1 while exists("a:" . i) execute "let myarg = myarg . \" " . a:{i} . " = \" . " . a:{i} " . \"\n\"" let i = i + 1 endwhile if has("gui_runnning") && has("dialog_gui") call confirm(myarg, "&Ok", 1) else echo myarg endif endfunction function! Cream_error_notice(myerror) if has("dialog_gui") call confirm("Notice:\n" . a:myerror, "&Ok", 1, "Info") else echo "----------------------------------------------------------------------" echo "Notice:" echo a:myerror echo "----------------------------------------------------------------------" endif endfunction function! Cream_error_warning(myerror) if has("dialog_gui") call confirm("Warning:\n" . a:myerror, "&Ok", 1, "Error") else echo "----------------------------------------------------------------------" echo "Warning:" echo a:myerror echo "----------------------------------------------------------------------" endif endfunction function! Cream_error_critical(myerror) if has("dialog_gui") call confirm("Critical:\n" . a:myerror, "&Ok", 1, "Warning") else echo "----------------------------------------------------------------------" echo "Critical:" echo a:myerror echo "----------------------------------------------------------------------" endif endfunction " 1}}} " Help {{{1 function! Cream_help(...) " open a $CREAM docs-html/{file} in the default browser " If {...} is empty, use keyboardshortcuts.html. let file = "" " try argument if a:0 > 0 let file = Cream_path_fullsystem($CREAM . 'docs-html/' . a:1) endif if filereadable(file) != 1 " if argument, warn invalid if a:0 > 0 " no command found, exit call confirm( \ "Invalid document looked up, using default.\n" . \ "\n", "&Ok", 1, "Info") endif let file = Cream_path_fullsystem($CREAM . 'docs-html/keyboardshortcuts.html') endif return Cream_file_open_defaultapp(file) endfunction function! Cream_help_find(...) " help control if a:0 > 0 let myhelp = a:1 " toggle open/closed (only close if on first page, help.txt) " try to find it let i = 1 while i <= bufnr("$") " move to it if Cream_buffer_ishelp(i) == 1 \&& fnamemodify(bufname(i), ":t") == "help.txt" " goto "help.txt" call MoveCursorToWindow(bufwinnr(i)) bwipeout! return endif let i = i + 1 endwhile else let mymsg = \ "Enter a command or word to find help on:\n" . \ "\n" . \ "Prepend i_ for Input mode commands (e.g.: i_CTRL-X)\n" . \ "Prepend c_ for command-line editing commands (e.g.: c_)\n" . \ "Prepend ' for an option name (e.g.: 'shiftwidth')\n" let myhelp = inputdialog(mymsg) " if empty, quit without confirmation if myhelp == "" return endif endif " window management " don't pop help from a special, unless it's help if Cream_buffer_isspecial() == 1 \&& Cream_buffer_ishelp() == 0 call Cream_TryAnotherWindow() endif let v:errmsg = "" silent! execute "help " . myhelp " indicate error in dialog if v:errmsg != "" call confirm(v:errmsg, "&Ok", 1, "Info") return endif " remember help height during the session let g:cream_help_size = winheight(0) " window management " remove all hidden help buffers (do before setup, since Vim's " :help command won't remove a previously open) call Cream_help_hidden_remove() " get help buffer number (current) let mybufnr = bufnr("%") call Cream_window_setup() " restore cursor to help buffer's (new) window call MoveCursorToWindow(bufwinnr(mybufnr)) endfunction function! Cream_help_hidden_remove() " remove all hidden help buffers (do this after we open ours so we " know it's hidden ;) let mybufnr = bufnr("%") let i = 1 while i <= bufnr('$') if Cream_buffer_ishelp(i) == 1 \&& bufwinnr(i) == -1 execute "bwipeout! " . i endif let i = i + 1 endwhile endfunction function! Cream_help_listtopics() let mymsg = \ "Enter a command or word to list help topics:\n" . \ "(results will be listed below the statusbar)\n" \ "\n" let myhelp = inputdialog(mymsg) if myhelp != "" let v:errmsg = "" execute "normal :help " . myhelp . "\" if v:errmsg != "" "+++ Cream: add dialog feedback if has("dialog_gui") call confirm(v:errmsg, "&Ok", 1) else echo v:errmsg endif "+++ endif endif call Cream_help_find() endfunction function! Cream_help_tags() " Re-define helptags of all .txt files in the current buffer's " directory. (See :helptags.) "set filetype=help execute "helptags " . expand("%:p:h") "set filetype=txt filetype detect endfunction " About Splash/License {{{1 function! Cream_splash() if has("gui_running") let str = \ "\n" . \ " Cream (for Vim) \n" . \ "\n" . \ " http://cream.sourceforge.net \n" . \ " " . g:cream_mail . " \n" . \ "\n" . \ "\n" . \ " Version: " . g:cream_version_str . " \n" . \ " " . g:cream_updated . " \n" . \ " * * * \n" . \ "\n" . \ " Vim version: " . Cream_version("string") . " \n" . \ "\n" let n = confirm( \ str . \ "\n", "&Ok", 3, "Info") endif endfunction function! Cream_license() " split open $CREAM/docs/COPYING.txt read-only call Cream_file_new() execute "read " . $CREAM . "docs/COPYING.txt" set nomodified endfunction " Features Cream_has(){{{1 function! Cream_has(property) " return 1 if Cream has feature, 0 if not, -1 on error " o See cases below for allowable arguments " a tags file exists if a:property == "tagsfile" if filereadable(expand("%:p:h") . "/tags") == 1 return 1 endif " app tags (or variant) exists " Note: Gentoo Linux properly appends "ctags" with "exuberant-" elseif a:property == "tags" if executable("ctags") == 1 \|| executable("exuberant-ctags") == 1 \|| executable("tags") == 1 return 1 endif " on a Microsoft system elseif a:property == "ms" " function defined in genutils.vim return OnMS() endif return 0 endfunction " Vim file lists {{{1 function! Cream_vim_syntax_list() " returns alphabetized list of syntax/*.vim, separated by "\n" " TODO: Use this prototype to return any file list from path. let mypath = $VIMRUNTIME . '/syntax/' if v:version >= 602 && Cream_has("ms") " BUGFIX: glob needs an "OS-friendly" path let myrt = fnamemodify(mypath, ":8") endif let myfiles = glob(mypath . "*.vim") " self-determine preceding path (as determined by glob() above) let str = matchstr(myfiles, '.\{-1,}syntax.\ze..\{-1,}\.vim') let myfiles = substitute(myfiles, escape(str, '~'), "", "g") let myfiles = substitute(myfiles, '\.vim', "", "g") return myfiles endfunction " Get filetypes {{{1 function! Cream_get_filetypes() " get a list of all potential Vim filetypes by parsing the output of " "autocmd filetypedetect" " " Hack: We're opening a temp buffer and processing the redirected " output. Not sure to sort, substitute, and uniq a var. " save cmdheight let mych = &cmdheight set cmdheight=8 set shortmess=stOTI " get list of filetype autocommands redir @x silent! autocmd filetypedetect redir END " restore cmdheight let &cmdheight = mych " open temp buffer silent! enew silent! put x " put all 'setf [:alnum:] at line beginnings silent! %substitute/^\s*.*\(setf\s\+[A-Za-z0-9]\+\)/\1\r/gei " remove all lines not beginning 'setf' silent! %substitute/^\(setf\)\@!.*$//gei " remove all initial 'setf ' silent! %substitute/^setf\s\+//gei " remove all empty lines silent! %substitute/\n\n\+/\r/gei " sort file silent! call BISort2(0, line("$")) " unselect normal i " remove initial empty line silent! %substitute/^\n//gei " uniq silent! call Uniq(0, line("$")) " select all silent! call Cream_select_all("endvisual") " yank normal "xy " close buffer silent! bwipeout! return @x endfunction " Strings, dialogs, and i18n {{{1 function! Cream_confirm() " endfunction function! Cream_echo() endfunction function! Cream_inputdialog(prompt, default) endfunction " Inputdialog() {{{1 function! Inputdialog(prompt, default) " Wraps Vim's "inputdialog()" function to accommodate Vim versions " prior to 6.2 which are unable to distinguish between a returned " Cancel value or an empty string value. When Vim version < 6.2, the " user is first prompted to distingish the two. " " Returns: " " string When return value is not empty " "" When determins the user wants an empty value " "{cancel}" When determins the user wants to cancel " if version >= 602 return inputdialog(a:prompt, a:default, "{cancel}") endif let myreturn = inputdialog(a:prompt, a:default) if myreturn == "" let n = confirm( \ "Leave Empty or Cancel?\n" . \ "\n" . \ "(Vim versions prior to 6.2 can't tell\n", \ "between an empty value and cancel.)\n", \ "&Leave\ Empty\n&Cancel", 2) if n != 1 return "{cancel}" else return "" endif endif return myreturn endfunction " 1}}} " File open, close " Last buffer restore {{{1 function! Cream_start() " obsolete endfunction function! Cream_last_buffer_restore() " Recall name of last current buffer and restore. " see if last buffer name was saved in Cream_exit() last session if exists("g:CREAM_LAST_BUFFER") " only open if exists (able to be written) if filewritable(g:CREAM_LAST_BUFFER) == 1 " NOTE: Must use name, number changes on restart. if bufexists(g:CREAM_LAST_BUFFER) if v:version >= 700 && exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1 call Cream_tab_goto(bufnr(g:CREAM_LAST_BUFFER)) else execute "buffer! " . g:CREAM_LAST_BUFFER endif else " Don't warn if unable to find! (This could be " experienced from any number of means, such as with a " second instance.) endif endif endif " TODO: leftover vestage of Cream_start(), also in tab_init. "" kill off any open special buffers "call Cream_buffers_delete_untitled() "call Cream_buffers_delete_special() endfunction function! Cream_last_buffer_toggle() " toggle restoration of last buffer behavior " default (restore) is not existing (or 0), don't restore == 1 if exists("g:CREAM_LAST_BUFFER_FORGET") unlet g:CREAM_LAST_BUFFER_FORGET else let g:CREAM_LAST_BUFFER_FORGET = 1 endif call Cream_menu_settings_preferences() endfunction " Var Management {{{1 function! Cream_var_manage() " variable management " * handle obsolete memorized global variable names " * correct variable types if !exists("g:CREAM_VARFIX_022") " v.12 and prior " -------------- " last buffer if exists("g:LAST_BUFFER") let g:CREAM_LAST_BUFFER = g:LAST_BUFFER unlet g:LAST_BUFFER endif " ReplaceMultifile if exists("g:RMFIND") let g:CREAM_RMFIND = g:RMFIND unlet g:RMFIND endif if exists("g:RMREPL") let g:CREAM_RMREPL = g:RMREPL unlet g:RMREPL endif if exists("g:RMPATH") let g:CREAM_RMPATH = g:RMPATH unlet g:RMPATH endif " MRU (Most recent used file menu) if exists("g:MRU_MENU") let g:CREAM_MRU_MENU = g:MRU_MENU unlet g:MRU_MENU endif if exists("g:MRU_MAX") let g:CREAM_MRU_MAX = g:MRU_MAX unlet g:MRU_MAX endif if exists("g:MRU_BUF_COUNT") let g:CREAM_MRU_BUF_COUNT = g:MRU_BUF_COUNT unlet g:MRU_BUF_COUNT endif if exists("g:MRU_MENU_PRIO") let g:CREAM_MRU_MENU_PRIO = g:MRU_MENU_PRIO unlet g:MRU_MENU_PRIO endif if exists('g:CREAM_MRU_MENU_PRIO') unlet g:CREAM_MRU_MENU_PRIO endif " individual buffers, now obsolete (1 through arbitrary 30) if exists("g:CREAM_MRU_MAX") let i = 0 while i < 30 "call Debug("i") if exists("g:MRU_BUFFER" . i) execute "let g:CREAM_MRU_BUFFER" . i . " = g:MRU_BUFFER" . i execute "unlet g:MRU_BUFFER" . i endif let i = i + 1 endwhile endif if exists('g:CREAM_MRU_MAX') unlet g:CREAM_MRU_MAX endif " v.13 " ---- " update language variable (only english existed) if exists("g:CREAM_SPELL_LANG") if g:CREAM_SPELL_LANG == "eng" let g:CREAM_SPELL_LANG = "eng,m;" endif endif " v.14 " ---- " version case change if exists('g:Cream_version') unlet g:Cream_version endif " show invisibles if exists('g:CREAM_LIST') unlet g:CREAM_LIST endif " migrate to distinguishing between platforms so multiple can be " supported [08 Sep 2002 v0.15] if exists("g:CREAM_COLS") let g:CREAM_COLS_{myos} = g:CREAM_COLS unlet g:CREAM_COLS endif if exists("g:CREAM_LINES") let g:CREAM_LINES_{myos} = g:CREAM_LINES unlet g:CREAM_LINES endif if exists("g:CREAM_WINPOSX") let g:CREAM_WINPOSX_{myos} = g:CREAM_WINPOSX unlet g:CREAM_WINPOSX endif if exists("g:CREAM_WINPOSY") let g:CREAM_WINPOSY_{myos} = g:CREAM_WINPOSY unlet g:CREAM_WINPOSY endif if exists("g:CREAM_FONT") let g:CREAM_FONT_{myos} = g:CREAM_FONT unlet g:CREAM_FONT endif " v.16 " ---- " convert var types (string to num) and initialize to 0 " type(), 0 if Number, 1 if String if exists("g:CREAM_WRAP") let g:CREAM_WRAP = g:CREAM_WRAP + 0 " change off state from -1 to 0 if g:CREAM_WRAP == -1 let g:CREAM_WRAP = 0 endif endif if exists("g:CREAM_AUTOWRAP") let g:CREAM_AUTOWRAP = g:CREAM_AUTOWRAP + 0 " change off state from -1 to 0 if g:CREAM_AUTOWRAP == -1 let g:CREAM_AUTOWRAP = 0 endif endif if exists("g:CREAM_AUTOWRAP_WIDTH") let g:CREAM_AUTOWRAP_WIDTH = g:CREAM_AUTOWRAP_WIDTH + 0 endif if exists("g:CREAM_TABSTOP") if type(g:CREAM_TABSTOP) == 1 " change to number let g:CREAM_TABSTOP = g:CREAM_TABSTOP + 0 endif endif if exists("g:CREAM_AUTOINDENT") let g:CREAM_AUTOINDENT = g:CREAM_AUTOINDENT + 0 " change off state from -1 to 0 if g:CREAM_AUTOINDENT == -1 let g:CREAM_AUTOINDENT = 0 endif endif if exists("g:CREAM_LINENUMBERS") let g:CREAM_LINENUMBERS = g:CREAM_LINENUMBERS + 0 endif if exists("g:LIST") let g:LIST = g:LIST + 0 endif if exists("g:CREAM_TOOLBAR") let g:CREAM_TOOLBAR = g:CREAM_TOOLBAR + 0 endif if exists("g:CREAM_EXPERTMODE") if type(g:CREAM_EXPERTMODE) == 1 " change state from "on-off" to "1-0" if g:CREAM_EXPERTMODE == "on" let g:CREAM_EXPERTMODE = 1 elseif g:CREAM_EXPERTMODE == "off" let g:CREAM_EXPERTMODE = 0 endif endif let g:CREAM_EXPERTMODE = g:CREAM_EXPERTMODE + 0 endif if exists("g:CREAM_SPELL_MULTIDICT") let g:CREAM_SPELL_MULTIDICT = g:CREAM_SPELL_MULTIDICT + 0 endif if exists("g:CREAM_SINGLESERVER") let g:CREAM_SINGLESERVER = g:CREAM_SINGLESERVER + 0 endif if exists("g:CREAM_SEARCH_HIGHLIGHT") let g:CREAM_SEARCH_HIGHLIGHT = g:CREAM_SEARCH_HIGHLIGHT + 0 endif " find if exists("g:CREAM_FCASE") let g:CREAM_FCASE = g:CREAM_FCASE + 0 " fix -1 state (make 0) if g:CREAM_FCASE == -1 let g:CREAM_FCASE = 0 endif endif if exists("g:CREAM_FREGEXP") let g:CREAM_FREGEXP = g:CREAM_FREGEXP + 0 " fix -1 state (make 0) if g:CREAM_FREGEXP == -1 let g:CREAM_FREGEXP = 0 endif endif " replace if exists("g:CREAM_RCASE") let g:CREAM_RCASE = g:CREAM_RCASE + 0 " fix -1 state (make 0) if g:CREAM_RCASE == -1 let g:CREAM_RCASE = 0 endif endif if exists("g:CREAM_RREGEXP") let g:CREAM_RREGEXP = g:CREAM_RREGEXP + 0 " fix -1 state (make 0) if g:CREAM_RREGEXP == -1 let g:CREAM_RREGEXP = 0 endif endif if exists("g:CREAM_RONEBYONE") let g:CREAM_RONEBYONE = g:CREAM_RONEBYONE + 0 " fix -1 state (make 0) if g:CREAM_RONEBYONE == -1 let g:CREAM_RONEBYONE = 0 endif endif " replace multi-file if exists("g:CREAM_RMCASE") let g:CREAM_RMCASE = g:CREAM_RMCASE + 0 " fix -1 state (make 0) if g:CREAM_RMCASE == -1 let g:CREAM_RMCASE = 0 endif endif if exists("g:CREAM_RMREGEXP") let g:CREAM_RMREGEXP = g:CREAM_RMREGEXP + 0 " fix -1 state (make 0) if g:CREAM_RMREGEXP == -1 let g:CREAM_RMREGEXP = 0 endif endif "...................................................................... " Hmm... not sure how long these have been obsolete if exists("g:CREAM_HI_SEL") unlet g:CREAM_HI_SEL endif if exists("g:CREAM_SHIFTWIDTH") unlet g:CREAM_SHIFTWIDTH endif " v.18 " ---- " this never in production if exists("g:CREAM_POP") unlet g:CREAM_POP endif " v.21 " ---- " never utilized if exists("g:CREAM_TAGLIST") unlet g:CREAM_TAGLIST endif " v.22 " ---- if exists("g:CREAM_FONT_COLUMNS") let myos = Cream_getoscode() let g:CREAM_FONT_COLUMNS_{myos} = g:CREAM_FONT_COLUMNS unlet g:CREAM_FONT_COLUMNS endif " array style/structure changes for addon mappings let i = 0 while i < 8 " if first item exists and is a string if exists("g:CREAM_ADDON_MAPS{i}") \ && type(g:CREAM_ADDON_MAPS{i}) == 1 " set new globals to old values let g:CREAM_ADDON_MAPS{i + 1}_{1} = MvElementAt(g:CREAM_ADDON_MAPS{i}, "\t", 0) let g:CREAM_ADDON_MAPS{i + 1}_{2} = MvElementAt(g:CREAM_ADDON_MAPS{i}, "\t", 1) let g:CREAM_ADDON_MAPS{i + 1}_{3} = MvElementAt(g:CREAM_ADDON_MAPS{i}, "\t", 2) " remove old globals "if i != 0 unlet g:CREAM_ADDON_MAPS{i} "else " " trick to get past init filter at " " Cream_addon_maps_init() so we get a count there " let g:CREAM_ADDON_MAPS{i} = -1 "endif else break endif let i = i + 1 endwhile " don't do this again let g:CREAM_VARFIX_022 = 1 endif if !exists("g:CREAM_VARFIX_029") " v.29 " ---- if exists("g:CREAM_AUTOWRAP_WIDTH") let g:CREAM_AUTOWRAP_WIDTH = g:CREAM_AUTOWRAP_WIDTH + 0 endif " don't do this again let g:CREAM_VARFIX_029 = 1 endif if !exists("g:CREAM_VARFIX_031") " v.31 " ---- " fix spelling dictionary dialect name changes if exists("g:CREAM_SPELL_LANG") let g:CREAM_SPELL_LANG = substitute(g:CREAM_SPELL_LANG, ',us', ',US', 'g') let g:CREAM_SPELL_LANG = substitute(g:CREAM_SPELL_LANG, ',ca', ',CA', 'g') let g:CREAM_SPELL_LANG = substitute(g:CREAM_SPELL_LANG, ',br', ',GB', 'g') endif " don't do this again let g:CREAM_VARFIX_031 = 1 endif " v.34 " ---- " type fix if exists("g:CREAM_TOOLBAR") && g:CREAM_TOOLBAR == "1" let g:CREAM_TOOLBAR = 1 endif endfunction " Buffer Enter fix {{{1 " fix normal mode hang on buffer enter (fixed in patch 6.0.254) "*** Broken *** function! Cream_bufenter_fix() if version <= 600 execute "normal \" endif endfunction " New {{{1 function! Cream_file_new() " opens new buffer in current window " if already in new, stop if Cream_buffer_isnewunmod() == 1 return endif " window management (prohibit from a special) if Cream_buffer_isspecial() == 1 call Cream_TryAnotherWindow() " if already in new, stop if Cream_buffer_isnewunmod() == 1 return endif endif " why would we need to confirm this? "confirm enew if v:version >= 700 \ && exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1 tabnew else enew endif " not needed, handled by BufNew autocmd call "" refresh buffer menu "call BMShow() endfunction " Open/Edit {{{1 function! Cream_file_open(...) " open file using dialog " * optional argument is file to be opened (without dialog) " * disallow opening in Calendar window " * disallow opening in Opsplorer window " window management (not from a special) if Cream_buffer_isspecial(bufnr("%")) call Cream_TryAnotherWindow() endif " if argument passed if a:0 == 0 " open dialog if exists("g:CREAM_CWD") let mydir = g:CREAM_CWD else "" TODO: did Vim behavior change? (empty works pre-7) "if v:version >= 700 " let mydir = getcwd() "else " let mydir = "" "endif "if Cream_has("ms") " let mydir = "" "else " if exists("b:cream_pathfilename") " let mydir = fnamemodify(expand(b:cream_pathfilename), ":p:h") . '/' " else " let mydir = "" " endif "endif " we've fixed automatic directory changing elsewhere, this " should always open to the cwd. let mydir = getcwd() endif ""*** DEBUG: "let n = confirm( " \ "DEBUG:\n" . " \ " mydir = " . mydir . "\n" . " \ "\n", "&Ok\n&Cancel", 1, "Info") "if n != 1 " return "endif ""*** let myfile = browse(0, "Select file", mydir, "") " To open file in path of current buffer "let myfile = browse(0, "Select file", fnamemodify(bufname("%"), ":p:h"), "") else let myfile = a:1 endif " ignore Cancel return if myfile == "" return endif " make sure we can edit! if filewritable(myfile) == 2 call confirm( \ "Can not edit a directory!\n" . \ "\n", "&Ok", 1, "Info") return elseif filereadable(myfile) == 0 let n = confirm( \ "File \"" . myfile . "\"\n" . \ "does not exist, create it?\n" . \ "\n", "&Ok\n&Cancel", 1, "Info") if n != 1 return endif elseif filewritable(myfile) == 0 let n = confirm( \ "Warning!\n\n" . \ "File is not writable (read-only, permissions, etc.). Open anyway?\n" . \ "\n", "&Ok\n&Cancel", 1, "Warning") if n != 1 return endif endif " hook for user functionality if exists("*Cream_hook_open") let fname = Cream_path_fullsystem(myfile) let test = Cream_hook_open(fname) if test == -1 " stop return -1 endif endif " escape spaces let myfile = escape(myfile, ' ') " if using tabs if v:version >= 700 \ && exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1 " if new-unmod if Cream_buffer_isnewunmod() " open in current window execute "edit " . myfile else " new tab execute "tabedit " . myfile endif else " open in current window execute "edit " . myfile endif " refresh syntax highlighting call Cream_filetype() endfunction function! Cream_file_open_readonly(...) " similar to open() except file is made readonly " window management (not from a special) if Cream_buffer_isspecial(bufnr("%")) call Cream_TryAnotherWindow() endif " if argument passed if a:0 == 0 " open dialog let myfile = browse(0, "Select file", "", '') else let myfile = a:1 endif " ignore Cancel return if myfile == "" return endif " make sure we can edit! if filewritable(myfile) == 2 call confirm( \ "Can not edit a directory!\n" . \ "\n", "&Ok", 1, "Info") return endif if filereadable(myfile) == 0 call confirm( \ "Error: File does not exist!\n" . \ "\n", "&Ok", 1, "Error") return endif " escape spaces let myfile = escape(myfile, ' ') " open in current window if v:version >= 700 \ && exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1 " if new-unmod if Cream_buffer_isnewunmod() " open in current window execute "view " . myfile else " new tab execute "tab view " . myfile endif else execute "view " . myfile endif " refresh syntax highlighting call Cream_filetype() endfunction function! Cream_session_new() " start new session (and over-ride single server mode temporarily) " TODO: OBSOLETE, we no longer permit multiple sessions. (2007-05-16) " solve buffer not found errors from second session startup let g:CREAM_LAST_BUFFER = "" " write the viminfo so it's remembered! wviminfo! " don't use if not initialized if !exists("g:CREAM_SINGLESERVER") if Cream_has("ms") execute 'silent! !start gvim --servername "CREAM" -U NONE -u "\$VIMRUNTIME/cream/creamrc"' else execute 'silent! !gvim --servername "CREAM" -U NONE -u "\$VIMRUNTIME/cream/creamrc"' endif else " TODO: There's a complex bug here: the new session will not " have the same settings as this session. But the last session " to close will determine the preferences of future sessions. " This will result in: " o Omissions of Recent File menu entries " o Settings toggled " " Solutions: " o Warn the user? " o => On close, message any existing sessions with the new " info. (talk about complicated) " o Immediately write setting changes back to viminfo? " * Any session beginning with a name other than "CREAM" " should register with the rest? " Set up viminfo for new session. " " so new session doesn't re-merge (see Cream_singleserver()) let g:CREAM_SERVER_OVERRIDE = 1 " disable swapfiles set noswapfile " disable window pos (so not over current session) call Cream_screen_unlet() " forget current buffers if !exists("g:CREAM_LAST_BUFFER_FORGET") || g:CREAM_LAST_BUFFER_FORGET == 1 let lastbuf = 1 let g:CREAM_LAST_BUFFER_FORGET = 1 if exists("g:CREAM_LAST_BUFFER") unlet g:CREAM_LAST_BUFFER endif set viminfo-=% endif " write viminfo wviminfo! " restore last buffer remember state if exists("lastbuf") let g:CREAM_LAST_BUFFER_FORGET = 1 let &viminfo = &viminfo . ",%" "let g:CREAM_LAST_BUFFER = 1 endif " restore GUI set call Cream_screen_get() " remove global shield unlet g:CREAM_SERVER_OVERRIDE " add four random digits to server name so unique let myserver = "CREAM" . strpart(localtime(), 6) " open the new session if Cream_has("ms") execute 'silent! !start gvim --servername "' . myserver . '" -U NONE -u "\$VIMRUNTIME/cream/creamrc"' else execute 'silent! !gvim --servername "' . myserver . '" -U NONE -u "\$VIMRUNTIME/cream/creamrc"' endif endif endfunction function! Cream_cwd() " maintain current working directory (called via autocmd) if exists("g:CREAM_CWD") execute 'cd "' . g:CREAM_CWD . '"' else if exists("b:cream_pathfilename") " need quotes on unix for unescaped filenames (escaping is harder) if Cream_has("ms") execute 'cd ' . \ fnamemodify(expand(b:cream_pathfilename), ":p:h") else execute 'cd ' . \ escape(fnamemodify(expand(b:cream_pathfilename), ":p:h"), ' \') endif endif endif endfunction " File open under cursor {{{1 function! Cream_file_open_undercursor(mode) " open the file under the cursor. " * guess where it is if not full path " * future options to open related (.h from .c, etc.) " get full name " with selection, we won't guess (much) if a:mode == "v" normal gv normal "xy " trim off accidental leading whitespace let myfile = Cream_trim(@x) " try as complete path first if filereadable(myfile) " try file in existing path elseif filereadable(expand("%:p:h") . "/" . myfile) let myfile = expand("%:p:h") . "/" . myfile " further guesses here... endif " use word under cursor (if file doesn't exist, we might try " a little harder in the area, but not much--tell user we can't " find spaces or odd characters.) elseif a:mode == "i" " try word under cursor let myfile = expand("") if filereadable(myfile) " try harder elseif filereadable(expand("")) let myfile = expand("") " try word under cursor, with path elseif filereadable(expand("%:p:h") . "/" . expand("")) let myfile = expand("%:p:h") . "/" . expand("") " try harder, with path elseif filereadable(expand("%:p:h") . "/" . expand("")) let myfile = expand("%:p:h") . "/" . expand("") " now try *really* hard else " add period as valid part of cword (already part of cWORD) set iskeyword+=. let myfile = expand("") if filereadable(myfile) " good, continue " try word with path elseif filereadable(expand("%:p:h") . "/" . expand("")) let myfile = expand("%:p:h") . "/" . expand("") endif set iskeyword-=. endif endif " validate (return if file unreadable) if filereadable(myfile) == 0 if a:mode == "v" call confirm( \ "Unable to find a file to open matching the selection.\n" . \ "\n", "&Ok", 1, "Info") normal gv elseif a:mode == "i" call confirm( \ "Unable to find a file to open matching the word under the cursor.\n" . \ "\n", "&Ok", 1, "Info") endif return endif " open validated file call Cream_file_open(myfile) " refresh buffer menu call BMShow() endfunction " Saving {{{1 function! Cream_save() " save no matter what " if new file if expand("%") == "" if has("browse") browse confirm write else confirm write endif else confirm write endif " refresh buffer menu call BMShow() endfunction function! Cream_saveas(...) " general SaveAs function " o Unloads original file without saving " o Optional argument {...} can be path-filename to save to without " prompting user for path-filename. " " IMPORTANT: " If saveas is successful, new buffer name will have old buffer number " while old buffer name will have a new buffer number. " remember original buffer let origbufnr = bufnr("%") let origbufname = fnamemodify(bufname(origbufnr), ":p") " if passed arg and head of it exists if a:0 == 1 && Cream_pathexists(fnamemodify(a:1, ":p:h")) " save as new file *name* execute "confirm saveas! " . a:1 else " prompt user for path/filename if has("browse") browse confirm saveas else confirm saveas endif endif " get original buffer's new number let origbufnr_new = bufnr(origbufname) " saveas failed? (old file's buffer number changed or doesn't exist) if origbufnr == origbufnr_new \ || origbufnr_new == -1 " nope, saveas failed, go no further return endif " remove original file (*now with new number*) *without saving* call Cream_bwipeout(origbufnr_new) " make new file name current (*has old buffer number*) execute "buffer " . origbufnr " refresh buf name if exists("b:cream_pathfilename") unlet b:cream_pathfilename endif " refresh highlighting if exists("g:CREAM_SYNTAX") && g:CREAM_SYNTAX == 1 syntax enable endif call Cream_filetype() " refresh spell check highlighting if on if exists("b:cream_spell") && b:cream_spell == "1" call Cream_spell() endif " refresh tab labels (must follow syntax update) if v:version >= 700 \ && exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1 call Cream_tabpages_refresh() endif " refresh buffer menu and MRU call BMShow() " BufEnter autocmd doesn't pick up call MRUAddToList() endfunction function! Cream_saveall() " function so buffer menu can be refreshed " we silence command line warning, so warn with dialog if Cream_NumberOfBuffers("newmod") > 0 call confirm( \ "Modified buffers exist that are not yet saved as files. " . \ "SaveAs in \"[untitled]\" windows to keep your work." . \ "\n", "&Ok", 1, "Warning") endif silent! execute "wall" call BMShow() endfunction function! Cream_update(mode) " save only when changes " * we don't use the :update command because it can't prompt to SaveAs " an un-named file if &modified == 1 call Cream_save() endif if a:mode == "v" " reselect normal gv endif " refresh buffer menu call BMShow() endfunction function! Cream_save_confirm() " confirm save any modified current document " " Returns: " -1 if user cancelled in some fashion (meaning "STOP!") " 1 if doc saved, chose not to save, or doc not modified " save if modified if &modified == 1 " unnamed file if Cream_buffer_isnewmod() == 1 "*** Developer: We want to track Vim dialogs against Cream's if exists("g:cream_dev") let mychoice = confirm("Cream: Save changes as a new document?", "&Yes\n&No\n&Cancel", 1) else let mychoice = confirm("Save changes as a new document?", "&Yes\n&No\n&Cancel", 1) endif "*** else "*** Developer: We want to track Vim dialogs against Cream's let filename = fnamemodify(expand("%"), ":p") if Cream_has("ms") let filename = substitute(filename, '/', '\', 'g') endif if exists("g:cream_dev") let mychoice = confirm("Cream: Save changes to\n \"" . filename . "\" ?\n", "&Yes\n&No\n&Cancel", 1) else let mychoice = confirm("Save changes to\n \"" . filename . "\" ?\n", "&Yes\n&No\n&Cancel", 1) endif "*** endif " yes, save if mychoice == 1 " unnamed file if Cream_buffer_isnewmod() == 1 if has("browse") " get path-filename via dialog "let n = browse("", "", getcwd(), "") "" if nothing was returned (error or cancel) "if n == "" " return -1 "endif browse saveas " if still not saved, error if Cream_buffer_isnewmod() == 1 return -1 endif else call confirm( \ "Please :saveas before closing." . \ "\n", "&Ok", 1, "Warning") return -1 endif else write endif " no: don't save changes! elseif mychoice == 2 " nothing " cancel or error: do nothing else return -1 endif " refresh buffer menu call BMShow() endif return 1 endfunction " Close {{{1 function! Cream_close() " * Provide options to close unsaved buffers " * Confirm unnamed files " * Drop into other open files rather than the unlisted "[No File]" " confirm the save let n = Cream_save_confirm() " required save cancelled or error if n == -1 return 0 endif " hook for user functionality if exists("*Cream_hook_close") let fname = Cream_path_fullsystem(expand("%")) let test = Cream_hook_close(fname) if test == -1 " stop return -1 endif endif " window management--if help, removal *all* help buffers, even " hidden ones if Cream_buffer_ishelp() call Cream_help_hidden_remove() endif " wipeout buffer (delete) call Cream_bwipeout() " refresh buffer menu call BMShow() return 1 endfunction function! Cream_close_all() let buffercount = Cream_NumberOfBuffers("all") let i = 0 while i < buffercount let return = Cream_close() if return != 1 " user quit at one file, stop closing call BMShow() return 0 endif let i = i + 1 endwhile " refresh buffer menu call BMShow() return 1 endfunction " Exit {{{1 function! Cream_exit() " * Remember last current buffer for restoration " * Existing buffers are retained (default nature of Vim) " * Quit Vim, confirm unsaved buffers with changes " only do once! (This function called directly by menu, but also " by autocmd in the case of a window manager exit, etc. We just " want to do it one time in the first case.) if exists("g:Cream_exit") return endif " remember something that's already showing (not just open) call Cream_TryAnotherWindow() " get current buffer let mybufnr = bufnr("%") " confirm save all modifieds; upon cancel of the confirm, exit " doesn't happen. (Was responsible for not-able-to-exit bug where " cancel aborts the close all, but check variable is still set!) let i = 1 while i <= bufnr('$') if getbufvar(i, "&modified") == 1 \&& Cream_buffer_isspecial(i) == 0 execute "buffer " . i let valid = Cream_save_confirm() if valid == -1 " save cancelled or error--go back to original buffer execute "buffer " . mybufnr return endif endif let i = i + 1 endwhile " avoid modified new (already elected not to save it) call Cream_TryAnotherWindow("nonewmod") " get current buffer filename (if not special, newmod or new unmod) " Note: We do this post save, to avoid saving modified un-named if Cream_buffer_isspecial(bufnr("%")) != 1 \&& Cream_buffer_isnewunmod(bufnr("%")) != 1 \&& Cream_buffer_isnewmod(bufnr("%")) != 1 let g:CREAM_LAST_BUFFER = fnamemodify(bufname("%"), ":p") else if exists("g:CREAM_LAST_BUFFER") unlet g:CREAM_LAST_BUFFER endif endif " get screen position and size if has("gui_running") call Cream_screen_get() endif " manage MRU menu call MRUVimLeavePre() " close calendar and remember state (do after confirmations so it " can be maintained if there are cancel/problems above.) call Cream_calendar_exit() " don't save buffer state based on preference if exists("g:CREAM_LAST_BUFFER_FORGET") && g:CREAM_LAST_BUFFER_FORGET == 1 " close all buffers let myreturn = Cream_close_all() if myreturn != 1 " user quit somewhere during close process, stop return 0 endif if exists("g:CREAM_LAST_BUFFER") unlet g:CREAM_LAST_BUFFER endif endif " penultimate: post-everything but the preserving viminfo write let g:Cream_exit = 1 " yes, we're really doing this (can't confirm--if "no" chosen " above, would see it twice) " * must be last to correctly write viminfo qall! endfunction function! Cream_save_exit() " save all files and exit silent! call Cream_saveall() silent! call Cream_exit() endfunction " 1}}} " Editing {{{1 " Cut/Copy/Paste {{{1 function! Cream_cut(mode) " cut selection to universal clipboard ("+) if a:mode == "v" normal gv normal "+x endif endfunction function! Cream_copy(mode) " copy selection to universal clipboard ("+) if a:mode == "v" normal gv normal "+y normal gv endif endfunction ""---------------------------------------------------------------------- "" Source: mswin.vim "" "" Pasting blockwise and linewise selections is not possible in Insert "" and Visual mode without the +virtualedit feature. They are pasted as "" if they were characterwise instead. "if has("virtualedit") " nnoremap Paste :call Paste() " function! Paste() " let myve = &virtualedit " set virtualedit=all " normal `^"+gPi " let &virtualedit = myve " endfunction " imap xPastegi " vmap "-cPaste "else " nnoremap Paste "=@+.'xy'gPFx"_2x " imap xPaste"_s " vmap "-cgixPaste"_x "endif "vmap "imap ""---------------------------------------------------------------------- function! Cream_paste(mode) " paste selection from universal clipboard ("+) if a:mode == "v" normal gv normal "+P " correct position normal l " don't re-select, sizes may differ elseif a:mode == "i" " fix win32 paste from app call setreg('+', @+, 'c') let myvirtualedit = &virtualedit set virtualedit=all normal `^"+gP let &virtualedit = myvirtualedit endif endfunction " Undo and Redo {{{1 function! Cream_undo(mode) undo if a:mode == "v" normal gv endif endfunction function! Cream_redo(mode) redo if a:mode == "v" normal gv endif endfunction " Delete {{{1 function! Cream_delete(mode) " for pop up menu item if a:mode == "v" normal gv normal x endif endfunction " Indent/Unindent {{{1 function! Cream_indent(mode) if a:mode == "v" normal gv normal > normal gv endif endfunction function! Cream_unindent(mode) if a:mode == "v" normal gv normal < normal gv elseif a:mode == "i" let mypos = Cream_pos() " select line and unindent normal V normal < execute mypos " now adjust for shift let i = 0 let myline = line('.') while i < &tabstop normal h " oops, go back to current line if we jumped up if line('.') < myline normal l endif let i = i + 1 endwhile " select one char so " * user can see a selection is in place " * if tab is used immediately following this routine believes " the whole line is selected rather than inserting a single " tab normal vl if mode() == "v" " change to select mode execute "normal \" endif endif endfunction " Word Count {{{1 function! Cream_count_word(mode) if a:mode == "i" " remember position let mypos = Cream_pos() let myword = expand('') elseif a:mode == "v" " use selection normal gv normal "xy let myword = @x else let myword = "" endif let pattern = inputdialog("Enter a word to count within the \ncurrent document... (case sensitive)", myword) if pattern != '' " test " search if search(pattern, 'w') > 0 let @/ = pattern " capture states let mymodified = &modified let myreport = &report " report all changes set report=0 " capture output of substitution redir @x "execute 'g/' . pattern . '/s//&/g' execute '%substitute/\<' . pattern . '\>/' . pattern . '/geI' "execute '%substitute/' . pattern . '/' . pattern . '/geI' redir END " restore states let &modified = mymodified let &report = myreport " remove initial leading linefeed let str = @x let str = strpart(str, 1) " the initial search above tells us it will be found "" parse output "if match(str, "Pattern") > 0 " " word doesn't exist " let cnt = 0 "else let thepos = match(str, ' ') let cnt = strpart(str, 0, thepos) "let cnt = matchstr(str, '^\d\+') " if highlighting on, match it to show on the screen if g:CREAM_SEARCH_HIGHLIGHT == 1 execute '/\<' . pattern . '\>' "execute '/' . pattern . '' endif "endif " if highlighting not on, explain benefit to user if g:CREAM_SEARCH_HIGHLIGHT == 0 call confirm( \ "\"" . pattern . "\" occurs " . cnt . " times." . "\n" . \ "\n" . \ "(Turn on Settings...Highlight Find to see occurances.)\n" . \ "\n", "&Ok", 1, "Info") else call confirm( \ "\"" . pattern . "\" occurs " . cnt . " times." . "\n" . \ "\n", "&Ok", 1, "Info") redraw! endif else call confirm( \ "\"" . pattern . "\" not found.\n" . \ "\n", "&Ok", 1, "Info") endif endif if a:mode == "i" " recall position execute mypos elseif a:mode == "v" normal gv endif endfunction function! Cream_count_words(mode) if a:mode == "i" " remember position let mypos = Cream_pos() endif " TODO: if a:mode == "v", just count in selection if a:mode == "v" normal gv let cnttype = "selection" else let cnttype = "file" endif " (approach by Piet Delport) execute "silent normal! g\" if a:mode == "v" let lines = matchstr(v:statusmsg, '\zs\d\+\ze of \d\+ Line') + 0 let words = matchstr(v:statusmsg, '\zs\d\+\ze of \d\+ Word') + 0 let chars = matchstr(v:statusmsg, '\zs\d\+\ze of \d\+ Byte') + 0 else let lines = matchstr(v:statusmsg, 'Line \d\+ of \zs\d\+') + 0 let words = matchstr(v:statusmsg, 'Word \d\+ of \zs\d\+') + 0 let chars = matchstr(v:statusmsg, 'Byte \d\+ of \zs\d\+') + 0 endif " subtract NL/CRs if &fileformat == "dos" let chars = chars - (lines * 2) else let chars = chars - lines endif " word length comment if words > (chars / 5) let wordlencomment = " (These words are shorter than average.)\n" elseif words < (chars / 5) let wordlencomment = " (These words are longer than average.)\n" else let wordlencomment = "" endif " strings if words == 0 let strpages = "" elseif words < 250 let strpages = "Less than one page\n" elseif words == 250 let strpages = "Exactly one typical 250-word page\n" elseif words > 250 && words < 500 let strpages = "Between one and two typical 250-word pages\n" else let avgwordm = Cream_format_number_commas(((chars / 5) / 250)) let avgwordt = Cream_format_number_commas(((chars / 5) / 400)) let strpages = avgwordm . " average 250-word manuscript pages\n" . \ avgwordt . " average 400-word technical pages\n" endif let str = Cream_format_number_commas(words) . " actual words\n" . \ Cream_format_number_commas((chars / 5)) . " average 5-letter words\n" . \ wordlencomment . \ "\n" . \ Cream_format_number_commas(chars) . " characters including spaces and tabs\n" . \ "\n" . \ strpages " display results let n = confirm( \ "This " . cnttype . " has:" . "\n" . \ "\n" . \ str . \ "\n", "Copy and Close\n&Close", 2, "Info") if n == 1 let @+ = str endif if a:mode == "i" " recall position execute mypos elseif a:mode == "v" normal gv endif endfunction " 1}}} " Formatting and text handling " String Handling {{{1 function! Cream_get_char_undercursor() " return character under cursor silent! redir @c silent! ascii silent! redir END return @c[2] endfunction function! Cream_str_pad(str, len) " Format {str} with preceeding spaces to length {len}. let str = a:str while strlen(str) < a:len let str = " " . str endwhile return str endfunction " Formatting {{{1 function! Cream_whitespace_trim_leading(mode, ...) " default is current document " (optional) argument, returns argument trimmed if a:0 > 0 return substitute(a:1, '\(^\|\n\)\zs\s\+', '', 'g') elseif a:mode == "v" normal gv normal "xy let @x = substitute(@x, '\(^\|\n\)\zs\s\+', '', 'g') " stupid hack to fix Vim if virtcol('.') == 1 normal h endif normal gv normal "xp elseif a:mode == "i" let mypos = Cream_pos() execute ':%substitute/^\s\+//ge' execute mypos endif endfunction function! Cream_whitespace_trim_trailing(mode, ...) " default is current document " (optional) argument, returns argument trimmed if a:0 > 0 return substitute(a:1, '\s\+\ze\($\|\n\)', '', 'g') elseif a:mode == "v" normal gv normal "xy let @x = substitute(@x, '\s\+\ze\($\|\n\)', '', 'g') " stupid hack to fix Vim if virtcol('.') == 1 normal h endif normal gv normal "xp elseif a:mode == "i" let mypos = Cream_pos() " test if sig line exists execute "0" if search('^-- $') > 0 let flag = 1 endif execute ':%substitute/\s\+$//ge' if exists("flag") " prompt user if should recover let n = confirm( \ "Email signature seperator lines (\"-- \") were detected in\n" . \ "this file. Would you like to recover their trailing space?" . \ "\n", "&Yes\n&No", 1, "Warning") if n == 1 execute ':%substitute/^--$/-- /ge' endif endif execute mypos endif endfunction function! Cream_whitespace_trim(mode, ...) " trim both leading and trailing whitespace " default is current document " (optional) argument, returns argument trimmed if a:0 > 0 let tmp = a:1 let tmp = Cream_whitespace_trim_leading("i", tmp) let tmp = Cream_whitespace_trim_trailing("i", tmp) return tmp elseif a:mode == "v" normal gv normal "xy let @x = Cream_whitespace_trim_leading("i", @x) let @x = Cream_whitespace_trim_trailing("i", @x) " stupid hack to fix Vim if virtcol('.') == 1 normal h endif normal gv normal "xp elseif a:mode == "i" call Cream_whitespace_trim_leading("i") call Cream_whitespace_trim_trailing("i") endif endfunction function! Cream_emptyline_collapse() " collapse all empty lines to 1 let mypos = Cream_pos() "silent! execute ':%substitute/\n\s*\n*$/\r/ge' "silent! execute ':%substitute/\n*$/\r/ge' silent! execute ':%substitute/\n\s\+$/\r/ge' silent! execute ':%substitute/\n\+$/\r/ge' execute mypos endfunction function! Cream_emptyline_delete() " deletes all empty lines let mypos = Cream_pos() silent! execute ':%substitute/\n\s*\n*$//ge' execute mypos endfunction function! Cream_joinlines(mode) " join selected lines if a:mode != "v" return endif normal gv let n = confirm( \ "Maintain spaces between each line?\n" . \ "\n", "&Yes\n&No\n&Cancel", 2, "Info") if n == 1 " preserve spaces normal J elseif n == 2 " don't preserve spaces normal gJ else return endif endfunction function! Cream_vimscript_compress() " Compress a Vim script by removing comments and leading whitespace. " verify vim filetype if &filetype != "vim" call confirm( \ "This isn't a Vim file. Quitting...\n" . \ "\n", "&Ok", 1, "Info") return endif " confirm destruction let n = confirm( \ "Strip comments and leading/trailing whitespace?\n" . \ "\n", "&Ok", 1, "Info") if n != 1 return endif " strip whitespace call Cream_whitespace_trim("i") " delete lines beginning with a comment silent %substitute/^".*$//ge " delete empty lines call Cream_emptyline_delete() endfunction " File Format {{{1 function! Cream_fileformat(...) " set &fileformat based on argument: " dos " unix " mac " get current file format let ffold = &fileformat " bypass dialog to get desired fileformat if argument passed if a:0 == 1 let ffnew = a:1 " don't mod file if already correct if ffnew ==? ffold return endif else " set default choice if ffold == "unix" let mychoice = 1 elseif ffold == "dos" let mychoice = 2 elseif ffold == "mac" let mychoice = 3 else let mychoice = 4 endif " change to new let n = confirm( \"Convert file from current " . toupper(ffold) . " format to...\n", \"&Unix\n&DOS/Windows\n&Apple\n&Cancel", mychoice, "Question") if n == 1 let ffnew = "unix" elseif n == 2 let ffnew = "dos" elseif n == 3 let ffnew = "mac" else return endif endif " change current buffer's fileformat based on selection if ffnew ==? "unix" set fileformat=unix elseif ffnew ==? "dos" set fileformat=dos execute ":%substitute/" . nr2char(13) . "$//ge" elseif ffnew ==? "mac" set fileformat=mac endif endfunction " Encoding {{{1 " Cream_filetypes_list() function! Cream_convert_encoding(encoding) " convert the current document's encoding to that passed " Example: :call ConvertEncoding("latin1") ""................................................................. "" method 1 "" select all "normal gg "normal gH "execute "normal \" "normal G "" cut "normal "xx "" convert "let @x = iconv(@x, &encoding, a:encoding) "" change document's encoding (must follow above) "execute "set encoding=" . a:encoding "" paste back the conversion "normal "xP "................................................................. " method 2 execute "set fileencoding=" . a:encoding endfunction function! Cream_fileencoding_set(encoding) " see :help encoding-values execute "set encoding=" . a:encoding execute "set fileencoding=" . a:encoding " reload keymaps call Cream_source($CREAM . "cream-keys.vim") " reload menus call Cream_menus() call MRURefreshMenu() call BMShow() endfunction " Tabs (&expandtab) {{{1 function! Cream_expandtab_init() if exists("g:CREAM_EXPANDTAB") && g:CREAM_EXPANDTAB == 1 set expandtab else set noexpandtab let g:CREAM_EXPANDTAB = 0 endif endfunction function! Cream_expandtab_toggle(mode) if exists("g:CREAM_EXPANDTAB") if g:CREAM_EXPANDTAB == 1 set noexpandtab let g:CREAM_EXPANDTAB = 0 else set expandtab let g:CREAM_EXPANDTAB = 1 endif else " error endif call Cream_menu_settings_expandtab() if a:mode == "v" normal gv endif endfunction " Retab {{{1 function! Cream_retab() " replace all existing tabs with spaces according to current tabstop settings " save expandtab let myexpandtab = &expandtab " turn on set expandtab silent! retab " restore let &expandtab = myexpandtab endfunction " 1}}} " Motion, selection " Positioning {{{1 function! Cream_pos(...) " return current position in the form of an executable command " Origins: Benji Fisher's foo.vim, available at " http://vim.sourceforge.net "let mymark = "normal " . line(".") . "G" . virtcol(".") . "|" "execute mymark "return mymark " current pos let curpos = line(".") . "G" . virtcol(".") . "|" " mark statement let mymark = "normal " " go to screen top normal H let mymark = mymark . line(".") . "G" " go to screen bottom normal L let mymark = mymark . line(".") . "G" " go back to curpos execute "normal " . curpos " cat top/bottom screen marks to curpos let mymark = mymark . curpos execute mymark return mymark endfunction " Motion {{{1 function! Cream_motion_doctop() normal gg0 " current line highlighting call Cream_highlight_currentline() endfunction function! Cream_motion_docbottom() normal G$ " current line highlighting call Cream_highlight_currentline() endfunction function! Cream_motion_windowtop() normal H " current line highlighting call Cream_highlight_currentline() endfunction function! Cream_motion_windowbottom() normal L " current line highlighting call Cream_highlight_currentline() endfunction function! Cream_motion_windowmiddle() normal M " current line highlighting call Cream_highlight_currentline() endfunction function! Cream_delete_v() " deletes selection (in Visual mode) normal gvd endfunction function! Cream_motion_home() " Original Concept: http://www.derwok.de/downloads/index.html " get current column let oldcol = col('.') " go to first non-white normal g^ " get current column, new let newcol = col('.') " if already were at first-non-white, toggle if (oldcol == newcol) " if we're on the first line, stop, otherwise toggle if (&wrap == 1) && (newcol > Cream_linewidth()) " stop else execute "normal gI\" let lastcol = col('.') " already were at first col? if (newcol == lastcol) " fix being stuck on second column if a one character line if (newcol == oldcol) " terminate, ensure at beginning normal i else " toggle back to first non-white normal g^ endif else " toggle to first col execute "normal gI\" endif endif endif endfunction function! Cream_linewidth() " calculate text width (not &columns, winwidth(0), col('$'), " virtcol('$') according to state of signs, fold columns, and line " numbers. let foldcolumn = &foldcolumn if Cream_ShowMarks_Exist() == 1 let signs = 2 else let signs = 0 endif if &number == 1 let number = 8 else let number = 0 endif return winwidth(0) - signs - foldcolumn - number endfunction function! Cream_map_end() " get current pos let oldcol = virtcol('.') " go to last screen column normal g$ " Hack: fix that doesn't allow ending up after last char " with wrap off (2004-04-23) if &wrap == 0 " if line is shorter than screen if virtcol('$') < Cream_linewidth() " fix position normal $ " if we were already at screen line end elseif oldcol >= virtcol('.') " move farther normal $ else " nothing, first g$ did what we wanted endif else " if already at screen end, go to line end if oldcol >= virtcol('.') normal $ endif endif endfunction function! Cream_up(mode) if a:mode == "i" normal gk elseif a:mode == "v" "...................................................................... " option 1 " don't reselect, we've already got one! normal gv " get positions let lin1 = line(".") let col1 = virtcol(".") let pos1 = Cream_pos() normal o let lin2 = line(".") let col2 = virtcol(".") let pos2 = Cream_pos() normal o " drop to normal mode execute "normal \\" " adjust only if multi-line if lin1 > lin2 execute pos2 elseif lin1 < lin2 execute pos1 elseif col1 > col2 execute pos2 elseif col2 > col1 execute pos1 endif "...................................................................... " option 2 endif " current line highlighting call Cream_highlight_currentline() endfunction function! Cream_down(mode) if a:mode == "i" normal gj elseif a:mode == "v" " don't reselect, we've already got one! normal gv " get positions let lin1 = line(".") let col1 = virtcol(".") let pos1 = Cream_pos() normal o let lin2 = line(".") let col2 = virtcol(".") let pos2 = Cream_pos() normal o " drop to normal mode execute "normal \\" " adjust only if multi-line if lin1 < lin2 execute pos2 elseif lin1 > lin2 execute pos1 elseif col1 > col2 execute pos1 elseif col2 > col1 execute pos2 endif endif " current line highlighting call Cream_highlight_currentline() endfunction function! Cream_scroll_down(...) " scroll screen up one line but maintain cursor position " if visual mode (argument "v") if a:0 != 0 if a:1 == "v" " reselect selection normal gv " move left one (bug fix) and scroll execute "normal \\" " re-select normal gv else call confirm( \ "Error: Invalid argument passed to Cream_scroll_down(). Quitting...\n" . \ "\n", "&Ok", 1, "Info") return endif " if insert mode else " scroll up, go down one execute "normal \\" endif " current line highlighting call Cream_highlight_currentline() endfunction function! Cream_scroll_up(...) "execute "normal \\" " scroll screen down one line but maintain cursor position " if visual mode (argument "v") if a:0 != 0 if a:1 == "v" " reselect selection normal gv " move left one (bug fix) and scroll execute "normal \\" " re-select normal gv else call confirm( \ "Error: Invalid argument passed to Cream_scroll_down(). Quitting...\n" . \ "\n", "&Ok", 1, "Info") return endif " if insert mode else " scroll up, go down one execute "normal \\" endif " current line highlighting call Cream_highlight_currentline() endfunction function! Cream_pageup() " PageUp -- ensure motion to top if in first page "" page only if we're already at the window edge "if winline() < 3 execute "normal \" "endif normal H " current line highlighting call Cream_highlight_currentline() endfunction function! Cream_pagedown() " PageUp -- ensure motion to top if in first page "" page only if we're already at the window edge "if winline() > winheight(0) - 3 execute "normal \" "endif normal L " current line highlighting call Cream_highlight_currentline() endfunction " Selection {{{1 function! Cream_select_all(...) " Notes: An optional argument "endvisual" can be passed to force the " function to end in visual mode and prevent the function from " returning to select mode. " important: drop existing selection if current normal i normal gg normal gH " change to visual mode execute "normal \" normal G " return to select if we weren't passed an argument or the " argument isn't "endvisual" if a:0 == 0 \|| a:0 > 1 && a:1 ==? "endvisual" " change to select mode execute "normal \" endif endfunction function! Cream_map_shift_home(mode) " toggles selection back and forth between first column and first " non-whitespace column " * Requires arguement "i" or "v" (for Insert or Visual mode) if a:mode == "i" normal v normal g^ " go to other end of selection normal o " while not at last insert position while col(".") < col("'^") " go right (usually only once) normal l endwhile " go back to front end of selection normal o " change to select mode execute "normal \" elseif a:mode == "v" " reselect normal gv " capture position let oldcol = col(".") " go to first screen line position normal g0 " get current column, new let newcol = col(".") " already were at first column if (oldcol == newcol) " back up to first char normal g^ endif endif endfunction function! Cream_map_shift_end() " get current column let oldcol = col(".") " go to last non-white normal v normal g$ " get current column, new let newcol = col(".") " already were at last non-white? if (oldcol == newcol) " go to first col normal $ let lastcol = col(".") " already were at last col? if (newcol == lastcol) " go back to last non-white normal g$ else " go to last col normal $ endif endif " we want select mode if still in visual so typing replaces if mode() == "v" execute "normal \" endif endfunction function! Cream_map_shift_up(mode) " accepts mode argument "i" or "v" if a:mode == "i" " this is a huge hack to remedy the fact that "normal vgk" omits " selection of the final char if beginning from the last pos of " a line, mostly because of the intro. normal v normal gk normal gj normal o normal gk " we want select mode if still in visual so typing replaces if mode() == "v" execute "normal \" endif elseif a:mode == "v" " reselect normal gv normal gk endif endfunction function! Cream_map_shift_down(mode) " accepts mode argument "i" or "v" if a:mode == "i" " same hack as Cream_map_shift_up() normal v normal gj normal gk normal o normal gj " we want select mode if still in visual so typing replaces if mode() == "v" execute "normal \" endif elseif a:mode == "v" normal gv normal gj endif endfunction function! Cream_map_shift_pageup(mode) " accepts mode argument "i" or "v" if a:mode == "i" normal vH elseif a:mode == "v" " reselect normal gv execute "normal \" endif endfunction function! Cream_map_shift_pagedown(mode) " accepts mode argument "i" or "v" if a:mode == "i" normal vL elseif a:mode == "v" " reselect normal gv execute "normal \" endif endfunction function! Cream_visual_swappos(direction) " from visual mode, go to end of selection specified " * arguments "up" and "dn" normal gv " get pos let myline = line('.') let mycol = col('.') " swap normal o " get pos, new let mylinenew = line('.') let mycolnew = col('.') if a:direction ==? "up" if myline > mylinenew elseif myline < mylinenew " swap back (original was less) normal o " equal else " check columns (selection only on one line) if mycol < mycolnew normal o endif endif elseif a:direction ==? "dn" if myline < mylinenew elseif myline > mylinenew " swap back (original was less) normal o " equal else " check columns (selection only on one line) if mycol > mycolnew normal o endif endif endif endfunction " Replace mode {{{1 function! Cream_replacemode() " used by key to replace tabs without moving positions " initialize if !exists("g:cream_replacemode") let g:cream_replacemode = 1 " toggle state else if g:cream_replacemode == 1 let g:cream_replacemode = 0 else let g:cream_replacemode = 1 endif endif " condition based on state if g:cream_replacemode == 1 " start replace mode if &modified == 1 return "x\gR\" else " need to compensate for the insert x pos stuff... return "x\gR\\:set nomodified\gR" endif else " end replace mode return "\i" endif endfunction "1}}} " Navigationy things " Tags {{{1 " Tag jumping function! Cream_tag_backward() " go to previous tag if !Cream_has("tagsfile") if !Cream_has("tags") call s:Cream_tag_warn() endif return endif if v:version >= 700 && exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1 silent! tab pop else silent! pop endif endfunction function! Cream_tag_forward() " go to next tag forward if !Cream_has("tagsfile") if !Cream_has("tags") call s:Cream_tag_warn() endif return endif if v:version >= 700 && exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1 silent! tab tag else silent! tag endif endfunction function! Cream_tag_goto() " go to tag under cursor if !Cream_has("tagsfile") if !Cream_has("tags") call s:Cream_tag_warn() endif return endif let mytag = expand("") if v:version >= 700 && exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1 execute "silent! tab tag " . mytag else execute "silent! tag " . mytag endif endfunction function! s:Cream_tag_warn() call confirm( \ "This feature requires a working installation of ctags.\n" . \ "Please see http://ctags.sf.net for more details. \n" . \ "\n", "&Ok", 1, "Info") endfunction function! Cream_tag_backclose() " close and go back if !Cream_has("tagsfile") && \ getbufvar("%", "&filetype") != "help" return endif " get current buffer let mybufno = bufnr("%") " delete other buffer--confirm if unsaved! if &modified == "1" " TODO: This area looks suspiciously duplicate of file " functions elsewhere... " unnamed file? if Cream_buffer_isnewunmod() == 1 let mychoice = confirm("Save changes as a new document?", "&Yes\n&No\n&Cancel", 1) else let mychoice = confirm("Save changes to \"" . expand("%:p") . "\"?", "&Yes\n&No\n&Cancel", 1) endif if mychoice == 1 " if an unnamed file, saveas first if Cream_buffer_isnewunmod() == 1 if has("browse") " browse confirm w let n = browse("", "", getcwd(), "") if n = "" return endif else call confirm(" WARNING!\n Cream_close() unfinished for terminal in cream-lib.vim. Aborting close.", "&Ok", 1, "Warning") return "confirm w "*** DANGER! if cancelled, exit still happens. endif else write endif elseif mychoice == 2 " no: don't save changes! else " cancel or error: do nothing return endif endif " go to previous tag if v:version >= 700 && exists("g:CREAM_TABPAGES") && g:CREAM_TABPAGES == 1 " go back there (in same window) silent! pop " remember (in same window) let bufnr = bufnr("%") " come back here (in same window) silent! tag " go to tab containing that buffer call Cream_tab_goto(bufnr) endif " go back to tag silent! pop " delete referenced buffer if not this file if mybufno != bufnr("%") " close only if unmodified if getbufvar(mybufno, "&modified") != 1 execute "bwipeout! " . mybufno endif " refresh buffer list call BMShow() endif endfunction function! Cream_Tlist_toggle() " window management wrapper for :Tlist " test if open let i = 1 while i <= bufnr('$') if bufname(i) == "__Tag_List__" let open = 1 endif let i = i + 1 endwhile " open if not if !exists("open") "let s:tlist_part_of_winmanager = 1 "let g:tlist_bufhidden = 1 if !Cream_has("tags") call s:Cream_tag_warn() return endif " notify external window management call Tlist_Set_App("cream") "call Tlist_Update_File_Tags(fnamemodify(expand("%"), ":p"), &filetype) " call command, not function! execute ":Tlist" " remember what buffer we're in (not window! it will change) let mybufnr = bufnr("%") " reset window configuration call Cream_window_setup() " restore cursor to original current buffer's new window call MoveCursorToWindow(bufwinnr(mybufnr)) " close it else " remember current buffer/window let mybufnr = bufnr("%") let i = 1 while i <= bufnr('$') if bufname(i) == "__Tag_List__" " close execute "bwipeout! " . i break endif let i = i + 1 endwhile " return to orig buffer's window let mywinnr = bufwinnr(bufname(mybufnr)) if mywinnr > 0 call MoveCursorToWindow(mywinnr) endif endif endfunction function! Cream_Tlist_prototype() " Return the current function's prototype without opening the list " window. " if list doesn't exist, initialize "if !exists("b:tlist_tag_count") "\|| b:tlist_tag_count == 0 " " regenerate tags " let b:tlist_tag_count = 0 " call setbufvar(bufnr("%"), 'tlist_sort_type', 'order') " call s:Tlist_Process_File(fnamemodify(expand("%"), ":p"), &filetype) "endif call Tlist_Update_File_Tags(fnamemodify(expand("%"), ":p"), &filetype) "let g:Tlist_Process_File_Always = 1 return Tlist_Get_Tag_Prototype_By_Line() endfunction " Goto {{{1 function! Cream_goto() " go to line number or % of file let m = 1 while m == 1 " set default empty, unless repeating if !exists("n") let n = "" endif let n = inputdialog("Enter line number to go to.\n(End with \"%\" to go to percentage in file.)", n) " remove spaces let n = substitute(n, " ", "", "g") " validate " invalid if contains anything but number and "%" if match(n, "[^0-9%]") > -1 let m = confirm("Only numbers and trailing \"%\" allowed.", "&Ok\n&Cancel", 1, "Info") if m != 1 return endif else break endif endwhile " if contains "%" go to percentage if match(n, "%") != -1 " invalid if "%" not at end if strpart(n, strlen(n) - 1, 1) != "%" call confirm("\"%\" must be last character.", "&Ok", 1, "Info") return else " goto percent execute "normal " . n . "%" endif else " goto line number execute "normal :" . n . "\" endif endfunction " Folding {{{1 function! Cream_fold(direction) " fold toggle (or go to next above/below) let myfold = foldlevel(line('.')) " in fold, toggle if myfold != 0 normal za " not in fold else " go up to previous ("up" argument) if a:direction == "up" " move to end of previous fold normal zk " go down to next else " move to start of next fold normal zj endif endif endfunction function! Cream_fold_set(mode) if a:mode != "v" return endif normal gv " Note: We'd love to remove foldmethod=marker here and restore on " the other side, but it doesn't seem to work. normal zf " why would we re-select? Don't. "normal gv endfunction function! Cream_fold_openall() normal zr endfunction function! Cream_fold_closeall() normal zM endfunction function! Cream_fold_delete() normal zd endfunction function! Cream_fold_deleteall() normal zE endfunction function! Cream_fold_init() " called by autocmd VimEnter to automatically open the current fold if foldlevel(line('.')) > 0 let mypos = Cream_pos() normal za execute mypos endif endfunction " Backspace {{{1 function! Cream_map_key_backspace(...) " * Shift+Backspace deletes word (see help for difference between " "word" and "WORD") " * Ctrl+Backspace deletes WORD " this is stupid. Vim can't keep track of position when at line end let oldcol = col('.') let colend = col('$') let oldline = line('.') if exists("a:1") if a:1 == "WORD" let myword = "W" else let myword = "w" endif else let myword = "w" endif " select previous word if oldcol == 1 " 1. at line beginning normal X else normal g^ " if we're already at the beginning of a line if oldcol == col('.') "call confirm("at begin/white", "&Ok") " 2. delete whitespace to beginning of line normal h execute "normal \" execute "normal \" " delete normal x execute "normal X" else " go back to original position while col('.') < oldcol execute "normal l" endwhile "*** evaluation fails, we never get here :( " " can't detect this (stupid / position loss at line end) " if oldcol == colend " "call confirm("else, end", "&Ok") " " 3. at line end " " end of line hoses " normal l " while line('.') > oldline " normal h " endwhile " execute "normal hva" . myword " " delete " normal x " else "*** "call confirm("else, NOT end", "&Ok") " 4. everywhere else execute "normal va" . myword " delete normal x endif endif endfunction " 1}}} " Search " Find/Replace {{{1 " Note: Both these functions are pointless: " o We map directly to :promptfind and :promptrepl to preserve their " multi-modal nature. " o :promptfind and :promptrepl appear to use '\V' by default, as " discussed in list thread on 2004-10-27. function! Cream_find_native() " Dialog Find, using Vim's native find dialog. let mymagic = &magic set nomagic promptfind let &magic = mymagic endfunction function! Cream_replace_native() " Dialog Find, using Vim's native find dialog. let mymagic = &magic set nomagic promptrepl let &magic = mymagic endfunction " Find Under Cursor {{{1 " Note: From visual mode, selection is extended to next find. function! Cream_findunder(mode) let myincsearch = &incsearch set noincsearch if a:mode == "v" normal gv normal "xy " test if exists if search(@x) != 0 " highlight it normal v let i = 0 while i < strlen(@x) normal l let i = i + 1 endwhile endif else silent normal * endif let &incsearch = myincsearch endfunction function! Cream_findunder_reverse(mode) if a:mode == "v" normal gv normal "xy " test if exists if search(@x, "b") != 0 " highlight it normal v let i = 0 while i < strlen(@x) normal l let i = i + 1 endwhile endif else silent normal # endif endfunction function! Cream_findunder_case(mode) let myhls = &hlsearch let myic = &ignorecase set hlsearch set noignorecase if a:mode == "v" normal gv normal "xy " test if exists if search(@x) != 0 " highlight it normal v let i = 0 while i < strlen(@x) normal l let i = i + 1 endwhile endif else silent normal * endif let &ignorecase = myic let &hlsearch = myhls endfunction function! Cream_findunder_case_reverse(mode) let myhls = &hlsearch let myic = &ignorecase set hlsearch set noignorecase if a:mode == "v" normal gv normal "xy " test if exists if search(@x, "b") != 0 " highlight it normal v let i = 0 while i < strlen(@x) normal l let i = i + 1 endwhile endif else silent normal # endif let &ignorecase = myic let &hlsearch = myhls endfunction " Search Highlighting {{{1 " search highlighting function! Cream_search_highlight_init() " initialize search highlighting if !exists("g:CREAM_SEARCH_HIGHLIGHT") " initially off set nohlsearch let g:CREAM_SEARCH_HIGHLIGHT = 0 else if g:CREAM_SEARCH_HIGHLIGHT == 1 set hlsearch else set nohlsearch endif endif endfunction function! Cream_search_highlight_toggle() " toggle search highlighting if exists("g:CREAM_SEARCH_HIGHLIGHT") if g:CREAM_SEARCH_HIGHLIGHT == 0 set hlsearch let g:CREAM_SEARCH_HIGHLIGHT = 1 elseif g:CREAM_SEARCH_HIGHLIGHT == 1 set nohlsearch let g:CREAM_SEARCH_HIGHLIGHT = 0 endif else call Cream_error_warning("Error: global uninitialized in Cream_search_highlight_toggle()") endif call Cream_menu_settings_highlightsearch() endfunction function! Cream_search_highlight_reset() " Reset search highlight to nothing. " TODO: Vim bug, this won't work from within a function. nohlsearch endfunction " 1}}} " Wrap " Word Wrap (Line wrap; wrap words at window margin) {{{1 " * By default, wrap is on, global variable g:CREAM_WRAP remembers session to " session " * Potentially, wrap could be turned on globally after being turned off in a " buffer and states could get confused. Account for both. function! Cream_wrap_init() " initialize wrap (for statusline) " don't change state in special buffers " opsplorer if bufname("%") == "_opsplorer" return endif " calendar if bufname("%") == "__Calendar" return endif " tag list if bufname("%") == "__Tag_List__" return endif " used before if exists("g:CREAM_WRAP") if g:CREAM_WRAP == 1 set wrap set guioptions-=b else set nowrap "execute "set lines=" . (&lines - 2) set guioptions+=b endif else " initialize on set wrap set guioptions-=b let g:CREAM_WRAP = 1 endif endfunction function! Cream_wrap(mode) " toggle word wrap if g:CREAM_WRAP == 1 let g:CREAM_WRAP = 0 set nowrap " save position on Windows if Cream_has("ms") call Cream_screen_get() endif " make window shorter execute "set lines=" . (&lines - 2) " add horiz. scroll bar set guioptions+=b " restore position on Windows if Cream_has("ms") call Cream_screen_init() endif else let g:CREAM_WRAP = 1 set wrap " save position on Windows if Cream_has("ms") call Cream_screen_get() endif " make window longer execute "set lines=" . (&lines + 2) " remove horiz. scroll bar set guioptions-=b " restore position on Windows if Cream_has("ms") call Cream_screen_init() endif endif call Cream_menu_settings_wordwrap() if a:mode == "v" normal gv endif endfunction " Auto Wrap (break lines automatically while typing) {{{1 function! Cream_autowrap_init() " initialize autowrap (for statusline) " don't change state in special buffers " opsplorer if bufname("%") == "_opsplorer" return endif " calendar if bufname("%") == "__Calendar" return endif " initialize wrap width if !exists("g:CREAM_AUTOWRAP_WIDTH") let g:CREAM_AUTOWRAP_WIDTH = 80 endif " used before if exists("g:CREAM_AUTOWRAP") if g:CREAM_AUTOWRAP == 1 execute "set textwidth=" . g:CREAM_AUTOWRAP_WIDTH set expandtab let g:CREAM_EXPANDTAB = 1 else set textwidth=0 set noexpandtab let g:CREAM_EXPANDTAB = 0 endif else " initialize off (use wrap settings) set textwidth=0 set noexpandtab let g:CREAM_AUTOWRAP = 0 let g:CREAM_EXPANDTAB = 0 endif endfunction function! Cream_autowrap(mode) " toggle autowrap " * Autowrap is currently global (buffer specific will mean a global for each buffer!) " * Dependent upon formatoptions-=tcrqn being set elsewhere! if g:CREAM_AUTOWRAP == 1 let g:CREAM_AUTOWRAP = 0 set textwidth=0 set noexpandtab let g:CREAM_EXPANDTAB = 0 else let g:CREAM_AUTOWRAP = 1 execute "set textwidth=" . g:CREAM_AUTOWRAP_WIDTH set expandtab let g:CREAM_EXPANDTAB = 1 endif call Cream_menu_settings_autowrap() if a:mode == "v" normal gv endif endfunction " Wrap Width {{{1 function! Cream_autowrap_setwidth() " Dialog to set g:CREAM_AUTOWRAP_WIDTH (textwidth) " NOTE: g:CREAM_AUTOWRAP_WIDTH is initialized at Cream_autowrap_init() " o Turns autowrap on (or resets) if used let n = Inputdialog("Set new wrap width for autowrap (when on):", g:CREAM_AUTOWRAP_WIDTH) " do nothing on cancel if n == "{cancel}" return " warn only numbers allowed elseif match(n, '[^0-9]') != -1 call confirm( \ "Only numbers are allowed.\n" . \ "\n", "&Ok", 1, "Error") " warn can not set to 0 elseif n == 0 call confirm( \ "Can not set to 0.", "&Ok", 1) " set else let g:CREAM_AUTOWRAP_WIDTH = n + 0 " turn on let g:CREAM_AUTOWRAP = 1 execute "set textwidth=" . g:CREAM_AUTOWRAP_WIDTH set expandtab " update column highlighting " NOTE: Super hack. We do this twice since this feature uses a " simple match (not a syntax highlighting group) so it must be " toggled on and off to reset. call Cream_highlight_columns(g:CREAM_AUTOWRAP_WIDTH) call Cream_highlight_columns(g:CREAM_AUTOWRAP_WIDTH) endif endfunction " Quick Wrap (Re-format existing text) {{{1 function! Cream_quickwrap(mode) " re-formats text " remember let mytextwidth = &textwidth let myautoindent = &autoindent let mysmartindent = &smartindent let myexpandtab = &expandtab " sets execute "set textwidth=" . g:CREAM_AUTOWRAP_WIDTH set autoindent set nosmartindent set expandtab let mypos = Cream_pos() " select if a:mode ==? "i" " select inner paragraph normal vip "" go to end (simplifies calcs) "normal '> " get range ( marks "'<" and "'>" are pre-function!) let myfirstline = line(".") normal o let mylastline = line(".") normal o elseif a:mode ==? "v" normal gv let myfirstline = line("'<") let mylastline = line("'>") else return -1 endif " flipped, put first range value first if mylastline < myfirstline let tmp = myfirstline let myfirstline = mylastline let mylastline = tmp else if virtcol('.') == 1 let atend = 1 endif endif " initialize justify (instance specific) if !exists("g:cream_justify") let g:cream_justify = "left" endif " condition wrap of content with numbered list " retain &formatoptions let myformatoptions = &formatoptions " Note: we still have a selection... yank it to register normal "xy normal gv if match(@x, '^[ \t]*\d\+[\.\:\)\]\}]\{1}[ \t]\+') != -1 set formatoptions+=n else set formatoptions-=n endif " clear register let @x = "" " wrap if g:cream_justify ==? "left" call s:Cream_wrap_left(myfirstline . "," . mylastline) elseif g:cream_justify ==? "center" call s:Cream_wrap_center(myfirstline . "," . mylastline) elseif g:cream_justify ==? "right" call s:Cream_wrap_right(myfirstline . "," . mylastline) elseif g:cream_justify ==? "full" execute myfirstline . "," . mylastline . "call Justify('tw', 3)" "else " call confirm( " \ "Error: Incorrect justification value in Cream_quickwrap()\n" . " \ "\n", "&Ok", 1, "Info") " return endif " restore &formatoptions let &formatoptions = myformatoptions " recover if a:mode ==? "i" "*** BROKEN: "startinsert "normal i "*** execute "normal \" " position execute mypos else execute mypos " selection normal gv endif " restore let &textwidth = mytextwidth let &autoindent = myautoindent let &smartindent = mysmartindent let &expandtab = myexpandtab endfunction function! s:Cream_wrap_left(range) " remove extra inner spaces if requested twice if Cream_delay() == 1 execute "silent! " . a:range . 'substitute/\(^[\s]\+\)\@!\(\S\+\) \+/\2 /gei' endif " format normal gq endfunction function! s:Cream_wrap_center(range) " remove extra inner spaces if requested twice if Cream_delay() == 1 execute "silent! " . a:range . 'substitute/\(^[\s]\+\)\@!\(\S\+\) \+/\2 /gei' endif " format execute "silent! " . a:range . "center" endfunction function! s:Cream_wrap_right(range) " remove extra inner spaces if requested twice if Cream_delay() == 1 execute "silent! " . a:range . 'substitute/\(^[\s]\+\)\@!\(\S\+\) \+/\2 /gei' endif " format execute "silent! " . a:range . "right" endfunction function! Cream_delay() " returns 1 if has been called before within two seconds " init timing if !exists("g:delaytime") let g:delaytime = localtime() return 0 endif " only eliminate spaces if called twice within two seconds if localtime() - g:delaytime < 2 let myreturn = 1 else let myreturn = 0 endif " record new time let g:delaytime = localtime() return myreturn + 0 endfunction function! Cream_quickwrap_set(mode, justification) " sets justification type and then quick wraps if selection (mode == "v") " insert mode: set mode, don't justify (user should quick wrap) if a:mode ==? "i" let g:cream_justify = a:justification return " visual mode: temp set mode, justify elseif a:mode ==? "v" " save environment if exists("g:cream_justify") let myjustify = g:cream_justify else let myjustify = "left" endif let g:cream_justify = a:justification call Cream_quickwrap(a:mode) let g:cream_justify = myjustify endif endfunction " Quick UnWrap {{{1 function! Cream_quickunwrap(mode) " remember let mytextwidth = &textwidth " set textwidth ridiculously high (100 lines of 100 chars) set textwidth=10000 " main if a:mode == "i" let mypos = Cream_pos() " select inner paragraph normal vip elseif a:mode == "v" normal gv else return -1 endif normal gq if a:mode == "i" execute mypos elseif a:mode == "v" normal gv endif " restore let &textwidth = mytextwidth endfunction " 1}}} " GUI " GUI functions {{{1 " font function! Cream_font_init() if !has("gui_running") return -1 endif let myos = Cream_getoscode() " set font based on global if exists("g:CREAM_FONT_" . myos) " had a problem with guifont being set to * in an error. "*** this fixed in patch 6.1.296 *** if g:CREAM_FONT_{myos} != "*" "execute "set guifont=" . g:CREAM_FONT_{myos} "execute "set printfont=" . g:CREAM_FONT_{myos} " fix fonts with spaces in names let g:CREAM_FONT_{myos} = substitute(g:CREAM_FONT_{myos}, " ", "\ ", "g") let &guifont = g:CREAM_FONT_{myos} let &printfont = g:CREAM_FONT_{myos} else " clean out possible error value unlet g:CREAM_FONT_{myos} endif else " Don't prompt to initialize font... use default. let g:CREAM_FONT_{myos} = "" endif endfunction function! Cream_font_set() if !has("gui_running") return -1 endif let myos = Cream_getoscode() " save screen pos " HACK: set guifont=* moves screen on WinXP call Cream_screen_get() silent! set guifont=* " if still empty or a "*", user may have cancelled; do nothing if &guifont == "*" \|| g:CREAM_FONT_{myos} == "" && &guifont == "" " do nothing else let g:CREAM_FONT_{myos} = &guifont endif " restore screen pos " HACK: set guifont=* moves screen on WinXP call Cream_screen_init() return endfunction " window positioning function! Cream_screen_init() " * Dynamically set based on previous settings " * Remembers and restores winposition, columns and lines stored in global " variables written to viminfo " * Must follow Cream_font_init() so that columns and lines are accurate based " on font size. if !has("gui_running") return -1 endif let myos = Cream_getoscode() " initialize if !exists("g:CREAM_COLS_" . myos) let g:CREAM_COLS_{myos} = 80 endif if !exists("g:CREAM_LINES_" . myos) let g:CREAM_LINES_{myos} = 30 endif if !exists("g:CREAM_WINPOSX_" . myos) " don't set to 0, let window manager decide let g:CREAM_WINPOSX_{myos} = "" endif if !exists("g:CREAM_WINPOSY_" . myos) " don't set to 0, let window manager decide let g:CREAM_WINPOSY_{myos} = "" endif " set if exists("g:CREAM_WINPOS") && g:CREAM_WINPOS == 1 execute "set columns=" . g:CREAM_COLS_{myos} execute "set lines=" . g:CREAM_LINES_{myos} execute "winpos " . g:CREAM_WINPOSX_{myos} . " " . g:CREAM_WINPOSY_{myos} endif endfunction function! Cream_screen_get() " used by Cream_exit() to retain window position and size if !has("gui_running") return -1 endif let myos = Cream_getoscode() let g:CREAM_COLS_{myos} = &columns let g:CREAM_LINES_{myos} = &lines let g:CREAM_WINPOSX_{myos} = getwinposx() " filter error condition if g:CREAM_WINPOSX_{myos} < 0 let g:CREAM_WINPOSX_{myos} = 0 endif let g:CREAM_WINPOSY_{myos} = getwinposy() " filter error condition if g:CREAM_WINPOSY_{myos} < 0 let g:CREAM_WINPOSY_{myos} = 0 endif endfunction function! Cream_screen_unlet() " Used by singleserver to unset window position and size. if !has("gui_running") return -1 endif let myos = Cream_getoscode() unlet g:CREAM_COLS_{myos} unlet g:CREAM_LINES_{myos} unlet g:CREAM_WINPOSX_{myos} unlet g:CREAM_WINPOSY_{myos} endfunction " window positioning preference (on/off) function! Cream_winpos_init() " initialize window positioning if !exists("g:CREAM_WINPOS") " initiallize on let g:CREAM_WINPOS = 1 endif endfunction function! Cream_winpos_toggle() " toggle window positioning if exists("g:CREAM_WINPOS") if g:CREAM_WINPOS == 0 let g:CREAM_WINPOS = 1 else let g:CREAM_WINPOS = 0 endif else call Cream_error_warning("Error: global uninitialized in Cream_winpos_toggle()") endif " update the menu item call Cream_menu_settings_preferences() endfunction " Mouse {{{1 function! Cream_mouse_middle_init() " initialize middle mouse button to one of two behavior styles if exists("g:CREAM_MOUSE_XSTYLE") && g:CREAM_MOUSE_XSTYLE == 1 " X-compatible paste (paste "* [selection] register) set guioptions+=a silent! iunmap silent! vunmap vnoremap else " "normal" middle mouse behavior set guioptions-=a imap vmap imap <2-MiddleMouse> vmap <2-MiddleMouse> endif endfunction function! Cream_mouse_middle_toggle() " toggles middle mouse button between one of two behavior styles if exists("g:CREAM_MOUSE_XSTYLE") && g:CREAM_MOUSE_XSTYLE == 1 unlet g:CREAM_MOUSE_XSTYLE else let g:CREAM_MOUSE_XSTYLE = 1 endif call Cream_mouse_middle_init() call Cream_menu_settings_preferences() endfunction " 1}}} " Settings " Tabstop settings {{{1 " tabstop AND shift width (force the same) function! Cream_tabstop_init() " Initialize tab settings, called via autocmd each BufEnter. " don't change if in help file if &filetype == "help" return 1 endif if exists("g:CREAM_TABSTOP") execute "set tabstop=" . g:CREAM_TABSTOP else " never initialized before set tabstop=4 let g:CREAM_TABSTOP = 4 endif if exists("g:CREAM_SOFTTABSTOP") execute "set shiftwidth=" . g:CREAM_SOFTTABSTOP execute "set softtabstop=" . g:CREAM_SOFTTABSTOP else " use tabstop execute "set shiftwidth=" . g:CREAM_TABSTOP execute "set softtabstop=" . g:CREAM_TABSTOP endif endfunction function! Cream_tabstop() " Set tabstop and associated via dialog (and Cream global variables). if !exists("g:CREAM_TABSTOP") let n = Inputdialog("Enter tabstop width:", 4) else let n = Inputdialog("Enter tabstop width:", g:CREAM_TABSTOP) endif " cancel if n == "{cancel}" return " empty or 0 elseif n == "" || n == "0" " if empty if !exists("g:CREAM_TABSTOP") " previous setting didn't exist, auto set to 4 if global didn't previously exist call confirm("Setting to default (4).", "&Ok", 1) call Cream_tabstop_init() else " previous setting existed, just use it call confirm("0 not allowed, defaulting to previous setting (" . g:CREAM_TABSTOP . ")", "&Ok", 1) endif " non-digits elseif n =~ '\D' call confirm( \ "Only number values accepted.\n" . \ "\n", "&Ok", 1, "Info") return " use new setting (allows "stupid" settings, ie, 1000) else let g:CREAM_TABSTOP = n execute "set tabstop=" . g:CREAM_TABSTOP if exists("g:CREAM_SOFTTABSTOP") execute "set shiftwidth=" . g:CREAM_SOFTTABSTOP execute "set softtabstop=" . g:CREAM_SOFTTABSTOP else execute "set shiftwidth=" . g:CREAM_TABSTOP execute "set softtabstop=" . g:CREAM_TABSTOP endif endif return g:CREAM_TABSTOP endfunction function! Cream_softtabstop() " Set softtabstop and shiftwidth via dialog (and Cream global variables) let introstr = "Soft tabstop allows new editing to use different \n" . \ "tabstop settings than existing text. Enter your new \n" . \ "tab width below, the main tabstop setting will \n" . \ "maintain existing text at the old tab spacing.\n" . \ "\n" . \ "To turn off soft tabstop, enter 0 or an empty box.\n" . \ "\n" if !exists("g:CREAM_SOFTTABSTOP") let n = Inputdialog(introstr, 4) else let n = Inputdialog(introstr, g:CREAM_SOFTTABSTOP) endif " cancel if n == "{cancel}" return " empty or 0 elseif n == "" || n == "0" if exists("g:CREAM_SOFTTABSTOP") unlet g:CREAM_SOFTTABSTOP call Cream_tabstop_init() endif " non-digits elseif n =~ '\D' call confirm( \ "Only number values accepted.\n" . \ "\n", "&Ok", 1, "Info") return " use new setting else let g:CREAM_SOFTTABSTOP = n execute "set shiftwidth=" . g:CREAM_SOFTTABSTOP execute "set softtabstop=" . g:CREAM_SOFTTABSTOP endif endfunction " Auto Indentation {{{1 " autoindent function! Cream_autoindent_init() " initialize autoindent (according to whatever on/off state currently " exists) " don't change state in special buffers " opsplorer if bufname("%") == "_opsplorer" return endif " calendar if bufname("%") == "__Calendar" return endif if !exists("g:CREAM_AUTOINDENT") " initially on call s:Cream_indent_on() else if g:CREAM_AUTOINDENT == 1 call s:Cream_indent_on() else call s:Cream_indent_off() endif endif endfunction function! Cream_autoindent_toggle() " toggle autoindent if exists("g:CREAM_AUTOINDENT") if g:CREAM_AUTOINDENT == 0 call s:Cream_indent_on() elseif g:CREAM_AUTOINDENT == 1 call s:Cream_indent_off() endif else call Cream_error_warning("Error: global uninitialized in Cream_autoindent_toggle()") endif call Cream_menu_settings_autoindent() endfunction function! s:Cream_indent_on() if exists("did_indent_on") unlet did_indent_on endif if exists("b:did_indent") unlet b:did_indent endif filetype indent on let g:CREAM_AUTOINDENT = 1 if &indentexpr == "" setlocal autoindent "setlocal smartindent endif endfunction function! s:Cream_indent_off() setlocal noautoindent "setlocal nosmartindent filetype indent off let g:CREAM_AUTOINDENT = 0 endfunction " Line numbers {{{1 function! Cream_linenumbers_init() " initialize line numbers if !exists("g:CREAM_LINENUMBERS") " initiallize on set number let g:CREAM_LINENUMBERS = 1 else if g:CREAM_LINENUMBERS == 1 set number else set nonumber endif endif endfunction function! Cream_linenumbers_init_buffer() " initialize line numbers upon entering buffer if g:CREAM_LINENUMBERS == 1 " turn on in buffer set number let b:cream_linenumbers = 1 else " turn off in buffer if exists("b:cream_linenumbers") let b:cream_linenumbers = 0 endif set nonumber endif endfunction function! Cream_linenumbers_toggle() " toggle line numbers if exists("g:CREAM_LINENUMBERS") if g:CREAM_LINENUMBERS == 0 set number let g:CREAM_LINENUMBERS = 1 elseif g:CREAM_LINENUMBERS == 1 set nonumber let g:CREAM_LINENUMBERS = 0 endif else call Cream_error_warning("Error: global uninitialized in Cream_linenumbers_toggle()") endif call Cream_menu_settings_linenumbers() endfunction " Syntax highlighting {{{1 function! Cream_syntax_init() " initialize syntax highlighting if !exists("g:CREAM_SYNTAX") " initialize on syntax on let g:CREAM_SYNTAX = 1 else if g:CREAM_SYNTAX == 1 " no need to initialize (besides, it hoses custom " highlighting in current file on startup) "syntax on else syntax off endif endif endfunction function! Cream_syntax_toggle(mode) " toggle syntax highlighting if exists("g:CREAM_SYNTAX") if g:CREAM_SYNTAX == 0 syntax on let g:CREAM_SYNTAX = 1 call Cream_filetype() elseif g:CREAM_SYNTAX == 1 syntax off let g:CREAM_SYNTAX = 0 endif else call Cream_error_warning("Error: global uninitialized in Cream_syntax_toggle()") endif if a:mode == "v" normal gv endif call Cream_menu_settings_syntax() endfunction " Highlight current line {{{1 function! Cream_highlight_currentline() " Initialize current line highlighting, method depends on Vim version. " Source: http://vim.sourceforge.net/tips/tip.php?tip_id=421 if v:version >= 700 return endif if exists("g:CREAM_HIGHLIGHT_CURRENTLINE") let linewidth = Cream_linewidth() let linestart = Cream_winline_start(linewidth) execute 'silent! match CurrentLine /\%' . line('.') . 'l\%<' . (linestart + linewidth) . 'v.\%>' . (linestart) . 'v/' endif endfunction function! Cream_highlight_currentline_init() " Initialize current line highlighting, Vim 7.0+, called by autocmd. if v:version < 700 call Cream_highlight_currentline() return endif if exists("g:CREAM_HIGHLIGHT_CURRENTLINE") if &cursorline == 0 set cursorline endif else if &cursorline == 1 set nocursorline endif endif endfunction function! Cream_winline_start(linewidth) " return start of current screen line let len = virtcol('$') let pos = virtcol('.') " if line shorter than window, only one screen line if len <= a:linewidth return 1 endif " if position is less than line width, on first line if pos <= a:linewidth return 1 endif " we're beyond the first screen line let i = 1 while i < pos + 1 let i = i + a:linewidth endwhile return i - a:linewidth endfunction function! Cream_highlight_currentline_toggle() if exists("g:CREAM_HIGHLIGHT_CURRENTLINE") unlet g:CREAM_HIGHLIGHT_CURRENTLINE if v:version >= 700 set nocursorline else " clear current line execute 'silent! match none /\%' . line('.') . 'l/' endif else let g:CREAM_HIGHLIGHT_CURRENTLINE = 1 if v:version >= 700 set cursorline else call Cream_highlight_currentline() endif endif call Cream_menu_settings_highlightcurrentline() endfunction " Highlight columns {{{1 function! Cream_highlight_columns(column) " toggle highlighting of column {column} and beyond if !exists("b:cream_col_highlight") let b:cream_col_highlight = 1 else unlet b:cream_col_highlight endif "let b:cream_col_highlight =! b:cream_col_highlight if exists("b:cream_col_highlight") highlight! link ColumnBeyond Todo execute 'match ColumnBeyond /.\%>' . (a:column+1) . 'v/' else match none endif call Cream_menu_settings_highlightwrapwidth() endfunction " Toolbar toggle {{{1 " NOTE: Cream_toolbar_init() is in cream-settings.vim! function! Cream_toolbar_toggle() " toggle toolbar (initialization in cream-menu.vim " initialize if !exists("g:CREAM_TOOLBAR") let g:CREAM_TOOLBAR = 1 endif " reverse current status if g:CREAM_TOOLBAR == 1 set guioptions-=T " no toolbar let g:CREAM_TOOLBAR = 0 else set guioptions+=T " toolbar let g:CREAM_TOOLBAR = 1 endif call Cream_menu_settings_preferences() endfunction " Statusline toggle {{{1 function! Cream_statusline_init() " initialize statusline state if !exists("g:CREAM_STATUSLINE") " initialize on set laststatus=2 let g:CREAM_STATUSLINE = 1 else if g:CREAM_STATUSLINE == 1 set laststatus=2 else set laststatus=0 endif endif endfunction function! Cream_statusline_toggle() " toggle syntax highlighting if exists("g:CREAM_STATUSLINE") if g:CREAM_STATUSLINE == 0 set laststatus=2 let g:CREAM_STATUSLINE = 1 elseif g:CREAM_STATUSLINE == 1 set laststatus=0 let g:CREAM_STATUSLINE = 0 endif else call Cream_error_warning("Error: global uninitialized in Cream_statusline_toggle()") endif call Cream_menu_settings_preferences() endfunction " Bracket matching {{{1 " initialize environment function! Cream_bracketmatch_init() set matchtime=1 if !exists("g:CREAM_BRACKETMATCH") " initially on set showmatch let g:CREAM_BRACKETMATCH = 1 else if g:CREAM_BRACKETMATCH == 1 set showmatch else set noshowmatch endif endif endfunction " toggle on/off function! Cream_bracketmatch_toggle() if exists("g:CREAM_BRACKETMATCH") if g:CREAM_BRACKETMATCH == 0 set showmatch let g:CREAM_BRACKETMATCH = 1 elseif g:CREAM_BRACKETMATCH == 1 set noshowmatch let g:CREAM_BRACKETMATCH = 0 endif else call confirm( \"Error: global uninitialized in Cream_bracketmatch_toggle()", "&Ok", 1, "Error") endif call Cream_menu_settings_preferences() endfunction " Errorbells {{{1 function! Cream_errorbells_off(...) " control Vim's audio and visual warnings " * Arguments: " "beep": turn off just beeping " "flash": turn off just flashing " (empty): both off " * Must be initialized after the GUI starts! " off if a:0 == 0 let myeb = "" else let myeb = a:1 endif if myeb ==? "flash" " audibly beep on error messages set errorbells " Screen flash on error (See also 't_vb') set novisualbell set t_vb= elseif myeb ==? "beep" " audibly beep on error messages set noerrorbells " Screen flash on error (See also 't_vb') set visualbell set t_vb& elseif myeb ==? "" " audibly beep on error messages set noerrorbells " Screen flash on error (See also 't_vb') set visualbell set t_vb= endif endfunction " Keymap {{{1 function! Cream_keymap(map) " change the setting of &keymap let g:CREAM_KEYMAP = a:map execute "set keymap=" . g:CREAM_KEYMAP " refresh menu to indicate new setting call Cream_menu_settings_preferences() endfunction function! Cream_keymap_init() " initialize &keymap if !exists("g:CREAM_KEYMAP") let g:CREAM_KEYMAP = "" else execute "set keymap=" . g:CREAM_KEYMAP endif endfunction " 1}}} " Inserts " Char Inserts {{{1 " Insert Digraph function! Cream_digraph_insert() " only available from insert mode "********************************************************************* " The insertion of digraphs does not occur via function! Since the " native keystroke is only available via insertmode, we're " unable to functionalize it. "********************************************************************* "normal i "execute "i\IE" endfunction " List Digraphs function! Cream_digraph_list() let str = \ "\n" . \ " The following digraph list is in the format:\n" . \ "\n" . \ " At @ 64\n" . \ "\n" . \ " where first two letters (\"digraph\") are typed to insert the following \n" . \ " character. The trailing digits indicate that character's decimal value.\n" . \ "\n" . \ " Note that proper display is dependant on operating system, font, and \n" . \ " file encoding. Characters beyond decimal 126 are generally unreliable.\n" . \ "\n" echo str digraphs endfunction function! Cream_insert_char() " Insert a char at cursor based on decimal, hex, or octal value. Uses " inputdialog for prompt. " get string representing value let x = Inputdialog("Input decimal value of character to insert:\n" . \ "(preceed with \"0x\" for hexidecimal, \"0\" for octal)\n" . \ "", "") " convert to char let @x = nr2char(x) " TODO: work around errant code for map if x == "174" let @x = "®" endif " get pos let line = line('.') let vcol = virtcol('.') " insert char if vcol == col('$') - 1 normal "xgp else normal "xgP endif endfunction function! Cream_allchars_list() " only use for > ascii if &encoding != "latin1" echo "\n" echo " (Use [Enter] to scroll by line, [Space] by page, or [Esc] to close.)" echo "\n" endif echo Cream_ascii_table() " limitations let min = 32 if &encoding == "latin1" echo "\n" echo " Set another file encoding (e.g. Unicode UTF-8) to test characters " echo " beyond decimal 255." echo "\n" return else let max = 65375 endif let str = "" " display setup echo "\n" echo " All characters available on this computer up to " . max . " places \n" echo " are listed below by HEXIDECIMAL VALUE. (Proper display is dependant on \n" echo " the current encoding and font.)" echo "\n" let numlen = strlen(Nr2Hex(max)) let num = "" if &columns < 80 let wid = &columns / 2 else let wid = 21 " 37 endif let i = 0 while min+i < max if i % (wid - strlen(max)) == 0 " headings if i == 0 || (i+16) % 256 == 0 echo " _________________________________________________" echo " 0 1 2 3 4 5 6 7 8 9 a b c d e f " echo " ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯" endif echo str let num = min+i " do in hex if bigger than decimal (:help i_CTRL-V_digit) if max > 255 let num = Nr2Hex(num) endif " pad let num = Cream_str_pad(num, numlen) let str = num . ": " endif let str = str . nr2char(min+i) . " " let i = i + 1 endwhile " print any remainder echo str endfunction " Date/Time {{{1 function! Cream_insert_datetime(...) " Insert the date/time at the cursor. If {...} is 1, use dialog to " select format. Otherwise, use default/last picked. " " Formatting References: " o http://www.saqqara.demon.co.uk/datefmt.htm " o http://www.opengroup.org/onlinepubs/7908799/xsh/strftime.html " o http://www.cl.cam.ac.uk/~mgk25/iso-time.html " o http://www.w3.org/TR/NOTE-datetime " retain existing dialog button display orientation let sav_go = &guioptions " make vertical set guioptions+=v " set default pick if no previous preference if !exists("g:CREAM_DATETIME_STYLE") let g:CREAM_DATETIME_STYLE = 1 endif if a:0 == 1 \ && a:1 == 1 " let button text equal current values let mybuttons = \ substitute(strftime('%d %B %Y'), '^0*', '', 'g') . "\n" . \ substitute(strftime('%d %b %Y'), '^0*', '', 'g') . "\n" . \ strftime('%Y %B %d') . "\n" . \ strftime('%Y %b %d') . "\n" . \ strftime('%Y-%b-%d') . "\n" . \ strftime("%Y-%m-%d") . "\n" . \ strftime("%Y-%m-%d, %I:%M") . tolower(strftime("%p")) . "\n" . \ strftime("%Y-%m-%d, %H:%M") . "\n" . \ strftime("%Y-%m-%d %H:%M:%S") . "\n" . \ strftime("%Y-%m-%d %H:%M:%S") . Cream_timezone() . "\n" . \ strftime("%Y%m%dT%H%M%S") . Cream_timezone() . "\n" . \ "&Cancel" let n = confirm( \ "Select the date/time format to insert: \n" . \ "\n" . \ "\n", mybuttons, g:CREAM_DATETIME_STYLE, "Info") else let n = g:CREAM_DATETIME_STYLE endif if n == 1 " 14 February 2003 (minus leading 0's) let mytime = substitute(strftime('%d %B %Y'), '^0*', '', 'g') elseif n == 2 " 14 Feb 2003 (minus leading 0's) let mytime = substitute(strftime('%d %b %Y'), '^0*', '', 'g') elseif n == 3 " 2003 February 14 let mytime = strftime('%Y %B %d') elseif n == 4 " 2003 Mar 14 let mytime = strftime("%Y %b %d") elseif n == 5 " 2003-Mar-14 let mytime = strftime("%Y-%b-%d") elseif n == 6 " 2003-03-14 let mytime = strftime("%Y-%m-%d") elseif n == 7 " 2003-02-14, 10:28pm let mytime = strftime("%Y-%m-%d, %I:%M") . tolower(strftime("%p")) elseif n == 8 " 2003-02-14, 22:28 let mytime = strftime("%Y-%m-%d, %H:%M") elseif n == 9 " 2003-02-14 22:28:14 let mytime = strftime("%Y-%m-%d %H:%M:%S") elseif n == 10 " 2003-02-14 22:28:23-0500 let mytime = strftime("%Y-%m-%d %H:%M:%S") . Cream_timezone() elseif n == 11 " 20030214T102823-0500 let mytime = strftime("%Y%m%dT%H%M%S") . Cream_timezone() else endif " restore gui buttons let &guioptions = sav_go " insert register "i" (condition on col position) if exists("mytime") let @i = mytime if virtcol('.') == virtcol('$') - 1 execute "normal a" . @i normal $ else execute "normal i" . @i normal l endif " remember selection if 0 < n && n < 11 let g:CREAM_DATETIME_STYLE = n endif endif endfunction " Character Lines {{{1 function! Cream_charline(...) " insert character line, full width " accepting argument allows function to be called with a supplied " character as the argument if exists("a:1") let mychar = a:1 else let mychar = nr2char(getchar()) endif " insert character &textwidth number of times *minus the current " position* let mylen = g:CREAM_AUTOWRAP_WIDTH - virtcol('.') call Cream_charline_insert(mychar, mylen) endfunction function! Cream_charline_insert(str, len) " insert a:str a:len number of times let i = 0 while i < a:len execute "normal a" . a:str let i = i + 1 endwhile normal $ endfunction function! Cream_charline_prompt() " a wrapper for Cream_charline() to prompt the user let n = confirm( \ "Enter any character after Continue to insert it as a line. \n" . \ "(Use the keyboard shortcut to avoid this prompt.)\n" . \ "\n", "Continue...\n&Cancel", 1, "Info") if n != 1 return endif call Cream_charline() endfunction function! Cream_charline_lineabove(...) " insert character line the length of the line above " set width based on line above " get str let mystr = getline(line(".") - 1) " substitute tabs for spaces let i = 0 let mytab = "" while i < &tabstop let mytab = mytab . " " let i = i + 1 endwhile let mystr = substitute(mystr, '\t', mytab, 'g') let mylen = strlen(mystr) " accepting argument allows function to be called with a supplied " character as the argument if exists("a:1") let mychar = a:1 else let mychar = nr2char(getchar()) endif " insert character mylen number of times *minus the current " position* let i = 0 " let pad equal 1 unless at line end let mystr = getline('.') let mystr = substitute(mystr, '\t', mytab, 'g') if virtcol('.') != strlen(mystr) let mypad = 1 else let mypad = 0 endif " calculate length let mylen = mylen - virtcol('.') + mypad call Cream_charline_insert(mychar, mylen) endfunction function! Cream_charline_lineabove_prompt() " a wrapper for Cream_charline_lineabove() to prompt the user let n = confirm( \ "Enter any character after Continue to insert it as a line the \n" . \ "length of the line above.\n" . \ "(Use the keyboard shortcut Ctrl+Shift+F4 to avoid this prompt. )\n" . \ "\n", "Continue...\n&Cancel", 1, "Info") if n != 1 return endif call Cream_charline_lineabove() endfunction " 1}}} " Other " Character codes {{{1 function! Cream_char_codes(mode) " display character codes " position if a:mode == "v" "normal gv "elseif a:mode == "i" " normal h endif redir @x normal ga redir END let str = @x let chr = matchstr(str, '.\ze> ') let dec = matchstr(str, '\d\+,\@=') let hex = matchstr(str, '\(Hex \)\@<=\x\+') let oct = matchstr(str, '\(Octal \)\@<=\o\+') if dec == 9 let chr = "(tab)" elseif dec == 10 let chr = "(line feed)" elseif dec == 13 let chr = "(carriage return)" elseif dec == 32 let chr = "(space)" elseif chr == "" call confirm( \ "No character found.\n" . \ "\n", "&Ok", 1, "Info") return endif " windows if chr == "&" && Cream_has("ms") let chr = "&&" endif call confirm( \ "character: " . chr . " \n" . \ "\n" . \ " dec: " . dec . "\n" . \ " hex: " . hex . "\n" . \ " oct: " . oct . "\n" . \ "\n", "&Ok", 1, "Info") endfunction " Version {{{1 function! Cream_version(form) " returns version, subversion, and/or patch number: " arguments: " "version" -- return numerical version number: "6" " "subversion" -- return numerical subversion number: "2" " "patchlevel" -- return numerical patch level number: "57" " "string" -- return version in string form: "6.2.71" " " find version (everything prior to last two digits) let myversion = strpart(v:version, 0, strlen(v:version) - 2) + 0 " find sub-version (last two digits of version) let mysubversion = strpart(v:version, strlen(v:version) - 2) + 0 " find patch level " which will be their problem ;) " Note: This function works only in Vim 6.2 or after since " has("patch##") was introduced in patch 6.1.384. let mypatchlevel = 0 if v:version < 602 " hack :version output redir @x silent! version redir END let mypos1 = matchend(@x, "Included patches: ") if mypos1 != -1 " get pos of line end following let mypos2 = match(@x, "\n", mypos1) " get entire patch level string let tmp = strpart(@x, mypos1, mypos2 - mypos1) " count digits at end (the last numbers in this string are " the highest patch) (add 1, it's 0-based) let cnt = match(tmp, '\d*$') + 1 " strip down to only those let mypatchlevel = strpart(tmp, strlen(tmp) - cnt) else let mypatchlevel = "0" endif else " loop through 999 (some people skip patches, let i = 0 while i < 1000 if has("patch" . i) let mypatchlevel = mypatchlevel + 1 endif let i = i + 1 endwhile endif " find string version let mystring = myversion . "." . mysubversion . "." . mypatchlevel ""*** DEBUG: "let n = confirm( " \ "DEBUG:\n" . " \ " myversion = \"" . myversion . "\"\n" . " \ " mysubversion = \"" . mysubversion . "\"\n" . " \ " mypatchlevel = \"" . mypatchlevel . "\"\n" . " \ " mystring = \"" . mystring . "\"\n" . " \ "\n", "&Ok\n&Cancel", 1, "Info") "if n != 1 " return "endif ""*** if a:form == "version" return myversion elseif a:form == "subversion" return mysubversion elseif a:form == "patchlevel" return mypatchlevel elseif a:form == "string" return mystring else call confirm( \ "Error: Invalid argument passed to Cream_version()\n" . \ "\n", "&Ok", 1, "Info") return -1 endif endfunction " OS code {{{1 " establish os for variable function! Cream_getoscode() " return a mneumonic code for the OS in use if Cream_has("ms") return "WIN" elseif has("unix") return "UNIX" else return "OTHER" endif endfunction " Date, Time, Timezone {{{1 function! Cream_timezone() " Return the current timezone value (system dependent). " o Override with g:CREAM_TIMEZONE. " o Otherwise, most system return strftime("%Z"). " o If system (Windows) does not have strftime("%Z"), empty string "" " is returned. if exists("g:CREAM_TIMEZONE") let timezone = g:CREAM_TIMEZONE else let timezone = strftime("%Z") endif return timezone endfunction function! Cream_daysinyear() " returns leap year status, 0 for false, 1 for true let leap = "" let myyear = strftime("%Y") if myyear % 400 != 0 if myyear % 100 != 0 if myyear % 4 != 0 let leap = 364 else let leap = 365 endif else let leap = 364 endif else let leap = 365 endif return leap endfunction function! Cream_time_convertformat(mode, from, to, ...) " o converts a time format to another " o returns a string " o {...} is the string to be converted (overrides selection in "v" mode) if a:mode == "v" normal gv normal "xy let str = @x endif if a:0 > 0 let str = a:1 endif " convert to seconds (number, not string!) let seconds = "" if a:from == "24" if strlen(str) != 4 call confirm( \ "Error in Cream_time_convertformat().\n" . \ "24-hour times expected to be 4 digits long.\n" . \ "\n", "&Ok", 1, "Info") return endif " get minutes let minutes = matchstr(str, '\d\d$') " strip leading 0 to avoid octal mis-interpretation if match(minutes, '^0') != -1 let minutes = matchstr(minutes, '\d$') endif " get hours let hours = matchstr(str, '^\d\+\ze\d\d') " strip leading 0 to avoid octal mis-interpretation if match(hours, '^0') != -1 let hours = matchstr(hours, '\d$') endif " convert hours and minutes to minutes let minutes = ((hours + 0) * 60) + (minutes + 0) " convert to seconds, string let seconds = minutes * 60 elseif a:from == "minutes" let seconds = str * 60 else call confirm( \ "Unhandled \"from\" time format in Cream_time_convertformat().\n" . \ "\n", "&Ok", 1, "Info") return endif " convert from seconds let time = "" if a:to == "seconds" let time = seconds elseif a:to == "minutes" let time = seconds / 60 elseif a:to == "24" " convert to minutes let time = seconds / 60 " obtain minutes remainder let minutes = time % 60 " pad to two digits while strlen(minutes) < 2 let minutes = "0" . minutes endwhile let hours = time / 60 let time = hours . minutes else call confirm( \ "Unhandled \"to\" time format in Cream_time_convertformat().\n" . \ "\n", "&Ok", 1, "Info") return endif ""*** DEBUG: "let n = confirm( " \ "DEBUG:\n" . " \ " str = \"" . str . "\"\n" . " \ " a:from = \"" . a:from . "\"\n" . " \ " a:to = \"" . a:to . "\"\n" . " \ " seconds = \"" . seconds . "\"\n" . " \ " time = \"" . time . "\"\n" . " \ "\n", "&Ok\n&Cancel", 1, "Info") "if n != 1 " return "endif ""*** if a:mode == "v" let @x = time normal gv normal "xp else " convert to string return strpart(time, 0) endif endfunction " Math {{{1 function! Cream_isfactor(dividend, divisor) " Return 1 if {divisor} is a factor of {dividend}, 0 if not. if a:dividend < a:divisor return 0 elseif a:dividend == a:divisor return 1 endif let i = 1 while 1 " raise divisor to power let divisor_n = a:divisor let j = 1 while j < i let divisor_n = (divisor_n * a:divisor) let j = j + 1 endwhile let modu = a:dividend % divisor_n " if we get to number before non-0 if modu == a:dividend return 1 elseif modu == 0 " still factor, continue else " nope return 0 endif let i = i + 1 endwhile endfunction " Evaluate &statusline/&printheader {{{1 function! Cream_statusline_eval(option) " evaluate &statusline or &printheader value and return an equivelent string if a:option != "statusline" && a:option != "stl" \ && a:option != "printheader" && a:option != "pheader" " invalid return endif execute "let str = &" . a:option " wrap/hide if match(str, "%<") != -1 let str = substitute(str, "%<", '', '') endif " path if match(str, "%f") != -1 let str = substitute(str, "%f", fnamemodify(expand("%"), ":p:h"), 'g') endif " filename if match(str, "%h") != -1 let str = substitute(str, "%h", fnamemodify(expand("%"), ":p:t"), 'g') endif " split left/right if match(str, "%=") != -1 let str = substitute(str, "%=", ' ', '') endif " page numbers if match(str, "%N") != -1 let str = substitute(str, "%N", '1', '') endif " modified if match(str, "%m") != -1 if &modified let str = substitute(str, "%m", ' [+]', '') else let str = substitute(str, "%m", ' ', '') endif endif return str endfunction " Diff Mode {{{1 " called by setting diffexpr=MyDiff() only if has("win32") function! MyDiff() if has("win32") let opt = "-a --binary " if &diffopt =~ "icase" | let opt = opt . "-i " | endif if &diffopt =~ "iwhite" | let opt = opt . "-b " | endif let myfname_in = substitute(v:fname_in, '/', '\', 'g') let myfname_new = substitute(v:fname_new, '/', '\', 'g') let myfname_out = substitute(v:fname_out, '/', '\', 'g') let myVIMRUNTIME = substitute($VIMRUNTIME, '/', '\', 'g') silent execute '!"' . myVIMRUNTIME . '\diff" ' . opt . \ myfname_in . ' ' . myfname_new . ' > ' . myfname_out endif endfunction function! Cream_diffmode_toggle() " toggles diff mode (detects existing state) " * diff mode is *not* retained session to session " * diff mode is *buffer-specific* " * g:cream_diffmode exists if on in any buffer if !exists("b:cream_diffmode") " Win95 error trap let myshellslash = &shellslash set noshellslash " turn on call Cream_diffmode(1) let &shellslash = myshellslash let b:cream_diffmode = 1 " keep track of how many diff mode buffers there are if !exists("g:cream_diffmode") let g:cream_diffmode = 1 else let g:cream_diffmode = g:cream_diffmode + 1 endif else " turn off call Cream_diffmode(0) unlet b:cream_diffmode " keep track of how many diff mode buffers there are let g:cream_diffmode = g:cream_diffmode - 1 if g:cream_diffmode == 0 unlet g:cream_diffmode endif endif endfunction function! Cream_diffmode(state) " turns diff mode on (1) or off (0) " abstracted from Cream_diffmode_toggle() so that autocmd can call " here for new buffers (behind the scenes conformance ;) if a:state == 1 diffthis "" same as using :diffthis "set diff "set scrollbind "set scrollopt=hor "set nowrap "set foldmethod=diff "set foldcolumn=2 let g:CREAM_WRAP = 0 elseif a:state == 0 " diffthis off set nodiff set noscrollbind set scrollopt=ver,jump "set nowrap set foldmethod=manual set foldcolumn=0 "let g:CREAM_WRAP = 0 endif endfunction function! Cream_diffmode_update() " update diff state if exists("b:cream_diffmode") diffupdate endif endfunction " Trim word {{{1 function! Cream_trim(word) " trim whitespace off both ends of the argument return substitute(a:word, '^\s*\(\S*\)\s*$', '\1', 'g') endfunction " Sort and Uniq {{{1 " Line Sort (BISort2) " Source: Piet Delport, vim@vim.org list, 2003-05-01 function! BISort2(start, end) " Sort a selection. Required to be in visual mode. " " Note: The four "toupper()" statements make this sort case-insenstive. " Remove for case-sensitive. if col("'>") == 1 let fix = 1 "call confirm( " \ "FIX!\n" . " \ "\n", "&Ok", 1, "Info") else let fix = 0 endif let i = a:start - 1 while i <= a:end - fix " find insertion point via binary search let i_val = getline(i) let lo = a:start let hi = i while lo < hi let mid = (lo + hi) / 2 let mid_val = getline(mid) if toupper(i_val) < toupper(mid_val) let hi = mid else let lo = mid + 1 if toupper(i_val) == toupper(mid_val) | break | endif endif endwhile " do insert if lo < i exec i.'d_' call append(lo - 1, i_val) endif let i = i + 1 endwhile "normal gv endfunction command! -nargs=0 -range BISort2 call BISort2(, ) function! BISort2Reverse(start, end) call BISort2(a:start, a:end) call Invert(a:start, a:end) endfunction command! -nargs=0 -range BISort2Reverse call BISort2Reverse(, ) function! Invert(start, end) if col("'>") == 1 let fix = 1 else let fix = 0 endif let i = a:end while i >= a:start - fix let i_val = getline(i) exec i.'d_' call append(a:end - 1, i_val) let i = i - 1 endwhile endfunction command! -nargs=0 -range Invert call Invert(, ) " Source: genutils.vim (included with Cream) " Note: Functions are declared local in genutils. (These are global.) function! CmpByString(line1, line2, direction) if a:line1 < a:line2 return -a:direction elseif a:line1 > a:line2 return a:direction else return 0 endif endfunction function! CmpByNumber(line1, line2, direction) let num1 = a:line1 + 0 let num2 = a:line2 + 0 if num1 < num2 return -a:direction elseif num1 > num2 return a:direction else return 0 endif endfunction ""*** obsoleted by above *** "function! Cream_sort_compare(idx1, idx2) "" return the index (1 or 2) for which of two arguments come first "" alphabetically "" * An empty value will be returned as first, too. " " let i = 0 " while i < strlen(a:idx1) " let myval1 = strpart(a:idx1, i, 1) " let myval2 = strpart(a:idx2, i, 1) " if char2nr(myval1) == char2nr(myval2) " let i = i + 1 " continue " elseif char2nr(myval2) > char2nr(myval1) " return 1 " else " return 2 " endif " let i = i + 1 " endwhile " " " two are equal for the length of a:idx1 " if strlen(a:idx2) > strlen(a:idx1) " " 2 is longer, so after " return 2 " else " " equal! " return 0 " endif " "endfunction function! Cream_uniq(mode) " call function to uniq a selection if a:mode != "v" return endif "normal gv " cursor in first column of last line implies not selected let mycol = col('.') let myline1 = line("'<") let myline2 = line("'>") if mycol == "1" let myline2 = myline2 - 1 endif let n = confirm( \ "Uniq only works on sorted lines. Do you want to sort the selection first?\n" . \ "\n", "&Yes\n&No\n&Cancel", 1, "Info") if n == 1 call BISort2(myline1, myline2) elseif n == 2 " do nothing, proceed with uniq else return endif call Uniq(myline1, myline2) " DON'T RESELECT! Lines deleted so it can't be the same. endfunction " Note: we use this as a library function, see Cream_uniq() for the " call. " " Author: Jean Jordaan " Source: http://groups.yahoo.com/group/vim/message/16444 " Date: Mon Feb 26, 2001 5:34 am " Subject: Some functions to read mailing list digests with Vim. " function! Uniq(...) range " use arguments if two passed if a:0 == 2 let a = a:1 let z = a:2 " use range else let a = a:firstline let z = a:lastline endif while (a <= z) let str1 = getline(a) let str2 = getline(a+1) if (str1 == str2) execute a . "delete" let z = z - 1 else let a = a + 1 endif endwhile endfunction " :Uniq takes a range of sorted lines and discards duplicates. command! -nargs=0 -range Uniq ,call Uniq() " Completion {{{1 function! Cream_complete_forward() return "\" endfunction function! Cream_complete_backward() return "\" endfunction " Progress Bars {{{1 function! ProgressBar(percent, string, char, barlen) " Draw a progress bar in the command line similar to: " " Loading file... [#################### ] 55% " " Example Call: " " call ProgressBar(55, "Loading file...", "#", 0) " " Arguments: " {percent} -- percent of bar complete " {string} -- leading description string (empty acceptable) " {char} -- character to use as bar (suggest "#", "|" or "*") " {barlen} -- bar length in columns, use 0 to use window width " " establish bar length (if no value passed) if a:barlen == 0 "____________window width__leading string___"["__"] "_63%_ margin let barlen = winwidth(0) - strlen(a:string) - 1 - 2 - 3 - 2 else let barlen = a:barlen endif " define progress let chrs = barlen * a:percent / 100 " define progress to go let chrx = barlen * (100 - a:percent) / 100 " bar, initial string and start line let bar = a:string . "[" " bar, progress while chrs let bar = bar . a:char let chrs = chrs - 1 endwhile " bar, progress to go while chrx let bar = bar . " " let chrx = chrx - 1 endwhile " bar, end line let bar = bar . "] " " bar, extra space if single digit if a:percent < 10 let bar = bar . " " endif " bar, percentage let bar = bar . a:percent . "%" " clear command line execute "normal \:\" " Yikes, this changes window/buffers, saves, other blechy stuff. "execute "normal \:\" " capture cmdheight let cmdheight = &cmdheight " setting to 2+ avoids 'Press Enter...' if cmdheight < 2 let &cmdheight = 2 endif " show on command line echon bar " restore cmdheight let &cmdheight = cmdheight endfunction "function! ProgressBarBuffer(string, progress, char, barlen) "" draw a progress bar *in a blank buffer* based on a percentage "" * WARNING: Draws in a previously opened and current empty buffer! "" ALL CONTENTS OF THE CURRENT BUFFER WILL BE DELETED!! "" * (a:string) -- string preceding bar "" * (a:progress) -- percentage of completion "" * (a:char) -- character used to draw the bar "" * (a:barlen) -- bar length (in chars) " " " loop to get current bar length " let mybar = "" " let i = 0 " while i < a:barlen " " bar characters " if i < (a:progress * a:barlen) / 100 " let mybar = mybar . a:char " " remaining spaces " else " let mybar = mybar . " " " endif " let i = i + 1 " endwhile " " " set echo string " let @x = a:string . "|" . mybar . "| " . a:progress . "%" " " " delete everything in buffer " " go to top, linewise select " normal gggH " " we need to change modes if in select " if mode() == "s" || mode() == "S" " execute "normal \" " endif " " go to bottom, delete " execute "normal G\" " " paste new bar " normal "xp " " redraw screen (and refresh background to remove cursor) " redraw! " "endfunction " Variable Type Conversions {{{1 function! Hex2Nr(hex) " return the decimal value of a Hex string "execute "return 0x" . a:hex let val = ("0x" . a:hex) + 0 "while strlen(val) < 2 " let val = "0" . val "endwhile return val endfunction function! Nr2Hex(nr) " return the Hex string of a number " Inspiration: :help eval-examples let n = a:nr let r = "" while n let r = '0123456789ABCDEF'[n % 16] . r let n = n / 16 endwhile " return a real 0, not empty! if r == "" return "0" else " ensure value padded to two digits while strlen(r) < 2 let r = "0" . r endwhile return tolower(r) endif endfunction function! String2Hex(str) " convert each character in a string to a two character Hex string " Inspiration: from :help eval-examples let out = '' let i = 0 while i < strlen(a:str) let mychar = Nr2Hex(char2nr(a:str[i])) " pad to two characters while strlen(mychar) < 2 let mychar = "0" . mychar endwhile let out = out . mychar let i = i + 1 endwhile return out endfunction function! Hex2String(hex, ...) " convert each two character pair in a string to a character " allows optional argument "silent" to avoid printing error let hex = a:hex " strip whitespace and ctrl chars let hex = substitute(hex, '[ [:cntrl:]]', '', 'g') " ensure pairs of chars if strlen(hex) % 2 != 0 if a:0 == 0 || a:1 != "silent" call confirm( \ "Error in Hex2String(), unable to process unpaired values.\n" . \ "Found: decimal " . "" . "\n" . \ "\n", "&Ok", 1, "Info") endif return a:hex endif let out = '' let i = 0 while i < strlen(hex) " char assumed to be two digits, but only use last if first is 0 if hex[i] == "0" let mychar = hex[i + 1] else let mychar = hex[i] . hex[i + 1] endif let out = out . nr2char(Hex2Nr(mychar)) let i = i + 2 endwhile return out endfunction function! Cream_nonoctal(str) " Returns number from string stripped of leading 0's (potentially " mis-interpreted as octal). "return substitute(a:str, '\(^\|\n\|\s\)\zs0\+', '', 'g') " Alternate: strip leading 0's in a word return substitute(a:str, '\<0\+', '', 'g') + 0 endfunction function! Cream_str2dec_pad(str) " convert a string to a string of decimal numbers, padded to three " registers ( "7" => "007") let newstr = a:str let mypos = 0 let i = 0 let mylength = strlen(newstr) * 3 while mypos < mylength " get first part let mystrfirst = strpart(newstr, 0, mypos) " get middle part (always one char) let mystrmiddle = strpart(newstr, mypos, 1) " get last part let mystrlast = strpart(newstr, mypos + 1) " convert to decimal let mystrmiddle = char2nr(mystrmiddle) " expand to three characters while strlen(mystrmiddle) < 3 let mystrmiddle = "0" . mystrmiddle endwhile " concatenate let newstr = mystrfirst . mystrmiddle . mystrlast " find new pos let mypos = mypos + 3 endwhile return newstr endfunction function! Cream_dec2str_pad(dec) " convert a string of decimal numbers, padded to three registers, to a " string, see Cream_str2dec_pad() ( "007" => "7") let newstr = a:dec " strip all non-digits let newstr = substitute(newstr, "\\D", '', 'g') ""*** DEBUG: "let n = confirm( " \ "DEBUG:\n" . " \ " newstr = \"" . newstr . "\"\n" . " \ " a:dec = \"" . a:dec . "\"\n" . " \ "\n", "&Ok\n&Cancel", 1, "Info") "if n != 1 " return "endif ""*** " un-3 digit ascii, char by char let mylen = strlen(newstr) let mypos = 0 while mypos < mylen " get first part let mystrfirst = strpart(newstr, 0, mypos) " get middle part (always four chars) let mystrmiddle = strpart(newstr, mypos, 3) " get last part let mystrlast = strpart(newstr, mypos + 3) " strip leading "0"s "let tmp1 = "" while strpart(mystrmiddle, 0, 1) == "0" let mystrmiddle = strpart(mystrmiddle, 1) "let tmp1 = mystrmiddle endwhile " convert to char "let tmp2 = mystrmiddle + 0 let mystrmiddle = nr2char(mystrmiddle) ""*** DEBUG: "let n = confirm( " \ "DEBUG:\n" . " \ " mystrfirst = \"" . mystrfirst . "\"\n" . " \ " tmp1 = \"" . tmp1 . "\"\n" . " \ " tmp2 = \"" . tmp2 . "\"\n" . " \ " mystrmiddle = \"" . mystrmiddle . "\"\n" . " \ "\n", "&Ok\n&Cancel", 1, "Info") "if n != 1 " return "endif ""*** " concatenate let newstr = mystrfirst . mystrmiddle . mystrlast " find new pos let mypos = mypos + 1 endwhile return newstr endfunction function! Cream_str2nr_sum(str) " convert a string to a number, the equivelent of each character's " decimal value summed. let nr = 0 let i = 0 while i < strlen(a:str) let nr = nr + char2nr(strpart(a:str, i, 1)) let i = i + 1 endwhile return nr endfunction function! Cream_format_number_commas(str) " Add commas to a string every three characters. ("75300242" => "75,300,242") " don't process less than 4 if strlen(a:str) < 4 return a:str endif let tmp = a:str let str = "" while strlen(tmp) > 3 " last three chars let str = "," . matchstr(tmp, '...$') . str " chew off 3 at a time let tmp = substitute(tmp, '...$', '', "") endwhile " tack on remaining let str = tmp . str return str endfunction " 1}}} " vim:foldmethod=marker