1 " genutils: Useful buffer, file and window related functions.
2 " Author: Hari Krishna Dara (hari_vim at yahoo dot com)
3 " Last Change: 08-Jun-2007 @ 17:36
6 " Licence: This program is free software; you can redistribute it and/or
7 " modify it under the terms of the GNU General Public License.
8 " See http://www.gnu.org/copyleft/gpl.txt
10 " - The genutils#GetNextWinnrInStack() function is based on the WinStackMv()
11 " function posted by Charles E. Campbell, Jr. on vim mailing list on Jul
13 " - The genutils#CommonPath() function is based on the thread,
14 " "computing relative path" on Jul 29, 2002.
15 " - The genutils#ShowLinesWithSyntax() function is based on a posting by
16 " Gary Holloway (gary at castandcrew dot com) on Jan, 16 2002.
17 " - Robert Webb for the original "quick sort" algorithm from eval.txt.
18 " - Peit Delport's (pjd at 303 dot za dot net) for his original BISort()
19 " algorithm on which the genutils#BinInsertSort() and
20 " genutils#BinInsertSort2() functions are based on.
22 " http://www.vim.org/script.php?script_id=197
23 " See Also: autoload/genutils.vim
26 " - Read the "Documentation With Function Prototypes" section below.
27 " - Misc. window/buffer related functions, genutils#NumberOfWindows(),
28 " genutils#FindBufferForName(), genutils#MoveCursorToWindow(),
29 " genutils#MoveCurLineToWinLine(), genutils#SetupScratchBuffer(),
30 " genutils#MapAppendCascaded()
31 " - Save/Restore all the window height/width settings to be restored later.
32 " - Save/Restore position in the buffer to be restored later. Works like the
33 " built-in marks feature, but has more to it.
34 " - genutils#AddNotifyWindowClose() to get notifications *after* a window
35 " with the specified buffer has been closed or the buffer is unloaded. The
36 " built-in autocommands can only notify you *before* the window is closed.
37 " You can use this with the Save/Restore window settings feature to
38 " restore the dimensions of existing windows, after your window is closed
39 " (just like how Vim does while closing help windows). See selectbuf.vim
40 " or perforce.vim for examples.
41 " There is also a test function called RunNotifyWindowCloseTest() that
42 " demos the usage (you need to uncomment RunNotifyWindowCloseTest and
43 " NotifyWindowCloseF functions).
44 " - genutils#ShowLinesWithSyntax() function to echo lines with syntax coloring.
45 " - genutils#ShiftWordInSpace(), genutils#CenterWordInSpace() and
46 " genutils#AlignWordWithWordInPreviousLine() utility functions to move
47 " words in the space without changing the width of the field. A
48 " genutils#GetSpacer() function to return a spacer of specified width.
49 " - Binary search function genutils#BinSearchList() for sorted lists, to
50 " find the index after which a given item can be inserted to keep the list
51 " in sorted order. You can also use these functions to just search for
53 " There are also a couple of functions genutils#BinSearchForInsert() and
54 " genutils#BinSearchForInsert2() to find the location for a newline to be
55 " inserted in an already sorted buffer or arbitrary data.
56 " There are also a few comparison functions that can be used with sort() or
57 " the above functions.
58 " - ExecMap function has now been separated as a plugin called execmap.vim.
59 " - New genutils#CommonPath() function to extract the common part of two
60 " paths, and genutils#RelPathFromFile() and genutils#RelPathFromDir() to
61 " find relative paths (useful HTML href's). A side effect is the
62 " genutils#CommonString() function to find the common string of two
64 " - genutils#UnEscape() and genutils#DeEscape() functions to reverse and
65 " genutils#Escape() to compliment what built-in escape() does. There is
66 " also an genutils#EscapeCommand() function to escape external command
68 " - Utility functions genutils#CurLineHasSign() and genutils#ClearAllSigns()
69 " to fill in the gaps left by Vim.
70 " - genutils#GetVimCmdOutput() function to capture the output of Vim built-in
71 " commands, in a safe manner.
72 " - genutils#OptClearBuffer() function to clear the contents and undo
73 " history of the current buffer in an optimal manner. Ideal to be used
74 " when plugins need to refresh their windows and don't care about
75 " preserving the current contents (which is the most usual case).
76 " - genutils#GetPreviewWinnr() function.
77 " - Functions to have persistent data, genutils#PutPersistentVar() and
78 " genutils#GetPersistentVar(). You don't need to worry about saving in
79 " files and reading them back. To disable, set g:genutilsNoPersist in your
81 " - A function to emulate the default Vim behavior for |timestamp| changes.
82 " It also provides hooks to get call backs before and after handling the
83 " default FileChangedShell autocommand (effectively splitting it into a
84 " Pre and a Post event). Suggested usage is to use
85 " genutils#AddToFCShellPre() and either install a default event handling
86 " mechanism for all files by calling genutils#DefFCShellInstall() or
87 " create your own autocommand on a matching pattern to call
88 " genutils#DefFileChangedShell() function. Most useful for the source
89 " control plugins to conditionally reload a file, while being able to
90 " default to the Vim's standard behavior of asking the user. See
91 " perforce.vim for usage examples.
92 " - Utility function genutils#ExtractFuncListing() that is useful to to
93 " create snippets (see breakpts.vim, ntservices.vim and ntprocesses.vim
94 " for interesting ideas on how to use this function).
96 " Function Prototypes:
97 " The types in prototypes of the functions mimic Java.
98 " This is just a full list for a quick reference, see
99 " "Documentation With Function Prototypes" for more information on the
102 " void genutils#DebugShowArgs(...)
103 " String genutils#ExtractFuncListing(String funcName, String hLines, String tLines)
104 " int genutils#NumberOfWindows()
105 " int genutils#FindBufferForName(String fileName)
106 " String genutils#GetBufNameForAu(String bufName)
107 " void genutils#MoveCursorToWindow(int winno)
108 " void genutils#MoveCurLineToWinLine(int winLine)
109 " void genutils#CloseWindow(int winnr, boolean force)
110 " void genutils#MarkActiveWindow()
111 " void genutils#RestoreActiveWindow()
112 " void genutils#IsOnlyVerticalWindow()
113 " void genutils#IsOnlyHorizontalWindow()
114 " int genutils#GetNextWinnrInStack(char dir)
115 " int genutils#GetLastWinnrInStack(char dir)
116 " void genutils#MoveCursorToNextInWinStack(char dir)
117 " void genutils#MoveCursorToLastInWinStack(char dir)
118 " void genutils#OpenWinNoEa(String openWinCmd)
119 " void genutils#CloseWinNoEa(int winnr, boolean force)
120 " void genutils#SetupScratchBuffer()
121 " void genutils#CleanDiffOptions()
122 " boolean genutils#ArrayVarExists(String varName, int index)
123 " void genutils#MapAppendCascaded(String lhs, String rhs, String mapMode)
124 " void genutils#SaveWindowSettings()
125 " void genutils#RestoreWindowSettings()
126 " void genutils#ResetWindowSettings()
127 " void genutils#SaveWindowSettings2(String id, boolean overwrite)
128 " void genutils#RestoreWindowSettings2(String id)
129 " void genutils#ResetWindowSettings2(String id)
130 " void genutils#SaveVisualSelection(String id)
131 " void genutils#RestoreVisualSelection(String id)
132 " void genutils#SaveSoftPosition(String id)
133 " void genutils#RestoreSoftPosition(String id)
134 " void genutils#ResetSoftPosition(String id)
135 " void genutils#SaveHardPosition(String id)
136 " void genutils#RestoreHardPosition(String id)
137 " void genutils#ResetHardPosition(String id)
138 " int genutils#GetLinePosition(String id)
139 " int genutils#GetColPosition(String id)
140 " boolean genutils#IsPositionSet(String id)
141 " String genutils#CleanupFileName(String fileName)
142 " String genutils#CleanupFileName2(String fileName, String win32ProtectedChars)
143 " boolean genutils#OnMS()
144 " boolean genutils#PathIsAbsolute(String path)
145 " boolean genutils#PathIsFileNameOnly(String path)
146 " void genutils#AddNotifyWindowClose(String windowTitle, String functionName)
147 " void genutils#RemoveNotifyWindowClose(String windowTitle)
148 " void genutils#CheckWindowClose()
149 " void genutils#ShowLinesWithSyntax() range
150 " void genutils#ShiftWordInSpace(int direction)
151 " void genutils#CenterWordInSpace()
152 " int genutils#BinSearchList(List list, int start, int end, Object item,
153 " [Funcref|String] cmp, int direction)
154 " int genutils#BinSearchForInsert(int start, int end, String line,
155 " String cmp, int direction)
156 " int genutils#BinSearchForInsert2(int start, int end, line, String cmp,
157 " int direction, String accessor, String context)
158 " String genutils#CommonPath(String path1, String path2)
159 " String genutils#CommonString(String str1, String str2)
160 " String genutils#RelPathFromFile(String srcFile, String tgtFile)
161 " String genutils#RelPathFromDir(String srcDir, String tgtFile)
162 " String genutils#Roman2Decimal(String str)
163 " String genutils#Escape(String str, String chars)
164 " String genutils#UnEscape(String str, String chars)
165 " String genutils#DeEscape(String str)
166 " String genutils#CrUnProtectedCharsPattern(String chars)
167 " String genutils#EscapeCommand(String cmd, List/String args, List/String pipe)
168 " int genutils#GetShellEnvType()
169 " String genutils#ExpandStr(String str)
170 " String genutils#QuoteStr(String str)
171 " boolean genutils#CurLineHasSign()
172 " void genutils#ClearAllSigns()
173 " String genutils#UserFileComplete(String ArgLead, String CmdLine,
174 " String CursorPos, String smartSlash, String searchPath)
175 " String genutils#UserFileExpand(String fileArgs)
176 " String genutils#GetVimCmdOutput(String cmd)
177 " void genutils#OptClearBuffer()
178 " int genutils#GetPreviewWinnr()
179 " void genutils#PutPersistentVar(String pluginName, String persistentVar,
181 " void genutils#GetPersistentVar(String pluginName, String persistentVar,
183 " void genutils#AddToFCShellPre(String funcName)
184 " void genutils#RemoveFromFCShellPre(String funcName)
185 " void genutils#DefFCShellInstall()
186 " void genutils#DefFCShellUninstall()
187 " boolean genutils#DefFileChangedShell()
188 " void genutils#SilentSubstitute(String pat, String cmd)
189 " void genutils#SilentDelete(String pat)
190 " void genutils#SilentDelete(String range, String pat)
191 " String genutils#GetSpacer(int width)
192 " String genutils#PromptForElement(List array,
193 " [String defaultValue | int defaultIndex], String msg,
194 " String skip, boolean useDialog, int nCols)
195 " int genutils#GetSelectedIndex()
197 " Documentation With Function Prototypes:
198 " -----------------------
199 " Useful function to debug passing arguments to functions. See exactly what
200 " you would receive on the other side.
201 " Ex: :exec 'call genutils#DebugShowArgs('. genutils#CreateArgString("a 'b' c", ' ') . ')'
203 " void genutils#DebugShowArgs(...)
204 " -----------------------
205 " This function returns the body of the specified function ( the name should be
206 " complete, including any scriptid prefix in case of a script local
207 " function), without the function header and tail. You can also pass in the
208 " number of additional lines to be removed from the head and or tail of the
211 " String genutils#ExtractFuncListing(String funcName, String hLines, String tLines)
212 " -----------------------
213 " -----------------------
214 " Return the number of windows open currently.
216 " int genutils#NumberOfWindows()
217 " -----------------------
218 " Returns the buffer number of the given fileName if it is already loaded.
219 " The fileName argument is treated literally, unlike the bufnr() which treats
220 " the argument as a filename-pattern. The function first escape all the
221 " |filename-pattern| characters before passing it to bufnr(). It should work
222 " in most of the cases, except when backslashes are used in non-windows
223 " platforms, when the result could be unpredictable.
225 " Note: The function removes protections for "#%" characters because, these
226 " are special characters on Vim commandline, and so are usually escaped
227 " themselves, but bufnr() wouldn't like them.
229 " int genutils#FindBufferForName(String fileName)
230 " -----------------------
231 " Returns the transformed buffer name that is suitable to be used in
234 " String genutils#GetBufNameForAu(String bufName)
235 " -----------------------
236 " Given the window number, moves the cursor to that window.
238 " void genutils#MoveCursorToWindow(int winno)
239 " -----------------------
240 " Moves the current line such that it is going to be the nth line in the window
241 " without changing the column position.
243 " void genutils#MoveCurLineToWinLine(int winLine)
244 " -----------------------
245 " Closes the given window and returns to the original window. It the simplest,
246 " this is equivalent to:
248 " let curWin = winnr()
249 " exec winnr 'wincmd w'
251 " exec curWin 'wincmd w'
253 " But the function keeps track of the change in window numbers and restores
254 " the current window correctly. It also restores the previous window (the
255 " window that the cursor would jump to when executing "wincmd p" command).
256 " This is something that all plugins should do while moving around in the
257 " windows, behind the scenes.
259 " Pass 1 to force closing the window (:close!).
261 " void genutils#CloseWindow(int winnr, boolean force)
262 " -----------------------
263 " Remembers the number of the current window as well as the previous-window
264 " (the one the cursor would jump to when executing "wincmd p" command). To
265 " determine the window number of the previous-window, the function temporarily
266 " jumps to the previous-window, so if your script intends to avoid generating
267 " unnecessary window events, consider disabling window events before calling
268 " this function (see :h 'eventignore').
270 " void genutils#MarkActiveWindow()
271 " -----------------------
272 " Restore the cursor to the window that was previously marked as "active", as
273 " well as its previous-window (the one the cursor would jump to when executing
274 " "wincmd p" command). To restore the window number of the previous-window,
275 " the function temporarily jumps to the previous-window, so if your script
276 " intends to avoid generating unnecessary window events, consider disabling
277 " window events before calling this function (see :h 'eventignore').
279 " void genutils#RestoreActiveWindow()
280 " -----------------------
281 " Returns 1 if the current window is the only window vertically.
283 " void genutils#IsOnlyVerticalWindow()
284 " -----------------------
285 " Returns 1 if the current window is the only window horizontally.
287 " void genutils#IsOnlyHorizontalWindow()
288 " -----------------------
289 " Returns the window number of the next window while remaining in the same
290 " horizontal or vertical window stack (or 0 when there are no more). Pass
291 " hjkl characters to indicate direction.
293 " let wn = genutils#GetNextWinnrInStack('h') left window number in stack.
294 " let wn = genutils#GetNextWinnrInStack('l') right window number in stack.
295 " let wn = genutils#GetNextWinnrInStack('j') upper window number in stack.
296 " let wn = genutils#GetNextWinnrInStack('k') lower window number in stack.
298 " int genutils#GetNextWinnrInStack(char dir)
299 " -----------------------
300 " Returns the window number of the last window while remaining in the same
301 " horizontal or vertical window stack (or 0 when there are no more, or it is
302 " already the last window). Pass hjkl characters to indicate direction.
304 " let wn = genutils#GetLastWinnrInStack('h') leftmost window number in stack.
305 " let wn = genutils#GetLastWinnrInStack('l') rightmost window number in stack.
306 " let wn = genutils#GetLastWinnrInStack('j') top window number in stack.
307 " let wn = genutils#GetLastWinnrInStack('k') bottom window number in stack.
309 " int genutils#GetLastWinnrInStack(char dir)
310 " -----------------------
311 " Move cursor to the next window in stack. See genutils#GetNextWinnrInStack()
312 " for more information.
314 " void genutils#MoveCursorToNextInWinStack(char dir)
315 " -----------------------
316 " Move cursor to the last window in stack. See genutils#GetLastWinnrInStack()
317 " for more information.
319 " void genutils#MoveCursorToLastInWinStack(char dir)
320 " -----------------------
321 " This function, which stands for "execute the given command that creates a
322 " window, while disabling the 'equalalways' setting", is a means for plugins
323 " to create new windows without disturbing the existing window dimensions as
324 " much as possible. This function would not be required if 'equalalways' is
325 " not set by the user. Even if set, the below code, though intuitive,
327 " let _equalalways = &equalalways
330 " let &equalalways = _equalalways
332 " The problem is that while restoring the value of equalalways, if the user
333 " originally had it set, Vim would immediately try to equalize all the
334 " window dimensions, which is exactly what we tried to avoid by setting
335 " 'noequalalways'. The function works around the problem by temporarily
336 " setting 'winfixheight' in all the existing windows and restoring them
339 " call genutils#OpenWinNoEa('sb ' pluginBuf)
341 " Note: The function doesn't catch any exceptions that are generated by the
342 " operations, so it is advisable to catch them by the caller itself.
344 " void genutils#OpenWinNoEa(String openWinCmd)
345 " -----------------------
346 " This is for the same purpose as described for genutils#OpenWinNoEa()
347 " function, except that it is used to close a given window. This is just a
348 " convenience function.
350 " void genutils#CloseWinNoEa(int winnr, boolean force)
351 " -----------------------
352 " Turn on some buffer settings that make it suitable to be a scratch buffer.
354 " void genutils#SetupScratchBuffer()
355 " -----------------------
356 " Turns off those options that are set by diff to the current window.
357 " Also removes the 'hor' option from scrollopt (which is a global option).
358 " Better alternative would be to close the window and reopen the buffer in a
361 " void genutils#CleanDiffOptions()
362 " -----------------------
363 " This function is an alternative to exists() function, for those odd array
364 " index names for which the built-in function fails. The var should be
365 " accessible to this functions, so it shouldn't be a local or script local
367 " if genutils#ArrayVarExists("array", id)
368 " let val = array{id}
371 " boolean genutils#ArrayVarExists(String varName, int index)
372 " -----------------------
373 " If lhs is already mapped, this function makes sure rhs is appended to it
374 " instead of overwriting it. If you are rhs has any script local functions,
375 " make sure you use the <SNR>\d\+_ prefix instead of the <SID> prefix (or the
376 " <SID> will be replaced by the SNR number of genutils script, instead of
378 " mapMode is used to prefix to "oremap" and used as the map command. E.g., if
379 " mapMode is 'n', then the function call results in the execution of noremap
382 " void genutils#MapAppendCascaded(String lhs, String rhs, String mapMode)
383 " -----------------------
384 " -----------------------
385 " Saves the heights and widths of the currently open windows for restoring
388 " void genutils#SaveWindowSettings()
389 " -----------------------
390 " Restores the heights of the windows from the information that is saved by
391 " genutils#SaveWindowSettings(). Works only when the number of windows
392 " haven't changed since the genutils#SaveWindowSettings is called.
394 " void genutils#RestoreWindowSettings()
395 " -----------------------
396 " Reset the previously saved window settings using genutils#SaveWindowSettings.
398 " void genutils#ResetWindowSettings()
399 " -----------------------
400 " Same as genutils#SaveWindowSettings, but uses the passed in id to create a
401 " private copy for the calling script. Pass in a unique id to avoid
402 " conflicting with other callers. If overwrite is zero and if the settings
403 " are already stored for the passed in id, it will overwrite previously
406 " void genutils#SaveWindowSettings2(String id, boolean overwrite)
407 " -----------------------
408 " Same as genutils#RestoreWindowSettings, but uses the passed in id to get the
409 " settings. The settings must have been previously saved using this
410 " id. Call genutils#ResetWindowSettings2() to explicitly reset the saved
413 " void genutils#RestoreWindowSettings2(String id)
414 " -----------------------
415 " Reset the previously saved window settings using genutils#SaveWindowSettings2.
416 " Releases the variables.
418 " void genutils#ResetWindowSettings2(String id)
419 " -----------------------
420 " -----------------------
421 " Save the current/last visual selection such that it can be later restored
422 " using genutils#RestoreVisualSelection(). Pass a unique id such that it will
423 " not interfere with the other callers to this function. Saved selections
424 " are not associated with the window so you can later restore the selection
425 " in any window, provided there are enough lines/columns.
427 " void genutils#SaveVisualSelection(String id)
428 " -----------------------
429 " Restore the visual selection that was previuosly saved using
430 " genutils#SaveVisualSelection().
432 " void genutils#RestoreVisualSelection(String id)
433 " -----------------------
434 " -----------------------
435 " This method tries to save the hard position along with the line context This
436 " is like the vim builtin marker. Pass in a unique id to avoid
437 " conflicting with other callers.
439 " void genutils#SaveSoftPosition(String id)
440 " -----------------------
441 " Restore the cursor position using the information saved by the previous call
442 " to genutils#SaveSoftPosition. This first calls
443 " genutils#RestoreHardPosition() and then searches for the original line
444 " first in the forward direction and then in the backward and positions the
445 " cursor on the line if found. If the original line is not found it still
446 " behaves like a call to genutils#RestoreHardPosition. This is similar to
447 " the functionality of the built-in marker, as Vim is capable of maintaining
448 " the marker even when the line is moved up or down. However, if there are
449 " identical lines in the buffer and the original line has moved, this
450 " function might get confused.
452 " void genutils#RestoreSoftPosition(String id)
453 " -----------------------
454 " Reset the previously cursor position using genutils#SaveSoftPosition.
455 " Releases the variables.
457 " void genutils#ResetSoftPosition(String id)
458 " -----------------------
459 " Useful when you want to go to the exact (line, col), but marking will not
460 " work, or if you simply don't want to disturb the marks. Pass in a unique
463 " void genutils#SaveHardPosition(String id)
464 " -----------------------
465 " Restore the cursor position using the information saved by the previous call
466 " to genutils#SaveHardPosition.
468 " void genutils#RestoreHardPosition(String id)
469 " -----------------------
470 " Reset the previously cursor position using genutils#SaveHardPosition.
471 " Releases the variables.
473 " void genutils#ResetHardPosition(String id)
474 " -----------------------
475 " Return the line number of the previously saved position for the id.
476 " This is like calling line() builtin function for a mark.
478 " int genutils#GetLinePosition(String id)
479 " -----------------------
480 " Return the column number of the previously saved position for the id.
481 " This is like calling col() builtin function for a mark.
483 " int genutils#GetColPosition(String id)
484 " -----------------------
485 " A convenience function to check if a position has been saved (and not reset)
486 " using the id given.
488 " boolean genutils#IsPositionSet(String id)
489 " -----------------------
490 " -----------------------
491 " Cleanup file name such that two *cleaned up* file names are easy to be
492 " compared. This probably works only on windows and unix platforms. Also
493 " recognizes UNC paths. Always returns paths with forward slashes only,
494 " irrespective of what your 'shellslash' setting is. The return path will
495 " always be a valid path for use in Vim, provided the original path itself
496 " was valid for the platform (a valid cygwin path after the cleanup will
497 " still be valid in a cygwin vim). The CleanupFileName2() variant is meant
498 " for win32, to avoid translating some backslash protections to be treated
499 " as regular path separators. Pass the characters that are protected, and
500 " the backslashes infront of them are preserved.
502 " String genutils#CleanupFileName(String fileName)
503 " String genutils#CleanupFileName2(String fileName, String win32ProtectedChars)
504 " -----------------------
505 " Returns true if the current OS is any of the Microsoft OSes. Most useful to
506 " know if the path separator is "\".
508 " boolean genutils#OnMS()
509 " -----------------------
510 " Returns true if the given path could be an absolute path. Probably works
511 " only on Unix and Windows platforms.
513 " boolean genutils#PathIsAbsolute(String path)
514 " -----------------------
515 " Returns true if the given path doesn't have any directory components.
516 " Probably works only on Unix and Windows platforms.
518 " boolean genutils#PathIsFileNameOnly(String path)
519 " -----------------------
520 " -----------------------
521 " Add a notification to know when a buffer with the given name (referred to as
522 " windowTitle) is no longer visible in any window. This by functionality is
523 " like a BufWinLeavePost event. The function functionName is called back
524 " with the title (buffer name) as an argument. The notification gets removed
525 " after excuting it, so for future notifications, you need to reregister
526 " your function. You can only have one notification for any buffer. The
527 " function should be accessible from the script's local context.
529 " void genutils#AddNotifyWindowClose(String windowTitle, String functionName)
530 " -----------------------
531 " Remove the notification previously added using genutils#AddNotifyWindowClose
534 " void genutils#RemoveNotifyWindowClose(String windowTitle)
535 " -----------------------
536 " Normally the plugin checks for closed windows for every WinEnter event, but
537 " you can force a check at anytime by calling this function.
539 " void genutils#CheckWindowClose()
540 " -----------------------
541 " -----------------------
542 " Displays the given line(s) from the current file in the command area (i.e.,
543 " echo), using that line's syntax highlighting (i.e., WYSIWYG). If no line
544 " number is given, display the current line.
546 " From: Gary Holloway "gary at castandcrew dot com"
547 " Date: Wed, 16 Jan 2002 14:31:56 -0800
549 " void genutils#ShowLinesWithSyntax() range
550 " -----------------------
551 " This function shifts the current word in the space without changing the
552 " column position of the next word. Doesn't work for tabs.
554 " void genutils#ShiftWordInSpace(int direction)
555 " -----------------------
556 " This function centers the current word in the space without changing the
557 " column position of the next word. Doesn't work for tabs.
559 " void genutils#CenterWordInSpace()
560 " -----------------------
561 " -----------------------
562 " Find common path component of two filenames.
563 " Based on the thread, "computing relative path".
564 " Date: Mon, 29 Jul 2002 21:30:56 +0200 (CEST)
565 " The last two arguments are optional and default to 0 (false), but you can
566 " pass a value of 1 (true) to indicate that the path represents a directory.
568 " genutils#CommonPath('/a/b/c/d.e', '/a/b/f/g/h.i') => '/a/b/'
569 " genutils#CommonPath('/a/b/c/d.e', '/a/b/') => '/a/b'
570 " genutils#CommonPath('/a/b/c/d.e', '/a/b/', 0, 1) => '/a/b/'
572 " String genutils#CommonPath(String path1, String path2 [, boolean path1IsDir, boolean path2IsDir])
573 " -----------------------
574 " Find common string component of two strings.
575 " Based on the tread, "computing relative path".
576 " Date: Mon, 29 Jul 2002 21:30:56 +0200 (CEST)
578 " genutils#CommonString('abcde', 'abfghi') => 'ab'
580 " String genutils#CommonString(String str1, String str2)
581 " -----------------------
582 " Find the relative path of tgtFile from the directory of srcFile.
583 " Based on the tread, "computing relative path".
584 " Date: Mon, 29 Jul 2002 21:30:56 +0200 (CEST)
586 " genutils#RelPathFromFile('/a/b/c/d.html', '/a/b/e/f.html') => '../f/g.html'
588 " String genutils#RelPathFromFile(String srcFile, String tgtFile)
589 " -----------------------
590 " Find the relative path of tgtFile from the srcDir.
591 " Based on the tread, "computing relative path".
592 " Date: Mon, 29 Jul 2002 21:30:56 +0200 (CEST)
594 " genutils#RelPathFromDir('/a/b/c/d', '/a/b/e/f/g.html') => '../../e/f/g.html'
596 " String genutils#RelPathFromDir(String srcDir, String tgtFile)
597 " -----------------------
598 " -----------------------
599 " Convert Roman numerals to decimal. Doesn't detect format errors.
601 " From: "Preben Peppe Guldberg" <c928400@student.dtu.dk>
602 " Date: Fri, 10 May 2002 14:28:19 +0200
604 " String genutils#Roman2Decimal(String str)
605 " -----------------------
606 " -----------------------
607 " Works like the built-in escape(), except that it escapes the specified
608 " characters only if they are not already escaped, so something like
609 " genutils#Escape('a\bc\\bd', 'b') would give 'a\bc\\\bd'. The chars value
610 " directly goes into the [] collection, so it can be anything that is
613 " String genutils#Escape(String str, String chars)
614 " -----------------------
615 " Works like the reverse of the builtin escape() function, but un-escapes the
616 " specified characters only if they are already escaped (essentially the
617 " opposite of genutils#Escape()). The chars value directly goes into the []
618 " collection, so it can be anything that is acceptable to [].
620 " String genutils#UnEscape(String str, String chars)
621 " -----------------------
622 " Works like the reverse of the built-in escape() function. De-escapes all the
623 " escaped characters. Essentially removes one level of escaping from the
624 " string, so something like: 'a\b\\\\c\\d' would become 'ab\\c\d'.
626 " String genutils#DeEscape(String str)
627 " -----------------------
628 " This function creates a pattern that avoids the given protected characters'
629 " from getting treated as separators, when used with split(). The argument
630 " goes directly into the [] atom, so make sure you pass in a valid string.
631 " When optional argument capture is true, the characters are placed in a
634 " let paths = split(&path, genutils#CrUnProtectedCharsPattern(','))
636 " String genutils#CrUnProtectedCharsPattern(String chars, [boolean capture = false])
637 " -----------------------
638 " genutils#Escape the passed in shell command with quotes and backslashes such
639 " a way that the arguments reach the command literally (avoids shell
640 " interpretations). See the function header for the kind of escapings that
641 " are done. The first argument is the actual command name, the second
642 " argument is the arguments to the command and third argument is any pipe
643 " command that should be appended to the command. The reason the function
644 " requires them to be passed separately is that the escaping is minimized
645 " for the first and third arguments. It is preferable to pass args as a Vim7
646 " List, but it can be passed as a single string with spaces separating the
647 " arguments (spaces in side each argument then needs to be protected)
649 " let fullCmd = genutils#EscapeCommand('ls', ['-u', expand('%:h')], ['|', 'grep', 'xxx'])
651 " If the escaped command is used on Vim command-line (such as with ":w !",
652 " ":r !" and ":!"), you need to further protect '%', '#' and '!' chars,
653 " even if they are in quotes, to avoid getting expanded by Vim before
654 " invoking external cmd. However this is not required for using it with
655 " system() function. The easiest way to escape them is by using the
656 " genutils#Escape() function as in "Escape(fullCmd, '%#!')".
657 " String genutils#EscapeCommand(String cmd, List/String args, List/String pipe)
658 " -----------------------
659 " Returns the global ST_* constants (g:ST_WIN_CMD, g:ST_WIN_SH, g:ST_UNIX)
660 " based on the values of shell related settings and the OS on which Vim is
663 " int genutils#GetShellEnvType()
664 " -----------------------
666 " Expands the string for the special characters. The return value should
667 " essentially be what you would see if it was a string constant with
670 " genutils#ExpandStr('a\tA') => 'a A'
671 " String genutils#ExpandStr(String str)
672 " -----------------------
673 " Quotes the passed in string such that it can be used as a string expression
674 " in :execute. It sorrounds the passed in string with single-quotes while
675 " escaping any existing single-quotes in the string.
677 " String genutils#QuoteStr(String str)
678 " -----------------------
679 " -----------------------
680 " Returns true if the current line has a sign placed.
682 " boolean genutils#CurLineHasSign()
683 " -----------------------
684 " Clears all signs in the current buffer.
686 " void genutils#ClearAllSigns()
687 " -----------------------
688 " -----------------------
689 " This function is suitable to be used by custom command completion functions
690 " for expanding filenames conditionally. The function could based on the
691 " context, decide whether to do a file completion or a different custom
692 " completion. See breakpts.vim and perforce.vim for examples.
693 " If you pass non-zero value to smartSlash, the function decides to use
694 " backslash or forwardslash as the path separator based on the user settings
695 " and the ArgLead, but if you always want to use only forwardslash as the
696 " path separator, then pass 0. If you pass in a comma separated list of
697 " directories as searchPath, then the file expansion is limited to the files
698 " under these directories. This means, you can implement your own commands
699 " that don't expect the user to type in the full path name to the file
700 " (e.g., if the user types in the command while in the explorer window, you
701 " could assume that the path is relative to the directory being viewed). Most
702 " useful with a single directory, but also useful in combination with vim
703 " 'runtimepath' in loading scripts etc. (see Runtime command in
706 " String genutils#UserFileComplete(String ArgLead, String CmdLine, String
707 " CursorPos, String smartSlash, String searchPath)
708 " -----------------------
709 " This is a convenience function to expand filename meta-sequences in the
710 " given arguments just as Vim would have if given to a user-defined command
711 " as arguments with completion mode set to "file". Useful
712 " if you set the completion mode of your command to anything
713 " other than the "file", and later conditionally expand arguments (for
714 " characters such as % and # and other sequences such as #10 and <cword>)
715 " after deciding which arguments represent filenames/patterns.
717 " String genutils#UserFileExpand(String fileArgs)
718 " -----------------------
719 " This returns the output of the vim command as a string, without corrupting
720 " any registers. Returns empty string on errors. Check for v:errmsg after
721 " calling this function for any error messages.
723 " String genutils#GetVimCmdOutput(String cmd)
724 " -----------------------
725 " Clear the contents of the current buffer in an optimum manner. For plugins
726 " that keep redrawing the contents of its buffer, executing "1,$d" or its
727 " equivalents result in overloading Vim's undo mechanism. Using this function
728 " avoids that problem.
730 " void genutils#OptClearBuffer()
731 " -----------------------
732 " Returns the window number of the preview window if open or -1 if not.
733 " int genutils#GetPreviewWinnr()
734 " -----------------------
735 " -----------------------
736 " These functions provide a persistent storage mechanism.
738 " Example: Put the following in a file called t.vim in your plugin
739 " directory and watch the magic. You can set new value using SetVar() and
740 " see that it returns the same value across session when GetVar() is
743 " au VimEnter * call LoadSettings()
744 " au VimLeavePre * call SaveSettings()
746 " function! LoadSettings()
747 " let s:tVar = genutils#GetPersistentVar("T", "tVar", "defVal")
750 " function! SaveSettings()
751 " call genutils#PutPersistentVar("T", "tVar", s:tVar)
754 " function! SetVar(val)
763 " The pluginName and persistentVar have to be unique and are case insensitive.
764 " Ideally called from your VimLeavePre autocommand handler of your plugin.
765 " This simply creates a global variable which will be persisted by Vim
766 " through viminfo. The variable can be read back in the next session by the
767 " plugin using genutils#GetPersistentVar() function, ideally from your
768 " VimEnter autocommand handler. The pluginName is to provide a name space
769 " for different plugins, and avoid conflicts in using the same persistentVar
771 " This feature uses the '!' option of viminfo, to avoid storing all the
772 " temporary and other plugin specific global variables getting saved.
774 " void genutils#PutPersistentVar(String pluginName, String persistentVar,
776 " -----------------------
777 " Ideally called from VimEnter, this simply reads the value of the global
778 " variable for the persistentVar that is saved in the viminfo in a previous
779 " session using genutils#PutPersistentVar() and returns it (and default if
780 " the variable is not found). It removes the variable from global space
781 " before returning the value, so can be called only once. It also means that
782 " genutils#PutPersistentVar should be called again in the next VimLeavePre
783 " if the variable continues to be persisted.
785 " void genutils#GetPersistentVar(String pluginName, String persistentVar,
787 " -----------------------
788 " -----------------------
789 " These functions channel the FileChangedShell autocommand and extend it to
790 " create an additional fictitious FileChangedShellPre and FileChangedShellPost
793 " Add the given noarg function to the list of functions that need to be
794 " notified before processing the FileChangedShell event. The function when
795 " called can expand "<abuf>" or "<afile>" to get the details of the buffer
796 " for which this autocommand got executed. It should return 0 to mean
797 " noautoread and 1 to mean autoread the current buffer. It can also return
798 " -1 to make its return value ignored and use default autoread mechanism
799 " (which could still be overridden by the return value of other functions).
800 " The return value of all the functions is ORed to determine the effective
803 " void genutils#AddToFCShellPre(String funcName)
804 " -----------------------
805 " Remove the given function previously added by calling
806 " genutils#AddToFCShellPre.
808 " void genutils#RemoveFromFCShellPre(String funcName)
809 " -----------------------
810 " Same as genutils#AddToFCShellPre except that the function is called after
811 " the event is processed, so this is like a fictitious FileChangedShellPost
814 " void genutils#DefFCShellInstall()
815 " -----------------------
816 " Uninstall the default autocommand handler that was previously installed
817 " using genutils#DefFCShellInstall. Calling this function may not actually
818 " result in removing the handler, in case there are other callers still
819 " dependent on it (which is kept track of by the number of times
820 " genutils#DefFCShellInstall has been called).
822 " void genutils#DefFCShellUninstall()
823 " -----------------------
824 " This function emulates the Vim's default behavior when a |timestamp| change
825 " is detected. Register your functions by calling genutils#AddToFCShellPre
826 " and have this function called during the FileChangedShell event (or just
827 " install the default handler by calling genutils#DefFCShellInstall). From
828 " your callbacks, return 1 to mean autoread, 0 to mean noautoread and -1 to
829 " mean system default (or ignore). The return value of this method is 1 if
830 " the file was reloaded and 0 otherwise. The return value of all the
831 " functions is ORed to determine the effective autoread value. See my
832 " perforce plugin for usage example.
834 " boolean genutils#DefFileChangedShell()
835 " -----------------------
836 " Execute a substitute command silently and without corrupting the search
837 " register. It also preserves the cursor position.
839 " To insert a tab infrontof all lines:
840 " call genutils#SilentSubstitute('^', '%s//\t/e')
841 " To remote all carriage returns at the line ending:
842 " call genutils#SilentSubstitute("\<CR>$", '%s///e')
844 " void genutils#SilentSubstitute(String pat, String cmd)
845 " -----------------------
846 " Delete all lines matching the given pattern silently and without corrupting
847 " the search register. The range argument if passed should be a valid prefix
848 " for the :global command. It also preserves the cursor position.
850 " To delete all lines that are empty:
851 " call genutils#SilentDelete('^\s*$')
852 " To delete all lines that are empty only in the range 10 to 100:
853 " call genutils#SilentDelete('10,100', '^\s*$')
855 " void genutils#SilentDelete(String pat)
856 " void genutils#SilentDelete(String range, String pat)
857 " -----------------------
858 " Can return a spacer from 0 to 80 characters width.
860 " String genutils#GetSpacer(int width)
861 " -----------------------
862 " Function to prompt user for an element out of the passed in array. The
863 " user will be prompted with a list of choices to make. The elements will be
864 " formatted in to the given number of columns. Each element will be given a
865 " number that the user can enter to indicate the selection. This is very
866 " much like the inputlist() method, but better for a large number of options
867 " formatted into multiple columns (instead of one per row). However, if the
868 " formatted options run for multiple pages, no special handling is done.
870 " default - The default value for the selection. Default can be the
871 " element-index or the element itself. If number (type() returns
872 " 0), it is treated as an index.
873 " msg - The message that should appear in the prompt (passed to input()).
874 " skip - The element that needs to be skipped from selection (pass a
875 " non-existent element to disable this, such as an empty value '').
876 " useDialog - if true, uses dialogs for prompts, instead of the command-line(
877 " inputdialog() instead of input()). But personally, I don't
878 " like this because the power user then can't use the
879 " expression register.
880 " nCols - Number of columns to use for formatting the options. Using "1"
881 " will make the output look very like that of inputlist()
883 " the selected element or empty string, "" if nothing is selected. Call
884 " genutils#GetSelectedIndex() for the index entered by the user.
887 " echo genutils#PromptForElement(map(range(0,25),
888 " \ "nr2char(char2nr('a')+v:val)") , 'd', 'Enter: ', 'x', 1, 5)
889 " String genutils#PromptForElement(List array,
890 " [String defaultValue | int defaultIndex], String msg,
891 " String skip, boolean useDialog, int nCols)
893 " Returns the index of the element selected by the user in the previous
894 " genutils#PromptForElement call. Returns -1 when the user didn't select
895 " any element (aborted the selection). This function is useful if there are
896 " empty or duplicate elements in the selection.
897 " int genutils#GetSelectedIndex()
898 " -----------------------
900 " - CleanDiffOptions() is deprecated as Vim now has the :diffoff command.
901 " - MakeArgumentString, MakeArgumentList and CreateArgString are deprecated.
902 " Vim7 now includes call() function to receive and pass argument lists
904 " - The g:makeArgumentString and g:makeArgumentList are obsolete and are
905 " deprecated, please use MakeArgumentString() and MakeArgumentList()
907 " - FindWindowForBuffer() function is now deprecated, as the corresponding
908 " Vim bugs are fixed. Use the below expr instead:
909 " bufwinnr(genutils#FindBufferForName(fileName))
910 " - QSort(), QSort2(), BinInsertSort() and BinInsertSort2() functions are
911 " now deprecated in favor of sort() function.
914 " Sample Usages Or Tips:
915 " - Add the following commands to create simple sort commands.
916 " command! -nargs=0 -range=% SortByLength <line1>,<line2>call
917 " \ genutils#QSort('genutils#CmpByLineLengthNname', 1)
918 " command! -nargs=0 -range=% RSortByLength <line1>,<line2>call
919 " \ genutils#QSort('genutils#CmpByLineLengthNname', -1)
920 " command! -nargs=0 -range=% SortJavaImports <line1>,<line2>call
921 " \ genutils#QSort('genutils#CmpJavaImports', 1)
923 " - You might like the following mappings to adjust spacing:
924 " nnoremap <silent> <C-Space> :call genutils#ShiftWordInSpace(1)<CR>
925 " nnoremap <silent> <C-BS> :call genutils#ShiftWordInSpace(-1)<CR>
926 " nnoremap <silent> \cw :call genutils#CenterWordInSpace()<CR>
927 " nnoremap <silent> \va :call
928 " \ genutils#AlignWordWithWordInPreviousLine()<CR>
930 " - The :find command is very useful to search for a file in path, but it
931 " doesn't support file completion. Add the following command in your vimrc
932 " to add this functionality:
933 " command! -nargs=1 -bang -complete=custom,<SID>PathComplete FindInPath
934 " \ :find<bang> <args>
935 " function! s:PathComplete(ArgLead, CmdLine, CursorPos)
936 " return genutils#UserFileComplete(a:ArgLead, a:CmdLine, a:CursorPos, 1,
940 " - If you are running commands that generate multiple pages of output, you
941 " might find it useful to redirect the output to a new buffer. Put the
942 " following command in your vimrc:
943 " command! -nargs=* -complete=command Redir
944 " \ :new | put! =genutils#GetVimCmdOutput('<args>') |
945 " \ setl bufhidden=wipe | setl nomodified
948 " - Fixed some corner cases in RelPathFromDir()/RelPathFromFile().
949 " - Made the default comparators sort() function friendly.
951 " - SilentSubstitute() and SilentDelete() should preserve cursor position.
952 " - CleanupFileName() should also remove any leading or trailing whitespace.
954 " - EscapeCommand() now supports Lists as arguments.
955 " - CrUnProtectedCharsPattern() now accepts an optional "capture" argument.
956 " - Renamed PromptForElement2 to PromptForElement. It was a typo.
958 " - Fixed a typo in AddNotifyWindowClose() in the previous release.
959 " - Added BinSearchList() function.
961 " - Converted to Vim7 autoload script. Since there is no common prefix to
962 " find all the usages of genutils functions in your script, Use the
963 " pattern \<\(:\|>\|#\)\@<!\zs\u\w\+( to find all the global functions and
964 " prefix the ones from genutils with genutils#.
965 " - The new version is not backwards compatible with prior versions. If you
966 " have plugins that depend on the older versions of genutils, you should try
967 " to request the author to port their plugin to use the new genutils. If
968 " having them to coexist is a must, then use the below trick:
969 " - Install the latest version of genutils first. Overwriting all existing
971 " - Open the plugin/genutils.vim file and note the value set to
972 " loaded_genutils variable.
973 " - Install the older version of genutils (non autoload version) in to
974 " plugin directory, overwriting the existing file.
975 " - Open the plugin/genutils.vim again and change the value of
976 " loaded_genutils variable to the value you noted before and save it.
977 " - Fix for Save/RestoreHardPosition() not working right when there are
978 " wrapped lines in the window.
979 " - Dropped the AddToFCShell and RemoveFromFCShell functions as these can't be
980 " implemented in Vim7 because of new restrictions on FileChangedShell
981 " autocommand. Use AddToFcShellPre and RemoveFromFCShellPre functions
983 " - No longer depends on multvals plugin. Inherits some useful functions from
984 " multvals to make way for it to be retired. New functions are:
985 " genutils#CrUnProtectedCharsPattern
986 " PromptForElement/GetSelectedIndex
988 if exists('loaded_genutils')
992 "echomsg 'genutils: You need at least Vim 7.0'
996 let loaded_genutils = 204