From d56a49f5b4d1eaf228007db86963cee2cebf1f78 Mon Sep 17 00:00:00 2001 From: huhuaishun Date: Tue, 18 Apr 2017 13:13:51 +0800 Subject: [PATCH] add vim-session --- sources_non_forked/vim-misc/.gitignore | 1 + sources_non_forked/vim-misc/INSTALL.md | 13 + sources_non_forked/vim-misc/README.md | 1015 ++++++++++++++ sources_non_forked/vim-misc/addon-info.json | 1 + .../vim-misc/autoload/xolox/misc.vim | 7 + .../vim-misc/autoload/xolox/misc/async.vim | 261 ++++ .../vim-misc/autoload/xolox/misc/buffer.vim | 80 ++ .../vim-misc/autoload/xolox/misc/complete.vim | 26 + .../autoload/xolox/misc/cursorhold.vim | 71 + .../vim-misc/autoload/xolox/misc/echo.exe | Bin 0 -> 7680 bytes .../vim-misc/autoload/xolox/misc/escape.vim | 56 + .../vim-misc/autoload/xolox/misc/format.vim | 46 + .../vim-misc/autoload/xolox/misc/list.vim | 42 + .../vim-misc/autoload/xolox/misc/msg.vim | 129 ++ .../vim-misc/autoload/xolox/misc/open.vim | 100 ++ .../vim-misc/autoload/xolox/misc/option.vim | 116 ++ .../vim-misc/autoload/xolox/misc/os.vim | 284 ++++ .../vim-misc/autoload/xolox/misc/path.vim | 278 ++++ .../vim-misc/autoload/xolox/misc/perm.vim | 100 ++ .../vim-misc/autoload/xolox/misc/persist.vim | 50 + .../vim-misc/autoload/xolox/misc/str.vim | 74 + .../vim-misc/autoload/xolox/misc/test.vim | 125 ++ .../vim-misc/autoload/xolox/misc/tests.vim | 301 +++++ .../vim-misc/autoload/xolox/misc/timer.vim | 130 ++ .../vim-misc/autoload/xolox/misc/version.vim | 34 + sources_non_forked/vim-misc/doc/misc.txt | 1204 +++++++++++++++++ .../vim-misc/plugin/xolox/misc.vim | 19 + .../vim-session-master/.gitignore | 1 + .../vim-session-master/INSTALL.md | 15 + .../vim-session-master/README.md | 646 +++++++++ sources_non_forked/vim-session-master/TODO.md | 5 + .../vim-session-master/addon-info.json | 1 + .../autoload/xolox/session.vim | 1158 ++++++++++++++++ .../autoload/xolox/session/suggestions.vim | 42 + .../vim-session-master/doc/session.txt | 960 +++++++++++++ .../vim-session-master/plugin/session.vim | 205 +++ .../screenshots/session-restore-prompt.png | Bin 0 -> 22330 bytes .../screenshots/session-save-prompt.png | Bin 0 -> 23303 bytes vimrcs/plugins_config.vim | 7 + 39 files changed, 7603 insertions(+) create mode 100755 sources_non_forked/vim-misc/.gitignore create mode 100755 sources_non_forked/vim-misc/INSTALL.md create mode 100755 sources_non_forked/vim-misc/README.md create mode 100755 sources_non_forked/vim-misc/addon-info.json create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/async.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/buffer.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/complete.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/cursorhold.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/echo.exe create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/escape.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/format.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/list.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/msg.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/open.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/option.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/os.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/path.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/perm.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/persist.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/str.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/test.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/tests.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/timer.vim create mode 100755 sources_non_forked/vim-misc/autoload/xolox/misc/version.vim create mode 100755 sources_non_forked/vim-misc/doc/misc.txt create mode 100755 sources_non_forked/vim-misc/plugin/xolox/misc.vim create mode 100755 sources_non_forked/vim-session-master/.gitignore create mode 100755 sources_non_forked/vim-session-master/INSTALL.md create mode 100755 sources_non_forked/vim-session-master/README.md create mode 100755 sources_non_forked/vim-session-master/TODO.md create mode 100755 sources_non_forked/vim-session-master/addon-info.json create mode 100755 sources_non_forked/vim-session-master/autoload/xolox/session.vim create mode 100755 sources_non_forked/vim-session-master/autoload/xolox/session/suggestions.vim create mode 100755 sources_non_forked/vim-session-master/doc/session.txt create mode 100755 sources_non_forked/vim-session-master/plugin/session.vim create mode 100755 sources_non_forked/vim-session-master/screenshots/session-restore-prompt.png create mode 100755 sources_non_forked/vim-session-master/screenshots/session-save-prompt.png diff --git a/sources_non_forked/vim-misc/.gitignore b/sources_non_forked/vim-misc/.gitignore new file mode 100755 index 00000000..926ccaaf --- /dev/null +++ b/sources_non_forked/vim-misc/.gitignore @@ -0,0 +1 @@ +doc/tags diff --git a/sources_non_forked/vim-misc/INSTALL.md b/sources_non_forked/vim-misc/INSTALL.md new file mode 100755 index 00000000..2020f3db --- /dev/null +++ b/sources_non_forked/vim-misc/INSTALL.md @@ -0,0 +1,13 @@ +# Installation instructions + +There are two ways to install the vim-misc plug-in and it's up to you which you prefer, both options are explained below. Please note that below are generic installation instructions while some Vim plug-ins may have external dependencies, please refer to the plug-in's [readme](README.md) for details. + +## Installation using a ZIP archive + +Unzip the most recent ZIP archive of the [vim-misc](http://peterodding.com/code/vim/downloads/misc.zip) plug-in inside your Vim profile directory (usually this is `~/.vim` on UNIX and `%USERPROFILE%\vimfiles` on Windows), restart Vim and execute the command `:helptags ~/.vim/doc` (use `:helptags ~\vimfiles\doc` instead on Windows). + +If you get warnings about overwriting existing files while unpacking the ZIP archive you probably don't need to worry about this because it's most likely caused by files like `README.md`, `INSTALL.md` and `addon-info.json`. If these files bother you then you can remove them after unpacking the ZIP archive, they are not required to use the plug-in. + +## Installation using a Vim plug-in manager + +If you prefer you can also use [Pathogen](http://www.vim.org/scripts/script.php?script_id=2332), [Vundle](https://github.com/gmarik/vundle) or a similar tool to install and update the [vim-misc](https://github.com/xolox/vim-misc) plug-in using a local clone of the git repository. This takes a bit of work to set up the first time but it makes updating much easier, and it keeps each plug-in in its own directory which helps to keep your Vim profile uncluttered. diff --git a/sources_non_forked/vim-misc/README.md b/sources_non_forked/vim-misc/README.md new file mode 100755 index 00000000..937d7c91 --- /dev/null +++ b/sources_non_forked/vim-misc/README.md @@ -0,0 +1,1015 @@ +# Miscellaneous auto-load Vim scripts + +The vim-misc plug-in contains Vim scripts that are used by most of the [Vim +plug-ins I've written] [plugins] yet don't really belong with any single one of +the plug-ins. Basically it's an extended standard library of Vim script +functions that I wrote during the development of my Vim profile and plug-ins. + +In the past these scripts were bundled with each plug-in, however that turned +out to be a maintenance nightmare for me. That's why the miscellaneous scripts +are now a proper plug-in with their own page on Vim Online. + +Because the miscellaneous scripts are no longer bundled with my Vim plug-ins, +users are now required to install the miscellaneous scripts separately. This is +unfortunate for users who are upgrading from a previous release that did bundle +the miscellaneous scripts, but I don't see any way around this. Sorry! + +## Installation + +Please refer to the [installation instructions] [howto-install] on GitHub. + +## Function documentation + +Below is the documentation for the functions included in the miscellaneous +scripts. Anyone is free to use these functions in their own Vim profile and/or +plug-ins. I care about backwards compatibility so won't break it without a good +reason to do so. + +For those who are curious: The function descriptions given below were extracted +from the source code of the miscellaneous scripts using the Python module +`vimdoctool.py` included in [vim-tools] []. + + + +The documentation of the 95 functions below was extracted from +19 Vim scripts on April 1, 2015 at 23:39. + +### Asynchronous Vim script evaluation + +The `xolox#misc#async#call()` function builds on top of `xolox#misc#os#exec()` +to support asynchronous evaluation of Vim scripts. The first (and for now +only) use case is my [vim-easytags][] plug-in which has a bunch of +conflicting requirements: + +1. I want the [vim-easytags][] plug-in to be as portable as possible. + Ideally everything is implemented in Vim script because that's the only + thing I can rely on to be available for all potential users of the + plug-in! + +2. Because of point one I've been forced to implement tags file reading, + parsing, (fold case) sorting and writing in Vim script. This is fine for + small tags files but once they grow to a couple of megabytes it becomes + annoying because Vim is unresponsive during tags file updates (key + presses are fortunately buffered due to Vim's input model but that + doesn't make it a nice user experience :-). + +3. I could (and did in the past) come up with all sorts of hacks to speed + things up without switching away from Vim script, but none of them are + going to solve the fundamental problem that Vim's unresponsive hiccups + become longer as tags files grow larger. + +By now it should be clear where this is heading: _Why not handle tags file +updates in a Vim process that runs in the background without blocking the +Vim process that the user is interacting with?_ It turns out that there are +quite a few details to take care of, but with those out of the way, it might +just work! I'm actually hoping to make asynchronous updates the default mode +in [vim-easytags][]. This means I need this functionality to be as +portable and robust as possible. + +**Status:** This code has seen little testing so I wouldn't trust it too +much just yet. On the other hand, as I said, my intention is to make this +functionality as portable and robust as possible. You be the judge :-). + +[vim-easytags]: http://peterodding.com/code/vim/easytags/ + +#### The `xolox#misc#async#call()` function + +Call a Vim script function asynchronously by starting a hidden Vim process +in the background. Once the function returns the hidden Vim process +terminates itself. This function takes a single argument which is a +dictionary with the following key/value pairs: + + - **function** (required): The name of the Vim function to call inside + the child process (a string). I suggest using an [autoload][] function + for this, see below. + + - **arguments** (optional): A list of arguments to pass to the function. + This list is serialized to a string using [string()][] and deserialized + using [eval()][]. + + - **callback** (optional): The name of a Vim function to call in the + parent process when the child process has completed (a string). + + - **clientserver** (optional): If this is true (1) the child process will + notify the parent process when it has finished (the default is true). + This works using Vim's client/server support which is not always + available. As a fall back Vim's [CursorHold][] automatic command is + also supported (although the effect is not quite as instantaneous :-). + +This functionality is experimental and non trivial to use, so consider +yourself warned :-). + +**Limitations** + +I'm making this functionality available in [vim-misc][] because I think it +can be useful to other plug-ins, however if you are going to use it you +should be aware of the following limitations: + + - Because of the use of multiple processes this functionality is only + suitable for 'heavy' tasks. + + - The function arguments are serialized to a string which is passed to + the hidden Vim process as a command line argument, so the amount of + data you can pass will be limited by your operating environment. + + - The hidden Vim process is explicitly isolated from the user in several + ways (see below for more details). This is to make sure that the hidden + Vim processes are fast and don't clobber the user's editing sessions in + any way. + +**Changes to how Vim normally works** + +You have to be aware that the hidden Vim process is initialized in a +specific way that is very different from your regular Vim editing +sessions: + + - Your [vimrc][] file is ignored using the `-u NONE` command line option. + + - Your [gvimrc][] file (if you even knew it existed ;-) is ignored using + the `-U NONE` command line option. + + - Plug-in loading is skipped using the `--noplugin` command line option. + + - Swap files (see [swap-file][]) are disabled using the `-n` command line + option. This makes sure asynchronous Vim processes don't disturb the + user's editing session. + + - Your [viminfo][] file is ignored using the `-i NONE` command line + option. Just like with swap files this makes sure asynchronous Vim + processes don't disturb the user's editing session. + + - No-compatible mode is enabled using the `-N` command line option + (usually the existence of your vimrc script would have achieved the + same effect but since we disable loading of your vimrc we need to spell + things out for Vim). + +**Use an auto-load function** + +The function you want to call is identified by its name which has to be +defined, but I just explained above that all regular initialization is +disabled for asynchronous Vim processes, so what gives? The answer is to +use an [autoload][] function. This should work fine because the +asynchronous Vim process 'inherits' the value of the ['runtimepath'][] +option from your editing session. + +['runtimepath']: http://vimdoc.sourceforge.net/htmldoc/options.html#'runtimepath' +[autoload]: http://vimdoc.sourceforge.net/htmldoc/eval.html#autoload +[CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold +[eval()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#eval() +[gvimrc]: http://vimdoc.sourceforge.net/htmldoc/gui.html#gvimrc +[string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string() +[swap-file]: http://vimdoc.sourceforge.net/htmldoc/recover.html#swap-file +[vim-misc]: http://peterodding.com/code/vim/misc/ +[viminfo]: http://vimdoc.sourceforge.net/htmldoc/starting.html#viminfo +[vimrc]: http://vimdoc.sourceforge.net/htmldoc/starting.html#vimrc + +#### The `xolox#misc#async#inside_child()` function + +Entry point inside the hidden Vim process that runs in the background. +Invoked indirectly by `xolox#misc#async#call()` because it runs a command +similar to the following: + + vim --cmd 'call xolox#misc#async#inside_child(...)' + +This function is responsible for calling the user defined function, +capturing exceptions and reporting the results back to the parent Vim +process using Vim's client/server support or a temporary file. + +#### The `xolox#misc#async#callback_to_parent()` function + +When Vim was compiled with client/server support this function (in the +parent process) will be called by `xolox#misc#async#inside_child()` (in +the child process) after the user defined function has returned. This +enables more or less instant callbacks after running an asynchronous +function. + +#### The `xolox#misc#async#periodic_callback()` function + +When client/server support is not being used the vim-misc plug-in +improvises: It uses Vim's [CursorHold][] event to periodically check if an +asynchronous process has written its results to one of the expected +temporary files. If a response is found the temporary file is read and +deleted and then `xolox#misc#async#callback_to_parent()` is called to +process the response. + +[CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold + +### Handling of special buffers + +The functions defined here make it easier to deal with special Vim buffers +that contain text generated by a Vim plug-in. For example my [vim-notes +plug-in] [vim-notes] generates several such buffers: + +- [:RecentNotes] [RecentNotes] lists recently modified notes +- [:ShowTaggedNotes] [ShowTaggedNotes] lists notes grouped by tags +- etc. + +Because the text in these buffers is generated, Vim shouldn't bother with +swap files and it should never prompt the user whether to save changes to +the generated text. + +[vim-notes]: http://peterodding.com/code/vim/notes/ +[RecentNotes]: http://peterodding.com/code/vim/notes/#recentnotes_command +[ShowTaggedNotes]: http://peterodding.com/code/vim/notes/#showtaggednotes_command + +#### The `xolox#misc#buffer#is_empty()` function + +Checks if the current buffer is an empty, unchanged buffer which can be +reused. Returns 1 if an empty buffer is found, 0 otherwise. + +#### The `xolox#misc#buffer#prepare()` function + +Open a special buffer, i.e. a buffer that will hold generated contents, +not directly edited by the user. The buffer can be customized by passing a +dictionary with the following key/value pairs as the first argument: + +- **name** (required): The base name of the buffer (i.e. the base name of + the file loaded in the buffer, even though it isn't really a file and + nothing is really 'loaded' :-) +- **path** (required): The pathname of the buffer. May be relevant if + [:lcd] [lcd] or ['autochdir'] [acd] is being used. + +[lcd]: http://vimdoc.sourceforge.net/htmldoc/editing.html#:lcd +[acd]: http://vimdoc.sourceforge.net/htmldoc/options.html#'autochdir' + +#### The `xolox#misc#buffer#lock()` function + +Lock a special buffer so that its contents can no longer be edited. + +#### The `xolox#misc#buffer#unlock()` function + +Unlock a special buffer so that its content can be updated. + +### Tab completion for user defined commands + +#### The `xolox#misc#complete#keywords()` function + +This function can be used to perform keyword completion for user defined +Vim commands based on the contents of the current buffer. Here's an +example of how you would use it: + + :command -nargs=* -complete=customlist,xolox#misc#complete#keywords MyCmd call s:MyCmd() + +### Rate limiting for Vim's CursorHold event + +Several of my Vim plug-ins (e.g. [vim-easytags][], [vim-notes][] and +[vim-session][]) use Vim's [CursorHold][] and [CursorHoldI][] events to +perform periodic tasks when the user doesn't press any keys for a couple of +seconds. These events by default fire after four seconds, this is +configurable using Vim's ['updatetime'][] option. The problem that this +script solves is that there are Vim plug-ins which set the ['updatetime'][] +option to unreasonably low values, thereby breaking my Vim plug-ins and +probably a lot of other Vim plug-ins out there. When users complain about +this I can tell them that another Vim plug-in is to blame, but users don't +care for the difference, their Vim is broken! So I implemented a workaround. +This script enables registration of [CursorHold][] event handlers with a +configurable interval (expressed in seconds). The event handlers will be +called no more than once every interval. + +['updatetime']: http://vimdoc.sourceforge.net/htmldoc/options.html#'updatetime' +[CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold +[CursorHoldI]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHoldI +[vim-easytags]: http://peterodding.com/code/vim/easytags/ +[vim-notes]: http://peterodding.com/code/vim/notes/ +[vim-session]: http://peterodding.com/code/vim/session/ + +#### The `xolox#misc#cursorhold#register()` function + +Register a [CursorHold][] event handler with a custom interval. This +function takes a single argument which is a dictionary with the following +fields: + + - **function** (required): The name of the event handler function (a + string). + + - **arguments** (optional): A list of arguments to pass to the event + handler function (defaults to an empty list). + + - **interval** (optional): The number of seconds between calls to the + event handler (defaults to 4). + +#### The `xolox#misc#cursorhold#autocmd()` function + +The 'top level event handler' that's called by Vim whenever the +[CursorHold][] or [CursorHoldI][] event fires. It iterates through the +event handlers registered using `xolox#misc#cursorhold#register()` and +calls each event handler at the appropriate interval, keeping track of +the time when each event handler was last run. + +### String escaping functions + +#### The `xolox#misc#escape#pattern()` function + +Takes a single string argument and converts it into a [:substitute] +[subcmd] / [substitute()] [subfun] pattern string that matches the given +string literally. + +[subfun]: http://vimdoc.sourceforge.net/htmldoc/eval.html#substitute() +[subcmd]: http://vimdoc.sourceforge.net/htmldoc/change.html#:substitute + +#### The `xolox#misc#escape#substitute()` function + +Takes a single string argument and converts it into a [:substitute] +[subcmd] / [substitute()] [subfun] replacement string that inserts the +given string literally. + +#### The `xolox#misc#escape#shell()` function + +Takes a single string argument and converts it into a quoted command line +argument. + +I was going to add a long rant here about Vim's ['shellslash' option] +[shellslash], but really, it won't make any difference. Let's just suffice +to say that I have yet to encounter a single person out there who uses +this option for its intended purpose (running a UNIX style shell on +Microsoft Windows). + +[shellslash]: http://vimdoc.sourceforge.net/htmldoc/options.html#'shellslash' + +### Human friendly string formatting for Vim + +#### The `xolox#misc#format#pluralize()` function + +Concatenate a counter (the first argument, expected to be an integer) with +a singular or plural label (the second and third arguments, both expected +to be strings). + +#### The `xolox#misc#format#timestamp()` function + +Format a time stamp (a string containing a formatted floating point +number) into a human friendly format, for example 70 seconds is phrased as +"1 minute and 10 seconds". + +### List handling functions + +#### The `xolox#misc#list#unique()` function + +Remove duplicate values from the given list in-place (preserves order). + +#### The `xolox#misc#list#binsert()` function + +Performs in-place binary insertion, which depending on your use case can +be more efficient than calling Vim's [sort()] [sort] function after each +insertion (in cases where a single, final sort is not an option). Expects +three arguments: + +1. A list +2. A value to insert +3. 1 (true) when case should be ignored, 0 (false) otherwise + +[sort]: http://vimdoc.sourceforge.net/htmldoc/eval.html#sort() + +### Functions to interact with the user + +#### The `xolox#misc#msg#info()` function + +Show a formatted informational message to the user. + +This function has the same argument handling as Vim's [printf()] [] +function with one notable difference: Any arguments which are not numbers +or strings are coerced to strings using Vim's [string()] [] function. + +In the case of `xolox#misc#msg#info()`, automatic string coercion simply +makes the function a bit easier to use. + +The messages emitted by this function have no highlighting. Previously +these messages were highlighted using the [Title group] [hl-title], but it +was pointed out in [pull request 16] [pr-16] that this group shouldn't be +used for informational messages because it is meant for titles and because +of this some color schemes use colors that stand out quite a bit, causing +the informational messages to look like errors. + +[hl-title]: http://vimdoc.sourceforge.net/htmldoc/syntax.html#hl-Title +[pr-16]: https://github.com/xolox/vim-misc/pull/16 +[printf()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#printf() +[string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string() + +#### The `xolox#misc#msg#warn()` function + +Show a formatted warning message to the user. + +This function has the same argument handling as the +`xolox#misc#msg#info()` function. + +#### The `xolox#misc#msg#debug()` function + +Show a formatted debugging message to the user, *if the user has enabled +increased verbosity by setting Vim's ['verbose'] [] option to one +(1) or higher*. + +This function has the same argument handling as the +`xolox#misc#msg#info()` function. + +In the case of `xolox#misc#msg#debug()`, automatic string coercion +provides lazy evaluation in the sense that complex data structures are +only converted to strings when the user has enabled increased verbosity. + +['verbose']: http://vimdoc.sourceforge.net/htmldoc/options.html#'verbose' + +### Integration between Vim and its environment + +#### The `xolox#misc#open#file()` function + +Given a pathname or URL as the first argument, this opens the file with +the program associated with the file type. So for example a text file +might open in Vim, an `*.html` file would probably open in your web +browser and a media file would open in a media player. + +This should work on Windows, Mac OS X and most Linux distributions. If +this fails to find a file association, you can pass one or more external +commands to try as additional arguments. For example: + + :call xolox#misc#open#file('/path/to/my/file', 'firefox', 'google-chrome') + +This generally shouldn't be necessary but it might come in handy now and +then. + +#### The `xolox#misc#open#url()` function + +Given a URL as the first argument, this opens the URL in your preferred or +best available web browser: + +- In GUI environments a graphical web browser will open (or a new tab will + be created in an existing window) +- In console Vim without a GUI environment, when you have any of `lynx`, + `links` or `w3m` installed it will launch a command line web browser in + front of Vim (temporarily suspending Vim) + +### Vim and plug-in option handling + +#### The `xolox#misc#option#get()` function + +Expects one or two arguments: 1. The name of a variable and 2. the default +value if the variable does not exist. + +Returns the value of the variable from a buffer local variable, global +variable or the default value, depending on which is defined. + +This is used by some of my Vim plug-ins for option handling, so that users +can customize options for specific buffers. + +#### The `xolox#misc#option#split()` function + +Given a multi-value Vim option like ['runtimepath'] [rtp] this returns a +list of strings. For example: + + :echo xolox#misc#option#split(&runtimepath) + ['/home/peter/Projects/Vim/misc', + '/home/peter/Projects/Vim/colorscheme-switcher', + '/home/peter/Projects/Vim/easytags', + ...] + +[rtp]: http://vimdoc.sourceforge.net/htmldoc/options.html#'runtimepath' + +#### The `xolox#misc#option#join()` function + +Given a list of strings like the ones returned by +`xolox#misc#option#split()`, this joins the strings together into a +single value that can be used to set a Vim option. + +#### The `xolox#misc#option#split_tags()` function + +Customized version of `xolox#misc#option#split()` with specialized +handling for Vim's ['tags' option] [tags]. + +[tags]: http://vimdoc.sourceforge.net/htmldoc/options.html#'tags' + +#### The `xolox#misc#option#join_tags()` function + +Customized version of `xolox#misc#option#join()` with specialized +handling for Vim's ['tags' option] [tags]. + +#### The `xolox#misc#option#eval_tags()` function + +Evaluate Vim's ['tags' option] [tags] without looking at the file +system, i.e. this will report tags files that don't exist yet. Expects +the value of the ['tags' option] [tags] as the first argument. If the +optional second argument is 1 (true) only the first match is returned, +otherwise (so by default) a list with all matches is returned. + +### Operating system interfaces + +#### The `xolox#misc#os#is_mac()` function + +Returns 1 (true) when on Mac OS X, 0 (false) otherwise. You would expect +this to simply check the Vim feature list, but for some obscure reason the +`/usr/bin/vim` included in Mac OS X (verified on version 10.7.5) returns 0 +(false) in response to `has('mac')`, so we check the output of `uname` +to avoid false negatives. + +#### The `xolox#misc#os#is_win()` function + +Returns 1 (true) when on Microsoft Windows, 0 (false) otherwise. + +#### The `xolox#misc#os#find_vim()` function + +Returns the program name of Vim as a string. On Windows and UNIX this just +[v:progname] [] as an absolute pathname while on Mac OS X there is +some special magic to find MacVim's executable even though it's usually +not on the executable search path. If you want, you can override the +value returned from this function by setting the global variable +`g:xolox#misc#os#vim_progname`. + +By default the choice of console Vim vs graphical Vim is made based on +the value of [v:progname] [], but if you have a preference you can pass +the string `vim` or `gvim` as the first and only argument. + +[v:progname]: http://vimdoc.sourceforge.net/htmldoc/eval.html#v:progname + +#### The `xolox#misc#os#exec()` function + +Execute an external command (hiding the console on Microsoft Windows when +my [vim-shell plug-in] [vim-shell] is installed). + +Expects a dictionary with the following key/value pairs as the first +argument: + +- **command** (required): The command line to execute +- **async** (optional): set this to 1 (true) to execute the command in the + background (asynchronously) +- **stdin** (optional): a string or list of strings with the input for the + external command +- **check** (optional): set this to 0 (false) to disable checking of the + exit code of the external command (by default an exception will be + raised when the command fails) + +Returns a dictionary with one or more of the following key/value pairs: + +- **command** (always available): the generated command line that was used + to run the external command +- **exit_code** (only in synchronous mode): the exit status of the + external command (an integer, zero on success) +- **stdout** (only in synchronous mode): the output of the command on the + standard output stream (a list of strings, one for each line) +- **stderr** (only in synchronous mode): the output of the command on the + standard error stream (as a list of strings, one for each line) + +[vim-shell]: http://peterodding.com/code/vim/shell/ + +#### The `xolox#misc#os#can_use_dll()` function + +If a) we're on Microsoft Windows, b) the vim-shell plug-in is installed +and c) the compiled DLL included in vim-shell works, we can use the +vim-shell plug-in to execute external commands! Returns 1 (true) +if we can use the DLL, 0 (false) otherwise. + +### Pathname manipulation functions + +#### The `xolox#misc#path#which()` function + +Scan the executable search path (`$PATH`) for one or more external +programs. Expects one or more string arguments with program names. Returns +a list with the absolute pathnames of all found programs. Here's an +example: + + :echo xolox#misc#path#which('gvim', 'vim') + ['/usr/local/bin/gvim', + '/usr/bin/gvim', + '/usr/local/bin/vim', + '/usr/bin/vim'] + +#### The `xolox#misc#path#split()` function + +Split a pathname (the first and only argument) into a list of pathname +components. + +On Windows, pathnames starting with two slashes or backslashes are UNC +paths where the leading slashes are significant... In this case we split +like this: + +- Input: `'//server/share/directory'` +- Result: `['//server', 'share', 'directory']` + +Everything except Windows is treated like UNIX until someone has a better +suggestion :-). In this case we split like this: + +- Input: `'/foo/bar/baz'` +- Result: `['/', 'foo', 'bar', 'baz']` + +To join a list of pathname components back into a single pathname string, +use the `xolox#misc#path#join()` function. + +#### The `xolox#misc#path#join()` function + +Join a list of pathname components (the first and only argument) into a +single pathname string. This is the counterpart to the +`xolox#misc#path#split()` function and it expects a list of pathname +components as returned by `xolox#misc#path#split()`. + +#### The `xolox#misc#path#directory_separator()` function + +Find the preferred directory separator for the platform and settings. + +#### The `xolox#misc#path#absolute()` function + +Canonicalize and resolve a pathname, *regardless of whether it exists*. +This is intended to support string comparison to determine whether two +pathnames point to the same directory or file. + +#### The `xolox#misc#path#relative()` function + +Make an absolute pathname (the first argument) relative to a directory +(the second argument). + +#### The `xolox#misc#path#merge()` function + +Join a directory pathname and filename into a single pathname. + +#### The `xolox#misc#path#commonprefix()` function + +Find the common prefix of path components in a list of pathnames. + +#### The `xolox#misc#path#starts_with()` function + +Check whether the first pathname starts with the second pathname (expected +to be a directory). This does not perform a regular string comparison; +first it normalizes both pathnames, then it splits them into their +pathname segments and then it compares the segments. + +#### The `xolox#misc#path#encode()` function + +Encode a pathname so it can be used as a filename. This uses URL encoding +to encode special characters. + +#### The `xolox#misc#path#decode()` function + +Decode a pathname previously encoded with `xolox#misc#path#encode()`. + +#### The `xolox#misc#path#is_relative()` function + +Returns true (1) when the pathname given as the first argument is +relative, false (0) otherwise. + +#### The `xolox#misc#path#tempdir()` function + +Create a temporary directory and return the pathname of the directory. + +### Manipulation of UNIX file permissions + +Vim's [writefile()][] function cannot set file permissions for newly created +files and although Vim script has a function to get file permissions (see +[getfperm()][]) there is no equivalent for changing a file's permissions. + +This omission breaks the otherwise very useful idiom of updating a file by +writing its new contents to a temporary file and then renaming the temporary +file into place (which is as close as you're going to get to atomically +updating a file's contents on UNIX) because the file's permissions will not +be preserved! + +**Here's a practical example:** My [vim-easytags][] plug-in writes tags file +updates to a temporary file and renames the temporary file into place. When +I use `sudo -s` on Ubuntu Linux it preserves my environment variables so my +`~/.vimrc` and the [vim-easytags][] plug-in are still loaded. Now when a +tags file is written the file becomes owned by root (my effective user id in +the `sudo` session). Once I leave the `sudo` session I can no longer update +my tags file because it's now owned by root … ಠ_ಠ + +[getfperm()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#getfperm() +[vim-easytags]: http://peterodding.com/code/vim/easytags/ +[writefile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#writefile() + +#### The `xolox#misc#perm#update()` function + +Atomically update a file's contents while preserving the owner, group and +mode. The first argument is the pathname of the file to update (a string). +The second argument is the list of lines to be written to the file. Writes +the new contents to a temporary file and renames the temporary file into +place, thereby preventing readers from reading a partially written file. +Returns 1 if the file is successfully updated, 0 otherwise. + +Note that if `xolox#misc#perm#get()` and `xolox#misc#perm#set()` cannot be +used to preserve the file owner/group/mode the file is still updated using +a rename (for compatibility with non-UNIX systems and incompatible +`/usr/bin/stat` implementations) so in that case you can still lose the +file's owner/group/mode. + +#### The `xolox#misc#perm#get()` function + +Get the owner, group and permissions of the pathname given as the first +argument. Returns an opaque value which you can later pass to +`xolox#misc#perm#set()`. + +#### The `xolox#misc#perm#set()` function + +Set the permissions (the second argument) of the pathname given as the +first argument. Expects a permissions value created by +`xolox#misc#perm#get()`. + +### Persist/recall Vim values from/to files + +Vim's [string()][] function can be used to serialize Vim script values like +numbers, strings, lists, dictionaries and composites of them to a string +which can later be evaluated using the [eval()][] function to turn it back +into the original value. This Vim script provides functions to use these +functions to persist and recall Vim values from/to files. This is very +useful for communication between (possibly concurrent) Vim processes. + +#### The `xolox#misc#persist#load()` function + +Read a Vim value like a number, string, list or dictionary from a file +using [readfile()][] and [eval()][]. The first argument is the filename of +the file to read (a string). The optional second argument specifies the +default value which is returned when the file can't be loaded. This +function returns the loaded value or the default value (which itself +defaults to the integer 0). + +[eval()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#eval() +[readfile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#readfile() + +#### The `xolox#misc#persist#save()` function + +Write a Vim value like a number, string, list or dictionary to a file +using [string()][] and [writefile()][]. The first argument is the filename +of the file to write (a string) and the second argument is the value to +write (any value). + +This function writes the serialized value to an intermediate file which is +then renamed into place atomically. This avoids issues with concurrent +processes where for example a producer has written a partial file which is +read by a consumer before the file is complete. In this case the consumer +would read a corrupt value. The rename trick avoids this problem. + +[string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string() +[writefile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#writefile() + +### String handling + +#### The `xolox#misc#str#slug()` function + +Convert a string to a "slug" - something that can be safely used in +filenames and URLs without worrying about quoting/escaping of special +characters. + +#### The `xolox#misc#str#ucfirst()` function + +Uppercase the first character in a string (the first argument). + +#### The `xolox#misc#str#unescape()` function + +Remove back slash escapes from a string (the first argument). + +#### The `xolox#misc#str#compact()` function + +Compact whitespace in a string (the first argument). + +#### The `xolox#misc#str#trim()` function + +Trim all whitespace from the start and end of a string (the first +argument). + +#### The `xolox#misc#str#indent()` function + +Indent all lines in a multi-line string (the first argument) with a +specific number of *space characters* (the second argument, an integer). + +#### The `xolox#misc#str#dedent()` function + +Remove common whitespace from a multi line string. + +### Test runner & infrastructure for Vim plug-ins + +The Vim auto-load script `autoload/xolox/misc/test.vim` contains +infrastructure that can be used to run an automated Vim plug-in test suite. +It provides a framework for running test functions, keeping track of the +test status, making assertions and reporting test results to the user. + +#### The `xolox#misc#test#reset()` function + +Reset counters for executed tests and passed/failed assertions. + +#### The `xolox#misc#test#summarize()` function + +Print a summary of test results, to be interpreted interactively. + +#### The `xolox#misc#test#wrap()` function + +Call a function in a try/catch block and prevent exceptions from bubbling. +The name of the function should be passed as the first and only argument; +it should be a string containing the name of a Vim auto-load function. + +#### The `xolox#misc#test#passed()` function + +Record a test which succeeded. + +#### The `xolox#misc#test#failed()` function + +Record a test which failed. + +#### The `xolox#misc#test#assert_true()` function + +Check whether an expression is true. + +#### The `xolox#misc#test#assert_equals()` function + +Check whether two values are the same. + +#### The `xolox#misc#test#assert_same_type()` function + +Check whether two values are of the same type. + +### Tests for the miscellaneous Vim scripts + +The Vim auto-load script `autoload/xolox/misc/tests.vim` contains the +automated test suite of the miscellaneous Vim scripts. Right now the +coverage is not very high yet, but this will improve over time. + +#### The `xolox#misc#tests#run()` function + +Run the automated test suite of the miscellaneous Vim scripts. To be used +interactively. Intended to be safe to execute irrespective of context. + +#### The `xolox#misc#tests#pattern_escaping()` function + +Test escaping of regular expression patterns with +`xolox#misc#escape#pattern()`. + +#### The `xolox#misc#tests#substitute_escaping()` function + +Test escaping of substitution strings with +`xolox#misc#escape#substitute()`. + +#### The `xolox#misc#tests#shell_escaping()` function + +Test escaping of shell arguments with `xolox#misc#escape#shell()`. + +#### The `xolox#misc#tests#making_a_list_unique()` function + +Test removing of duplicate values from lists with +`xolox#misc#list#unique()`. + +#### The `xolox#misc#tests#binary_insertion()` function + +Test the binary insertion algorithm implemented in +`xolox#misc#list#binsert()`. + +#### The `xolox#misc#tests#getting_configuration_options()` function + +Test getting of scoped plug-in configuration "options" with +`xolox#misc#option#get()`. + +#### The `xolox#misc#tests#splitting_of_multi_valued_options()` function + +Test splitting of multi-valued Vim options with +`xolox#misc#option#split()`. + +#### The `xolox#misc#tests#joining_of_multi_valued_options()` function + +Test joining of multi-valued Vim options with `xolox#misc#option#join()`. + +#### The `xolox#misc#tests#finding_vim_on_the_search_path()` function + +Test looking up Vim's executable on the search path using [v:progname] [] +with `xolox#misc#os#find_vim()`. + +[v:progname]: http://vimdoc.sourceforge.net/htmldoc/eval.html#v:progname + +#### The `xolox#misc#tests#synchronous_command_execution()` function + +Test basic functionality of synchronous command execution with +`xolox#misc#os#exec()`. + +#### The `xolox#misc#tests#synchronous_command_execution_with_stderr()` function + +Test basic functionality of synchronous command execution with +`xolox#misc#os#exec()` including the standard error stream (not available +on Windows when vim-shell is not installed). + +#### The `xolox#misc#tests#synchronous_command_execution_with_raising_of_errors()` function + +Test raising of errors during synchronous command execution with +`xolox#misc#os#exec()`. + +#### The `xolox#misc#tests#synchronous_command_execution_without_raising_errors()` function + +Test synchronous command execution without raising of errors with +`xolox#misc#os#exec()`. + +#### The `xolox#misc#tests#asynchronous_command_execution()` function + +Test the basic functionality of asynchronous command execution with +`xolox#misc#os#exec()`. This runs the external command `mkdir` and tests +that the side effect of creating the directory takes place. This might +seem like a peculiar choice, but it's one of the few 100% portable +commands (Windows + UNIX) that doesn't involve input/output streams. + +#### The `xolox#misc#tests#string_case_transformation()` function + +Test string case transformation with `xolox#misc#str#ucfirst()`. + +#### The `xolox#misc#tests#string_whitespace_compaction()` function + +Test compaction of whitespace in strings with `xolox#misc#str#compact()`. + +#### The `xolox#misc#tests#string_whitespace_trimming()` function + +Test trimming of whitespace in strings with `xolox#misc#str#trim()`. + +#### The `xolox#misc#tests#multiline_string_dedent()` function + +Test dedenting of multi-line strings with `xolox#misc#str#dedent()`. + +#### The `xolox#misc#tests#version_string_parsing()` function + +Test parsing of version strings with `xolox#misc#version#parse()`. + +#### The `xolox#misc#tests#version_string_comparison()` function + +Test comparison of version strings with `xolox#misc#version#at_least()`. + +### Timing of long during operations + +#### The `xolox#misc#timer#resumable()` function + +Create a resumable timer object. This returns an object (a dictionary with +functions) with the following "methods": + + - `start()` instructs the timer object to start counting elapsed time + (when a timer object is created it is not automatically started). + + - `stop()` instructs the timer object to stop counting elapsed time. + This adds the time elapsed since `start()` was last called to the + total elapsed time. This method will raise an error if called out of + sequence. + + - `format()` takes the total elapsed time and reports it as a string + containing a formatted floating point number. + +Timer objects are meant to accurately time short running operations so +they're dependent on Vim's [reltime()][] and [reltimestr()][] functions. +In order to make it possible to use timer objects in my Vim plug-ins +unconditionally there's a fall back to [localtime()][] when [reltime()][] +is not available. In this mode the timer objects are not very useful but +at least they shouldn't raise errors. + +[localtime()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#localtime() +[reltime()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#reltime() +[reltimestr()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#reltimestr() + +#### The `xolox#misc#timer#start()` function + +Start a timer. This returns a list which can later be passed to +`xolox#misc#timer#stop()`. + +#### The `xolox#misc#timer#stop()` function + +Show a formatted debugging message to the user, if the user has enabled +increased verbosity by setting Vim's ['verbose'] [verbose] option to one +(1) or higher. + +This function has the same argument handling as Vim's [printf()] [printf] +function with one difference: At the point where you want the elapsed time +to be embedded, you write `%s` and you pass the list returned by +`xolox#misc#timer#start()` as an argument. + +[verbose]: http://vimdoc.sourceforge.net/htmldoc/options.html#'verbose' +[printf]: http://vimdoc.sourceforge.net/htmldoc/eval.html#printf() + +#### The `xolox#misc#timer#force()` function + +Show a formatted message to the user. This function has the same argument +handling as Vim's [printf()] [printf] function with one difference: At the +point where you want the elapsed time to be embedded, you write `%s` and +you pass the list returned by `xolox#misc#timer#start()` as an argument. + +#### The `xolox#misc#timer#convert()` function + +Convert the value returned by `xolox#misc#timer#start()` to a string +representation of the elapsed time since `xolox#misc#timer#start()` was +called. Other values are returned unmodified (this allows using it with +Vim's [map()][] function). + +[map()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#map() + +### Version string handling + +#### The `xolox#misc#version#parse()` function + +Convert a version string to a list of integers. + +#### The `xolox#misc#version#at_least()` function + +Check whether the second version string is equal to or greater than the +first version string. Returns 1 (true) when it is, 0 (false) otherwise. + + + +## Contact + +If you have questions, bug reports, suggestions, etc. please open an issue or +pull request on [GitHub] []. Download links and documentation can be found on +the plug-in's [homepage] []. If you like the script please vote for it on +[Vim Online] []. + +## License + +This software is licensed under the [MIT license] []. +© 2015 Peter Odding <>. + + +[GitHub]: http://github.com/xolox/vim-misc +[homepage]: http://peterodding.com/code/vim/misc +[MIT license]: http://en.wikipedia.org/wiki/MIT_License +[plugins]: http://peterodding.com/code/vim/ +[Vim Online]: http://www.vim.org/scripts/script.php?script_id=4597 +[vim-tools]: http://peterodding.com/code/vim/tools/ +[howto-install]: https://github.com/xolox/vim-misc/blob/master/INSTALL.md diff --git a/sources_non_forked/vim-misc/addon-info.json b/sources_non_forked/vim-misc/addon-info.json new file mode 100755 index 00000000..934bcf72 --- /dev/null +++ b/sources_non_forked/vim-misc/addon-info.json @@ -0,0 +1 @@ +{"vim_script_nr": 4597, "dependencies": {}, "homepage": "http://peterodding.com/code/vim/misc", "name": "vim-misc"} \ No newline at end of file diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc.vim b/sources_non_forked/vim-misc/autoload/xolox/misc.vim new file mode 100755 index 00000000..19aed51c --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc.vim @@ -0,0 +1,7 @@ +" The version of my miscellaneous scripts. +" +" Author: Peter Odding +" Last Change: May 21, 2015 +" URL: http://peterodding.com/code/vim/misc/ + +let g:xolox#misc#version = '1.17.6' diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/async.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/async.vim new file mode 100755 index 00000000..294a3a16 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/async.vim @@ -0,0 +1,261 @@ +" Asynchronous Vim script evaluation. +" +" Author: Peter Odding +" Last Change: September 17, 2014 +" URL: http://peterodding.com/code/vim/misc/ +" +" The `xolox#misc#async#call()` function builds on top of `xolox#misc#os#exec()` +" to support asynchronous evaluation of Vim scripts. The first (and for now +" only) use case is my [vim-easytags][] plug-in which has a bunch of +" conflicting requirements: +" +" 1. I want the [vim-easytags][] plug-in to be as portable as possible. +" Ideally everything is implemented in Vim script because that's the only +" thing I can rely on to be available for all potential users of the +" plug-in! +" +" 2. Because of point one I've been forced to implement tags file reading, +" parsing, (fold case) sorting and writing in Vim script. This is fine for +" small tags files but once they grow to a couple of megabytes it becomes +" annoying because Vim is unresponsive during tags file updates (key +" presses are fortunately buffered due to Vim's input model but that +" doesn't make it a nice user experience :-). +" +" 3. I could (and did in the past) come up with all sorts of hacks to speed +" things up without switching away from Vim script, but none of them are +" going to solve the fundamental problem that Vim's unresponsive hiccups +" become longer as tags files grow larger. +" +" By now it should be clear where this is heading: _Why not handle tags file +" updates in a Vim process that runs in the background without blocking the +" Vim process that the user is interacting with?_ It turns out that there are +" quite a few details to take care of, but with those out of the way, it might +" just work! I'm actually hoping to make asynchronous updates the default mode +" in [vim-easytags][]. This means I need this functionality to be as +" portable and robust as possible. +" +" **Status:** This code has seen little testing so I wouldn't trust it too +" much just yet. On the other hand, as I said, my intention is to make this +" functionality as portable and robust as possible. You be the judge :-). +" +" [vim-easytags]: http://peterodding.com/code/vim/easytags/ + +if !exists('g:xolox#misc#async#counter') + " Increasing integer number used to match asynchronous responses to the + " requests that generated them. + let g:xolox#misc#async#counter = 1 +endif + +if !exists('g:xolox#misc#async#requests') + " Queue of asynchronous requests that haven't received a response yet. + let g:xolox#misc#async#requests = {} +endif + +function! xolox#misc#async#call(options) " {{{1 + " Call a Vim script function asynchronously by starting a hidden Vim process + " in the background. Once the function returns the hidden Vim process + " terminates itself. This function takes a single argument which is a + " dictionary with the following key/value pairs: + " + " - **function** (required): The name of the Vim function to call inside + " the child process (a string). I suggest using an [autoload][] function + " for this, see below. + " + " - **arguments** (optional): A list of arguments to pass to the function. + " This list is serialized to a string using [string()][] and deserialized + " using [eval()][]. + " + " - **callback** (optional): The name of a Vim function to call in the + " parent process when the child process has completed (a string). + " + " - **clientserver** (optional): If this is true (1) the child process will + " notify the parent process when it has finished (the default is true). + " This works using Vim's client/server support which is not always + " available. As a fall back Vim's [CursorHold][] automatic command is + " also supported (although the effect is not quite as instantaneous :-). + " + " This functionality is experimental and non trivial to use, so consider + " yourself warned :-). + " + " **Limitations** + " + " I'm making this functionality available in [vim-misc][] because I think it + " can be useful to other plug-ins, however if you are going to use it you + " should be aware of the following limitations: + " + " - Because of the use of multiple processes this functionality is only + " suitable for 'heavy' tasks. + " + " - The function arguments are serialized to a string which is passed to + " the hidden Vim process as a command line argument, so the amount of + " data you can pass will be limited by your operating environment. + " + " - The hidden Vim process is explicitly isolated from the user in several + " ways (see below for more details). This is to make sure that the hidden + " Vim processes are fast and don't clobber the user's editing sessions in + " any way. + " + " **Changes to how Vim normally works** + " + " You have to be aware that the hidden Vim process is initialized in a + " specific way that is very different from your regular Vim editing + " sessions: + " + " - Your [vimrc][] file is ignored using the `-u NONE` command line option. + " + " - Your [gvimrc][] file (if you even knew it existed ;-) is ignored using + " the `-U NONE` command line option. + " + " - Plug-in loading is skipped using the `--noplugin` command line option. + " + " - Swap files (see [swap-file][]) are disabled using the `-n` command line + " option. This makes sure asynchronous Vim processes don't disturb the + " user's editing session. + " + " - Your [viminfo][] file is ignored using the `-i NONE` command line + " option. Just like with swap files this makes sure asynchronous Vim + " processes don't disturb the user's editing session. + " + " - No-compatible mode is enabled using the `-N` command line option + " (usually the existence of your vimrc script would have achieved the + " same effect but since we disable loading of your vimrc we need to spell + " things out for Vim). + " + " **Use an auto-load function** + " + " The function you want to call is identified by its name which has to be + " defined, but I just explained above that all regular initialization is + " disabled for asynchronous Vim processes, so what gives? The answer is to + " use an [autoload][] function. This should work fine because the + " asynchronous Vim process 'inherits' the value of the ['runtimepath'][] + " option from your editing session. + " + " ['runtimepath']: http://vimdoc.sourceforge.net/htmldoc/options.html#'runtimepath' + " [autoload]: http://vimdoc.sourceforge.net/htmldoc/eval.html#autoload + " [CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold + " [eval()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#eval() + " [gvimrc]: http://vimdoc.sourceforge.net/htmldoc/gui.html#gvimrc + " [string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string() + " [swap-file]: http://vimdoc.sourceforge.net/htmldoc/recover.html#swap-file + " [vim-misc]: http://peterodding.com/code/vim/misc/ + " [viminfo]: http://vimdoc.sourceforge.net/htmldoc/starting.html#viminfo + " [vimrc]: http://vimdoc.sourceforge.net/htmldoc/starting.html#vimrc + let unique_number = g:xolox#misc#async#counter + let g:xolox#misc#async#counter += 1 + let request = {'function': a:options['function']} + let request['arguments'] = get(a:options, 'arguments', []) + let request['starttime'] = xolox#misc#timer#start() + let request['number'] = unique_number + let callback = get(a:options, 'callback') + if !empty(callback) + let request['callback'] = callback + endif + if get(a:options, 'clientserver', 1) && !empty(v:servername) + let request['servername'] = v:servername + else + let temporary_file = tempname() + let request['temporary_file'] = temporary_file + endif + let vim_command = printf('let &rtp = %s | call xolox#misc#async#inside_child(%s)', string(&rtp), string(request)) + call xolox#misc#msg#debug("vim-misc %s: Generated asynchronous Vim command #%i: %s", g:xolox#misc#version, unique_number, vim_command) + let quoted_program = xolox#misc#escape#shell(xolox#misc#os#find_vim('vim')) + let quoted_command = xolox#misc#escape#shell(vim_command) + let shell_command = printf('%s -u NONE -U NONE --noplugin -n -N -i NONE --cmd %s', quoted_program, quoted_command) + call xolox#misc#msg#debug("vim-misc %s: Generated asynchronous shell command #%i: %s", g:xolox#misc#version, unique_number, shell_command) + call xolox#misc#os#exec({'command': shell_command, 'async': 1}) + let g:xolox#misc#async#requests[unique_number] = request +endfunction + +function! xolox#misc#async#inside_child(request) " {{{1 + " Entry point inside the hidden Vim process that runs in the background. + " Invoked indirectly by `xolox#misc#async#call()` because it runs a command + " similar to the following: + " + " vim --cmd 'call xolox#misc#async#inside_child(...)' + " + " This function is responsible for calling the user defined function, + " capturing exceptions and reporting the results back to the parent Vim + " process using Vim's client/server support or a temporary file. + try + let response = {'number': a:request['number']} + let starttime = xolox#misc#timer#start() + try + " Call the user defined function and store its result. + let response['result'] = call(a:request['function'], a:request['arguments']) + catch + " Intercept errors raised by the user defined function. + let response['exception'] = v:exception + let response['throwpoint'] = v:throwpoint + endtry + " Record the elapsed time. + let response['elapsed_time'] = xolox#misc#timer#convert(starttime) + " Communicate the results back to the master Vim process. + let servername = get(a:request, 'servername', '') + if !empty(servername) + " Actively notify the parent process using Vim's client/server support? + call remote_expr(servername, printf('xolox#misc#async#callback_to_parent(%s)', string(response))) + else + " 'Passively' notify the parent process by creating the expected + " temporary file. + call xolox#misc#persist#save(a:request['temporary_file'], response) + endif + finally + " Make sure we terminate this hidden Vim process. + quitall! + endtry +endfunction + +function! xolox#misc#async#callback_to_parent(response) " {{{1 + " When Vim was compiled with client/server support this function (in the + " parent process) will be called by `xolox#misc#async#inside_child()` (in + " the child process) after the user defined function has returned. This + " enables more or less instant callbacks after running an asynchronous + " function. + let unique_number = a:response['number'] + let request = g:xolox#misc#async#requests[unique_number] + call xolox#misc#timer#stop("vim-misc %s: Processing asynchronous callback #%i after %s ..", g:xolox#misc#version, unique_number, request['starttime']) + call remove(g:xolox#misc#async#requests, unique_number) + let callback = get(request, 'callback') + if !empty(callback) + call call(callback, [a:response]) + endif +endfunction + +function! xolox#misc#async#periodic_callback() " {{{1 + " When client/server support is not being used the vim-misc plug-in + " improvises: It uses Vim's [CursorHold][] event to periodically check if an + " asynchronous process has written its results to one of the expected + " temporary files. If a response is found the temporary file is read and + " deleted and then `xolox#misc#async#callback_to_parent()` is called to + " process the response. + " + " [CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold + if !empty(g:xolox#misc#async#requests) + let num_processed = 0 + call xolox#misc#msg#debug("vim-misc %s: Checking for asynchronous responses (%i responses not yet received) ..", g:xolox#misc#version, len(g:xolox#misc#async#requests)) + for unique_number in sort(keys(g:xolox#misc#async#requests)) + let request = g:xolox#misc#async#requests[unique_number] + let temporary_file = get(request, 'temporary_file', '') + if !empty(temporary_file) && getfsize(temporary_file) > 0 + try + call xolox#misc#msg#debug("vim-misc %s: Found asynchronous response by %s in %s ..", g:xolox#misc#version, request['function'], temporary_file) + call xolox#misc#async#callback_to_parent(xolox#misc#persist#load(temporary_file)) + let num_processed += 1 + finally + call delete(temporary_file) + endtry + endif + endfor + call xolox#misc#msg#debug("vim-misc %s: Processed %i asynchronous responses (%i responses not yet received).", g:xolox#misc#version, num_processed, len(g:xolox#misc#async#requests)) + endif +endfunction + +" }}}1 + +" The interval in the options below is set to one (1) although the default +" value for &updatetime is four seconds. Because vim-misc never modifies +" &updatetime the interval will effectively default to four seconds unless the +" user has set &updatetime to a lower value themselves. +call xolox#misc#cursorhold#register({'function': 'xolox#misc#async#periodic_callback', 'interval': 1}) + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/buffer.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/buffer.vim new file mode 100755 index 00000000..01dca6ef --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/buffer.vim @@ -0,0 +1,80 @@ +" Handling of special buffers +" +" Author: Peter Odding +" Last Change: May 19, 2013 +" URL: http://peterodding.com/code/vim/misc/ +" +" The functions defined here make it easier to deal with special Vim buffers +" that contain text generated by a Vim plug-in. For example my [vim-notes +" plug-in] [vim-notes] generates several such buffers: +" +" - [:RecentNotes] [RecentNotes] lists recently modified notes +" - [:ShowTaggedNotes] [ShowTaggedNotes] lists notes grouped by tags +" - etc. +" +" Because the text in these buffers is generated, Vim shouldn't bother with +" swap files and it should never prompt the user whether to save changes to +" the generated text. +" +" [vim-notes]: http://peterodding.com/code/vim/notes/ +" [RecentNotes]: http://peterodding.com/code/vim/notes/#recentnotes_command +" [ShowTaggedNotes]: http://peterodding.com/code/vim/notes/#showtaggednotes_command + +function! xolox#misc#buffer#is_empty() " {{{1 + " Checks if the current buffer is an empty, unchanged buffer which can be + " reused. Returns 1 if an empty buffer is found, 0 otherwise. + return !&modified && expand('%') == '' && line('$') <= 1 && getline(1) == '' +endfunction + +function! xolox#misc#buffer#prepare(...) " {{{1 + " Open a special buffer, i.e. a buffer that will hold generated contents, + " not directly edited by the user. The buffer can be customized by passing a + " dictionary with the following key/value pairs as the first argument: + " + " - **name** (required): The base name of the buffer (i.e. the base name of + " the file loaded in the buffer, even though it isn't really a file and + " nothing is really 'loaded' :-) + " - **path** (required): The pathname of the buffer. May be relevant if + " [:lcd] [lcd] or ['autochdir'] [acd] is being used. + " + " [lcd]: http://vimdoc.sourceforge.net/htmldoc/editing.html#:lcd + " [acd]: http://vimdoc.sourceforge.net/htmldoc/options.html#'autochdir' + if a:0 == 1 && type(a:1) == type('') + " Backwards compatibility with old interface. + let options = {'name': a:1, 'path': a:1} + elseif type(a:1) == type({}) + let options = a:1 + else + throw "Invalid arguments" + endif + let winnr = 1 + let found = 0 + for bufnr in tabpagebuflist() + if xolox#misc#path#equals(options['path'], bufname(bufnr)) + execute winnr . 'wincmd w' + let found = 1 + break + else + let winnr += 1 + endif + endfor + if !(found || xolox#misc#buffer#is_empty()) + vsplit + endif + silent execute 'edit' fnameescape(options['path']) + lcd " clear working directory + setlocal buftype=nofile bufhidden=hide noswapfile + let &l:statusline = '[' . options['name'] . ']' + call xolox#misc#buffer#unlock() + silent %delete +endfunction + +function! xolox#misc#buffer#lock() " {{{1 + " Lock a special buffer so that its contents can no longer be edited. + setlocal readonly nomodifiable nomodified +endfunction + +function! xolox#misc#buffer#unlock() " {{{1 + " Unlock a special buffer so that its content can be updated. + setlocal noreadonly modifiable +endfunction diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/complete.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/complete.vim new file mode 100755 index 00000000..e3818d42 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/complete.vim @@ -0,0 +1,26 @@ +" Tab completion for user defined commands. +" +" Author: Peter Odding +" Last Change: July 9, 2014 +" URL: http://peterodding.com/code/vim/misc/ + +function! xolox#misc#complete#keywords(arglead, cmdline, cursorpos) + " This function can be used to perform keyword completion for user defined + " Vim commands based on the contents of the current buffer. Here's an + " example of how you would use it: + " + " :command -nargs=* -complete=customlist,xolox#misc#complete#keywords MyCmd call s:MyCmd() + let words = {} + for line in getline(1, '$') + for word in split(line, '\W\+') + let words[word] = 1 + endfor + endfor + let arguments = [keys(filter(words, 'v:key =~# a:arglead'))] + if &ignorecase + call add(arguments, 1) + endif + return call('sort', arguments) +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/cursorhold.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/cursorhold.vim new file mode 100755 index 00000000..cbbde1fe --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/cursorhold.vim @@ -0,0 +1,71 @@ +" Rate limiting for Vim's CursorHold event. +" +" Author: Peter Odding +" Last Change: June 22, 2014 +" URL: http://peterodding.com/code/vim/misc/ +" +" Several of my Vim plug-ins (e.g. [vim-easytags][], [vim-notes][] and +" [vim-session][]) use Vim's [CursorHold][] and [CursorHoldI][] events to +" perform periodic tasks when the user doesn't press any keys for a couple of +" seconds. These events by default fire after four seconds, this is +" configurable using Vim's ['updatetime'][] option. The problem that this +" script solves is that there are Vim plug-ins which set the ['updatetime'][] +" option to unreasonably low values, thereby breaking my Vim plug-ins and +" probably a lot of other Vim plug-ins out there. When users complain about +" this I can tell them that another Vim plug-in is to blame, but users don't +" care for the difference, their Vim is broken! So I implemented a workaround. +" This script enables registration of [CursorHold][] event handlers with a +" configurable interval (expressed in seconds). The event handlers will be +" called no more than once every interval. +" +" ['updatetime']: http://vimdoc.sourceforge.net/htmldoc/options.html#'updatetime' +" [CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold +" [CursorHoldI]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHoldI +" [vim-easytags]: http://peterodding.com/code/vim/easytags/ +" [vim-notes]: http://peterodding.com/code/vim/notes/ +" [vim-session]: http://peterodding.com/code/vim/session/ + +if !exists('g:xolox#misc#cursorhold#handlers') + let g:xolox#misc#cursorhold#handlers = [] +endif + +function! xolox#misc#cursorhold#register(options) + " Register a [CursorHold][] event handler with a custom interval. This + " function takes a single argument which is a dictionary with the following + " fields: + " + " - **function** (required): The name of the event handler function (a + " string). + " + " - **arguments** (optional): A list of arguments to pass to the event + " handler function (defaults to an empty list). + " + " - **interval** (optional): The number of seconds between calls to the + " event handler (defaults to 4). + call add(g:xolox#misc#cursorhold#handlers, copy(a:options)) +endfunction + +function! xolox#misc#cursorhold#autocmd() + " The 'top level event handler' that's called by Vim whenever the + " [CursorHold][] or [CursorHoldI][] event fires. It iterates through the + " event handlers registered using `xolox#misc#cursorhold#register()` and + " calls each event handler at the appropriate interval, keeping track of + " the time when each event handler was last run. + for handler in g:xolox#misc#cursorhold#handlers + let function = handler['function'] + let last_run = get(handler, 'last_run', 0) + let interval = get(handler, 'interval', 4) + call xolox#misc#msg#debug("vim-misc %s: Checking handler %s with interval %i and last run %i ..", g:xolox#misc#version, function, interval, last_run) + " Rate limit in case &updatetime is set (very) low. + let time_until_next_run = (last_run + interval) - localtime() + if time_until_next_run > 0 + call xolox#misc#msg#debug("vim-misc %s: Rate limiting handler %s (time until next run: %i seconds).", g:xolox#misc#version, function, time_until_next_run) + else + call xolox#misc#msg#debug("vim-misc %s: Running handler %s ..", g:xolox#misc#version, function) + call call(function, get(handler, 'arguments', [])) + let handler['last_run'] = localtime() + endif + endfor +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/echo.exe b/sources_non_forked/vim-misc/autoload/xolox/misc/echo.exe new file mode 100755 index 0000000000000000000000000000000000000000..52f4e792df13bebd4f5743f29ba8fbe59fb40915 GIT binary patch literal 7680 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 literal 0 HcmV?d00001 diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/escape.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/escape.vim new file mode 100755 index 00000000..29a16ca1 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/escape.vim @@ -0,0 +1,56 @@ +" String escaping functions. +" +" Author: Peter Odding +" Last Change: May 19, 2013 +" URL: http://peterodding.com/code/vim/misc/ + +function! xolox#misc#escape#pattern(string) " {{{1 + " Takes a single string argument and converts it into a [:substitute] + " [subcmd] / [substitute()] [subfun] pattern string that matches the given + " string literally. + " + " [subfun]: http://vimdoc.sourceforge.net/htmldoc/eval.html#substitute() + " [subcmd]: http://vimdoc.sourceforge.net/htmldoc/change.html#:substitute + if type(a:string) == type('') + let string = escape(a:string, '^$.*\~[]') + return substitute(string, '\n', '\\n', 'g') + endif + return '' +endfunction + +function! xolox#misc#escape#substitute(string) " {{{1 + " Takes a single string argument and converts it into a [:substitute] + " [subcmd] / [substitute()] [subfun] replacement string that inserts the + " given string literally. + if type(a:string) == type('') + let string = escape(a:string, '\&~%') + return substitute(string, '\n', '\\r', 'g') + endif + return '' +endfunction + +function! xolox#misc#escape#shell(string) " {{{1 + " Takes a single string argument and converts it into a quoted command line + " argument. + " + " I was going to add a long rant here about Vim's ['shellslash' option] + " [shellslash], but really, it won't make any difference. Let's just suffice + " to say that I have yet to encounter a single person out there who uses + " this option for its intended purpose (running a UNIX style shell on + " Microsoft Windows). + " + " [shellslash]: http://vimdoc.sourceforge.net/htmldoc/options.html#'shellslash' + if xolox#misc#os#is_win() + try + let ssl_save = &shellslash + set noshellslash + return shellescape(a:string) + finally + let &shellslash = ssl_save + endtry + else + return shellescape(a:string) + endif +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/format.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/format.vim new file mode 100755 index 00000000..44f7b543 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/format.vim @@ -0,0 +1,46 @@ +" Human friendly string formatting for Vim. +" +" Author: Peter Odding +" Last Change: June 2, 2013 +" URL: http://peterodding.com/code/vim/misc/ + +function! xolox#misc#format#pluralize(count, singular, plural) " {{{1 + " Concatenate a counter (the first argument, expected to be an integer) with + " a singular or plural label (the second and third arguments, both expected + " to be strings). + if a:count == 0 + return printf('no %s', a:plural) + else + return printf('%i %s', a:count, a:count == 1 ? a:singular : a:plural) + endif +endfunction + +function! xolox#misc#format#timestamp(ts) " {{{1 + " Format a time stamp (a string containing a formatted floating point + " number) into a human friendly format, for example 70 seconds is phrased as + " "1 minute and 10 seconds". + let seconds = a:ts + 0 + " Fast common case with extra precision from reltime(). + if seconds < 5 + let extract = matchstr(a:ts, '^\d\+\(\.0*[1-9][1-9]\?\)\?') + if extract =~ '[123456789]' + return extract . ' second' . (extract != '1' ? 's' : '') + endif + endif + " Generic but slow code. + let result = [] + for [name, size] in [['day', 60 * 60 * 24], ['hour', 60 * 60], ['minute', 60], ['second', 1]] + if seconds >= size + let counter = seconds / size + let seconds = seconds % size + let suffix = counter != 1 ? 's' : '' + call add(result, printf('%i %s%s', counter, name, suffix)) + endif + endfor + " Format the resulting text? + if len(result) == 1 + return result[0] + else + return join(result[0:-2], ', ') . ' and ' . result[-1] + endif +endfunction diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/list.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/list.vim new file mode 100755 index 00000000..548592a3 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/list.vim @@ -0,0 +1,42 @@ +" List handling functions. +" +" Author: Peter Odding +" Last Change: June 2, 2013 +" URL: http://peterodding.com/code/vim/misc/ + +function! xolox#misc#list#unique(list) " {{{1 + " Remove duplicate values from the given list in-place (preserves order). + call reverse(a:list) + call filter(a:list, 'count(a:list, v:val) == 1') + return reverse(a:list) +endfunction + +function! xolox#misc#list#binsert(list, value, ...) " {{{1 + " Performs in-place binary insertion, which depending on your use case can + " be more efficient than calling Vim's [sort()] [sort] function after each + " insertion (in cases where a single, final sort is not an option). Expects + " three arguments: + " + " 1. A list + " 2. A value to insert + " 3. 1 (true) when case should be ignored, 0 (false) otherwise + " + " [sort]: http://vimdoc.sourceforge.net/htmldoc/eval.html#sort() + let idx = s:binsert_r(a:list, 0, len(a:list), a:value, exists('a:1') && a:1) + return insert(a:list, a:value, idx) +endfunction + +function! s:binsert_r(list, low, high, value, ignorecase) + let mid = a:low + (a:high - a:low) / 2 + if a:low == a:high + return a:low + elseif a:ignorecase ? a:value >? a:list[mid] : a:value > a:list[mid] + return s:binsert_r(a:list, mid + 1, a:high, a:value, a:ignorecase) + elseif a:ignorecase ? a:value +" Last Change: March 15, 2015 +" URL: http://peterodding.com/code/vim/misc/ + +if !exists('g:xolox_message_buffer') + " For when I lose my :messages history :-\ + let g:xolox_message_buffer = 100 +endif + +if !exists('g:xolox_messages') + let g:xolox_messages = [] +endif + +function! xolox#misc#msg#info(...) " {{{1 + " Show a formatted informational message to the user. + " + " This function has the same argument handling as Vim's [printf()] [] + " function with one notable difference: Any arguments which are not numbers + " or strings are coerced to strings using Vim's [string()] [] function. + " + " In the case of `xolox#misc#msg#info()`, automatic string coercion simply + " makes the function a bit easier to use. + " + " The messages emitted by this function have no highlighting. Previously + " these messages were highlighted using the [Title group] [hl-title], but it + " was pointed out in [pull request 16] [pr-16] that this group shouldn't be + " used for informational messages because it is meant for titles and because + " of this some color schemes use colors that stand out quite a bit, causing + " the informational messages to look like errors. + " + " [hl-title]: http://vimdoc.sourceforge.net/htmldoc/syntax.html#hl-Title + " [pr-16]: https://github.com/xolox/vim-misc/pull/16 + " [printf()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#printf() + " [string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string() + call s:show_message('None', a:000) +endfunction + +function! xolox#misc#msg#warn(...) " {{{1 + " Show a formatted warning message to the user. + " + " This function has the same argument handling as the + " `xolox#misc#msg#info()` function. + call s:show_message('WarningMsg', a:000) +endfunction + +function! xolox#misc#msg#debug(...) " {{{1 + " Show a formatted debugging message to the user, *if the user has enabled + " increased verbosity by setting Vim's ['verbose'] [] option to one + " (1) or higher*. + " + " This function has the same argument handling as the + " `xolox#misc#msg#info()` function. + " + " In the case of `xolox#misc#msg#debug()`, automatic string coercion + " provides lazy evaluation in the sense that complex data structures are + " only converted to strings when the user has enabled increased verbosity. + " + " ['verbose']: http://vimdoc.sourceforge.net/htmldoc/options.html#'verbose' + if &vbs >= 1 + call s:show_message('Question', a:000) + endif +endfunction + +function! s:show_message(hlgroup, args) " {{{1 + " The implementation of info() and warn(). + let nargs = len(a:args) + if nargs == 1 + let message = a:args[0] + elseif nargs >= 2 + let args = map(copy(a:args), 's:coerce_argument(v:val)') + let message = call('printf', args) + endif + if exists('message') + try + " Temporarily disable Vim's |hit-enter| prompt and mode display. + if !exists('s:more_save') + let s:more_save = &more + let s:ruler_save = &ruler + let s:smd_save = &showmode + endif + set nomore noshowmode + if winnr('$') == 1 | set noruler | endif + augroup PluginXoloxHideMode + autocmd! CursorHold,CursorHoldI * call s:clear_message() + augroup END + execute 'echohl' a:hlgroup + " Redraw to avoid the |hit-enter| prompt. We use :silent to avoid issues + " like this one: https://github.com/xolox/vim-easytags/issues/69. + silent! redraw + for line in split(message, "\n") + echomsg line + endfor + if g:xolox_message_buffer > 0 + call add(g:xolox_messages, message) + if len(g:xolox_messages) > g:xolox_message_buffer + call remove(g:xolox_messages, 0) + endif + endif + finally + " Always clear message highlighting, even when interrupted by Ctrl-C. + echohl none + endtry + endif +endfunction + +function! s:coerce_argument(value) " {{{1 + " Callback to coerce printf() arguments into strings. + let value_type = type(a:value) + if value_type != type(0) && value_type != type('') + return string(a:value) + else + return a:value + endif +endfunction + +function! s:clear_message() " {{{1 + " Callback to clear message after some time has passed. + echo '' + let &more = s:more_save + let &showmode = s:smd_save + let &ruler = s:ruler_save + unlet s:more_save s:ruler_save s:smd_save + autocmd! PluginXoloxHideMode + augroup! PluginXoloxHideMode +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/open.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/open.vim new file mode 100755 index 00000000..ff0b5e24 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/open.vim @@ -0,0 +1,100 @@ +" Integration between Vim and its environment. +" +" Author: Peter Odding +" Last Change: June 19, 2013 +" URL: http://peterodding.com/code/vim/misc/ + +let s:enoimpl = "vim-misc %s: %s() hasn't been implemented for your platform! If you have suggestions, please get in touch at https://github.com/xolox/vim-misc/issues" +let s:handlers = ['gnome-open', 'kde-open', 'exo-open', 'xdg-open', 'cygstart'] + +function! xolox#misc#open#file(location, ...) " {{{1 + " Given a pathname or URL as the first argument, this opens the file with + " the program associated with the file type. So for example a text file + " might open in Vim, an `*.html` file would probably open in your web + " browser and a media file would open in a media player. + " + " This should work on Windows, Mac OS X and most Linux distributions. If + " this fails to find a file association, you can pass one or more external + " commands to try as additional arguments. For example: + " + " :call xolox#misc#open#file('/path/to/my/file', 'firefox', 'google-chrome') + " + " This generally shouldn't be necessary but it might come in handy now and + " then. + if xolox#misc#os#is_win() + try + call xolox#shell#open_with_windows_shell(a:location) + catch /^Vim\%((\a\+)\)\=:E117/ + let command = '!start CMD /C START "" %s' + silent execute printf(command, xolox#misc#escape#shell(a:location)) + endtry + return + elseif xolox#misc#os#is_mac() + call xolox#misc#msg#debug("vim-misc %s: Detected Mac OS X, using 'open' command to open %s ..", g:xolox#misc#version, string(a:location)) + let cmd = 'open ' . shellescape(a:location) . ' 2>&1' + call s:handle_error(cmd, system(cmd)) + return + else + for handler in s:handlers + a:000 + if executable(handler) + call xolox#misc#msg#debug("vim-misc %s: Using '%s' to open '%s'.", g:xolox#misc#version, handler, a:location) + let cmd = shellescape(handler) . ' ' . shellescape(a:location) . ' 2>&1' + call s:handle_error(cmd, system(cmd)) + return + endif + endfor + endif + throw printf(s:enoimpl, g:xolox#misc#version, 'xolox#misc#open#file') +endfunction + +function! xolox#misc#open#url(url) " {{{1 + " Given a URL as the first argument, this opens the URL in your preferred or + " best available web browser: + " + " - In GUI environments a graphical web browser will open (or a new tab will + " be created in an existing window) + " - In console Vim without a GUI environment, when you have any of `lynx`, + " `links` or `w3m` installed it will launch a command line web browser in + " front of Vim (temporarily suspending Vim) + let url = a:url + if url !~ '^\w\+://' + call xolox#misc#msg#debug("vim-misc %s: The URL %s doesn't contain a scheme, improvising ..", g:xolox#misc#version, string(url)) + if url !~ '@' + call xolox#misc#msg#debug("vim-misc %s: Defaulting to http:// URL scheme ..", g:xolox#misc#version) + let url = 'http://' . url + elseif url !~ '^mailto:' + call xolox#misc#msg#debug("vim-misc %s: Defaulting to mailto: URL scheme ..", g:xolox#misc#version) + let url = 'mailto:' . url + endif + endif + let on_unix = has('unix') + let not_on_mac = !xolox#misc#os#is_mac() + let no_gui_available = (has('gui_running') == 0 && $DISPLAY == '') + if on_unix && not_on_mac && no_gui_available + call xolox#misc#msg#debug("vim-misc %s: Using command line web browser because no GUI seems to be available ..", g:xolox#misc#version) + for browser in ['lynx', 'links', 'w3m'] + call xolox#misc#msg#debug("vim-misc %s: Checking whether %s command line web browser is installed ..", g:xolox#misc#version, string(browser)) + if executable(browser) + call xolox#misc#msg#debug("vim-misc %s: Found %s, using it to open %s ..", g:xolox#misc#version, string(browser), string(url)) + execute '!' . browser fnameescape(url) + call s:handle_error(browser . ' ' . url, '') + return + endif + endfor + endif + call xolox#misc#msg#debug("vim-misc %s: Defaulting to GUI web browser to open %s ..", g:xolox#misc#version, string(url)) + call xolox#misc#open#file(url, 'firefox', 'google-chrome') +endfunction + +function! s:handle_error(cmd, output) " {{{1 + if v:shell_error + let message = "vim-misc %s: Failed to execute program! (command line: %s%s)" + let output = strtrans(xolox#misc#str#trim(a:output)) + if output != '' + let output = ", output: " . string(output) + endif + throw printf(message, g:xolox#misc#version, a:cmd, output) + endif +endfunction + +" vim: et ts=2 sw=2 fdm=marker diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/option.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/option.vim new file mode 100755 index 00000000..47c5f24f --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/option.vim @@ -0,0 +1,116 @@ +" Vim and plug-in option handling. +" +" Author: Peter Odding +" Last Change: April 1, 2015 +" URL: http://peterodding.com/code/vim/misc/ + +function! xolox#misc#option#get(name, ...) " {{{1 + " Expects one or two arguments: 1. The name of a variable and 2. the default + " value if the variable does not exist. + " + " Returns the value of the variable from a buffer local variable, global + " variable or the default value, depending on which is defined. + " + " This is used by some of my Vim plug-ins for option handling, so that users + " can customize options for specific buffers. + if exists('b:' . a:name) + " Buffer local variable. + return eval('b:' . a:name) + elseif exists('g:' . a:name) + " Global variable. + return eval('g:' . a:name) + elseif exists('a:1') + " Default value. + return a:1 + endif +endfunction + +function! xolox#misc#option#split(value) " {{{1 + " Given a multi-value Vim option like ['runtimepath'] [rtp] this returns a + " list of strings. For example: + " + " :echo xolox#misc#option#split(&runtimepath) + " ['/home/peter/Projects/Vim/misc', + " '/home/peter/Projects/Vim/colorscheme-switcher', + " '/home/peter/Projects/Vim/easytags', + " ...] + " + " [rtp]: http://vimdoc.sourceforge.net/htmldoc/options.html#'runtimepath' + let values = split(a:value, '[^\\]\zs,') + return map(values, 's:unescape(v:val)') +endfunction + +function! s:unescape(s) + return substitute(a:s, '\\\([\\,]\)', '\1', 'g') +endfunction + +function! xolox#misc#option#join(values) " {{{1 + " Given a list of strings like the ones returned by + " `xolox#misc#option#split()`, this joins the strings together into a + " single value that can be used to set a Vim option. + let values = copy(a:values) + call map(values, 's:escape(v:val)') + return join(values, ',') +endfunction + +function! s:escape(s) + return escape(a:s, ',\') +endfunction + +function! xolox#misc#option#split_tags(value) " {{{1 + " Customized version of `xolox#misc#option#split()` with specialized + " handling for Vim's ['tags' option] [tags]. + " + " [tags]: http://vimdoc.sourceforge.net/htmldoc/options.html#'tags' + let values = split(a:value, '[^\\]\zs,') + return map(values, 's:unescape_tags(v:val)') +endfunction + +function! s:unescape_tags(s) + return substitute(a:s, '\\\([\\, ]\)', '\1', 'g') +endfunction + +function! xolox#misc#option#join_tags(values) " {{{1 + " Customized version of `xolox#misc#option#join()` with specialized + " handling for Vim's ['tags' option] [tags]. + let values = copy(a:values) + call map(values, 's:escape_tags(v:val)') + return join(values, ',') +endfunction + +function! s:escape_tags(s) + return escape(a:s, ', ') +endfunction + +function! xolox#misc#option#eval_tags(value, ...) " {{{1 + " Evaluate Vim's ['tags' option] [tags] without looking at the file + " system, i.e. this will report tags files that don't exist yet. Expects + " the value of the ['tags' option] [tags] as the first argument. If the + " optional second argument is 1 (true) only the first match is returned, + " otherwise (so by default) a list with all matches is returned. + let pathnames = [] + let first_only = exists('a:1') ? a:1 : 0 + for pattern in xolox#misc#option#split_tags(a:value) + " Make buffer relative pathnames absolute. + if pattern =~ '^\./' + let suffix = matchstr(pattern, '^./\zs.*$') + let directory = (&cpoptions =~# 'd') ? getcwd() : expand('%:p:h') + let pattern = xolox#misc#path#merge(directory, suffix) + endif + " Make working directory relative pathnames absolute. + if xolox#misc#path#is_relative(pattern) + let pattern = xolox#misc#path#merge(getcwd(), pattern) + endif + " Ignore the trailing `;' for recursive upwards searching because we + " always want the most specific pathname available. + let pattern = substitute(pattern, ';$', '', '') + " Expand the pattern. + call extend(pathnames, split(expand(pattern), "\n")) + if first_only && !empty(pathnames) + return pathnames[0] + endif + endfor + return first_only ? '' : pathnames +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/os.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/os.vim new file mode 100755 index 00000000..31e1232e --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/os.vim @@ -0,0 +1,284 @@ +" Operating system interfaces. +" +" Author: Peter Odding +" Last Change: May 21, 2015 +" URL: http://peterodding.com/code/vim/misc/ + +function! xolox#misc#os#is_mac() " {{{1 + " Returns 1 (true) when on Mac OS X, 0 (false) otherwise. You would expect + " this to simply check the Vim feature list, but for some obscure reason the + " `/usr/bin/vim` included in Mac OS X (verified on version 10.7.5) returns 0 + " (false) in response to `has('mac')`, so we check the output of `uname` + " to avoid false negatives. + if !exists('s:is_mac') + " By default we assume we are *not* on Mac OS X. + let s:is_mac = 0 + if has('mac') || has('macunix') || has('gui_mac') + " If Vim's feature list indicates we are on Mac OS X, we have our answer :-). + let s:is_mac = 1 + elseif !xolox#misc#os#is_win() + " Otherwise we check the output of `uname' to avoid false negatives. + let result = xolox#misc#os#exec({'command': 'uname', 'check': 0}) + if result['exit_code'] == 0 && get(result['stdout'], 0, '') == 'Darwin' + let s:is_mac = 1 + endif + endif + endif + return s:is_mac +endfunction + +function! xolox#misc#os#is_win() " {{{1 + " Returns 1 (true) when on Microsoft Windows, 0 (false) otherwise. + return has('win16') || has('win32') || has('win64') +endfunction + +function! xolox#misc#os#find_vim(...) " {{{1 + " Returns the program name of Vim as a string. On Windows and UNIX this just + " [v:progname] [] as an absolute pathname while on Mac OS X there is + " some special magic to find MacVim's executable even though it's usually + " not on the executable search path. If you want, you can override the + " value returned from this function by setting the global variable + " `g:xolox#misc#os#vim_progname`. + " + " By default the choice of console Vim vs graphical Vim is made based on + " the value of [v:progname] [], but if you have a preference you can pass + " the string `vim` or `gvim` as the first and only argument. + " + " [v:progname]: http://vimdoc.sourceforge.net/htmldoc/eval.html#v:progname + if exists('a:1') + let program_name = a:1 + else + let program_name = v:progname + endif + if exists('g:xolox#misc#os#vim_progname') + let pathname = g:xolox#misc#os#vim_progname + else + let pathname = '' + endif + if empty(pathname) && xolox#misc#os#is_mac() + " Special handling for Mac OS X where MacVim is usually not on the $PATH. + " This always returns the "Vim" executable and not "MacVim" (regardless of + " the caller's preference) because "MacVim" has funky dock magic going on. + call xolox#misc#msg#debug("vim-misc %s: Trying MacVim workaround to find Vim executable ..", g:xolox#misc#version) + let segments = xolox#misc#path#split($VIMRUNTIME) + if segments[-3:] == ['Resources', 'vim', 'runtime'] + let pathname = xolox#misc#path#join(segments[0:-4] + ['MacOS', 'Vim']) + call xolox#misc#msg#debug("vim-misc %s: The MacVim workaround resulted in the Vim executable %s.", g:xolox#misc#version, string(pathname)) + endif + endif + if empty(pathname) + " Default logic. + call xolox#misc#msg#debug("vim-misc %s: Looking for Vim executable named %s on search path ..", g:xolox#misc#version, string(program_name)) + let candidates = xolox#misc#path#which(program_name) + if !empty(candidates) + call xolox#misc#msg#debug("vim-misc %s: Found %i candidate(s) on search path: %s.", g:xolox#misc#version, len(candidates), string(candidates)) + let pathname = candidates[0] + endif + endif + call xolox#misc#msg#debug("vim-misc %s: Reporting Vim executable %s.", g:xolox#misc#version, string(pathname)) + return pathname +endfunction + +function! xolox#misc#os#exec(options) " {{{1 + " Execute an external command (hiding the console on Microsoft Windows when + " my [vim-shell plug-in] [vim-shell] is installed). + " + " Expects a dictionary with the following key/value pairs as the first + " argument: + " + " - **command** (required): The command line to execute + " - **async** (optional): set this to 1 (true) to execute the command in the + " background (asynchronously) + " - **stdin** (optional): a string or list of strings with the input for the + " external command + " - **check** (optional): set this to 0 (false) to disable checking of the + " exit code of the external command (by default an exception will be + " raised when the command fails) + " + " Returns a dictionary with one or more of the following key/value pairs: + " + " - **command** (always available): the generated command line that was used + " to run the external command + " - **exit_code** (only in synchronous mode): the exit status of the + " external command (an integer, zero on success) + " - **stdout** (only in synchronous mode): the output of the command on the + " standard output stream (a list of strings, one for each line) + " - **stderr** (only in synchronous mode): the output of the command on the + " standard error stream (as a list of strings, one for each line) + " + " [vim-shell]: http://peterodding.com/code/vim/shell/ + try + + " Unpack the options. + let cmd = a:options['command'] + let async = get(a:options, 'async', 0) + + " We need to know in a couple of places whether we are on Windows. + let is_win = xolox#misc#os#is_win() + + " Use vim-shell so we don't pop up a console window on Windows? If the + " caller specifically asks us *not* to use vim-shell, we'll respect that + " choice; this is very useful for automated tests :-). + if get(a:options, 'use_dll', 1) == 0 + let use_dll = 0 + else + let use_dll = xolox#misc#os#can_use_dll() + endif + + " Decide whether to redirect the standard output and standard error + " streams to temporary files. + let redirect_output = !async && (use_dll || !is_win) + + " Write the input for the external command to a temporary file? + if has_key(a:options, 'stdin') && use_dll + let tempin = tempname() + if type(a:options['stdin']) == type([]) + let lines = a:options['stdin'] + else + let lines = split(a:options['stdin'], "\n") + endif + call writefile(lines, tempin) + let cmd .= ' < ' . xolox#misc#escape#shell(tempin) + endif + + " Redirect the standard output and/or standard error streams of the + " external process to temporary files? (only in synchronous mode) + if redirect_output + let tempout = tempname() + let temperr = tempname() + let cmd = printf('(%s) 1>%s 2>%s', cmd, xolox#misc#escape#shell(tempout), xolox#misc#escape#shell(temperr)) + endif + + " Use vim-shell or system() to execute the external command? + if use_dll + call xolox#misc#msg#debug("vim-misc %s: Executing external command using compiled DLL: %s", g:xolox#misc#version, cmd) + let exit_code = xolox#shell#execute_with_dll(cmd, async) + else + + " Enable asynchronous mode (very platform specific). + if async + if is_win + " As pointed out in issue 17 [1] the use of `:!start' on Windows + " requires characters like `!', `%' and `#' to be escaped with a + " backslash [2]. Vim's shellescape() function knows how to escape + " these special characters however the use of `:!start' is an + " implementation detail of xolox#misc#os#exec() so I don't want to + " bother callers (who perform the shell escaping) with such a + " specific implementation detail. This is why I resort to manually + " escaping characters documented to have a special meaning [2]. + " + " [1] https://github.com/xolox/vim-misc/issues/17 + " [2] All characters interpreted specially in shell command lines + " executed from Vim's command mode, refer to `:help :!' for + " details. + let cmd = printf('start /b %s', escape(cmd, "\\\n!%#")) + elseif has('unix') + let cmd = printf('(%s) &', cmd) + else + call xolox#misc#msg#warn("vim-misc %s: I don't know how to execute the command %s asynchronously on your platform! Falling back to synchronous mode...", g:xolox#misc#version, cmd) + endif + endif + + " On UNIX we explicitly execute the command line using 'sh' instead of + " the default shell, because we assume that standard output and standard + " error can be redirected separately, but (t)csh does not support this + " (and it might be the default shell). + if has('unix') + call xolox#misc#msg#debug("vim-misc %s: Generated shell expression: %s", g:xolox#misc#version, cmd) + let cmd = printf('sh -c %s', xolox#misc#escape#shell(cmd)) + endif + + " Let the user know what's happening (in case they're interested). + if async && is_win + call xolox#misc#msg#debug("vim-misc %s: Executing external command using !start command: %s", g:xolox#misc#version, cmd) + silent execute '!' . cmd + else + call xolox#misc#msg#debug("vim-misc %s: Executing external command using system() function: %s", g:xolox#misc#version, cmd) + let arguments = [cmd] + if has_key(a:options, 'stdin') + if type(a:options['stdin']) == type([]) + call add(arguments, join(a:options['stdin'], "\n")) + else + call add(arguments, a:options['stdin']) + endif + endif + let stdout = call('system', arguments) + let exit_code = v:shell_error + endif + + endif + + " Return the results as a dictionary with one or more key/value pairs. + let result = {'command': cmd} + if !async + let result['exit_code'] = exit_code + " Get the standard output of the command. + if redirect_output + let result['stdout'] = s:readfile(tempout, 'standard output', a:options['command']) + elseif exists('stdout') + let result['stdout'] = split(stdout, "\n") + else + let result['stdout'] = [] + endif + " Get the standard error of the command. + if exists('temperr') + let result['stderr'] = s:readfile(temperr, 'standard error', a:options['command']) + else + let result['stderr'] = [] + endif + " If we just executed a synchronous command and the caller didn't + " specifically ask us *not* to check the exit code of the external + " command, we'll do so now. The idea here is that it should be easy + " to 'do the right thing'. + if get(a:options, 'check', 1) && exit_code != 0 + " Prepare an error message with enough details so the user can investigate. + let msg = printf("vim-misc %s: External command failed with exit code %d!", g:xolox#misc#version, result['exit_code']) + let msg .= printf("\nCommand line: %s", result['command']) + " If the external command reported an error, we'll include it in our message. + if !empty(result['stderr']) + " This is where we would normally expect to find an error message. + let msg .= printf("\nOutput on standard output stream:\n%s", join(result['stderr'], "\n")) + elseif !empty(result['stdout']) + " Exuberant Ctags on Windows XP reports errors on standard output :-x. + let msg .= printf("\nOutput on standard error stream:\n%s", join(result['stdout'], "\n")) + endif + throw msg + endif + endif + return result + + finally + " Cleanup any temporary files we created. + for name in ['tempin', 'tempout', 'temperr'] + if exists(name) + call delete({name}) + endif + endfor + endtry + +endfunction + +function! xolox#misc#os#can_use_dll() " {{{1 + " If a) we're on Microsoft Windows, b) the vim-shell plug-in is installed + " and c) the compiled DLL included in vim-shell works, we can use the + " vim-shell plug-in to execute external commands! Returns 1 (true) + " if we can use the DLL, 0 (false) otherwise. + let can_use_dll = 0 + try + let can_use_dll = xolox#shell#can_use_dll() + catch /^Vim\%((\a\+)\)\=:E117/ + " Silence E117. + endtry + return can_use_dll +endfunction + +function! s:readfile(fname, label, cmd) " {{{1 + try + return readfile(a:fname) + catch + call xolox#misc#msg#warn("vim-misc %s: Failed to read temporary file (%s) with %s of external command: %s! (external command: %s)", g:xolox#misc#version, a:fname, a:label, v:exception, a:cmd) + return [] + endtry +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/path.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/path.vim new file mode 100755 index 00000000..6ff55894 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/path.vim @@ -0,0 +1,278 @@ +" Pathname manipulation functions. +" +" Author: Peter Odding +" Last Change: July 7, 2014 +" URL: http://peterodding.com/code/vim/misc/ + +let s:windows_compatible = xolox#misc#os#is_win() + +function! xolox#misc#path#which(...) " {{{1 + " Scan the executable search path (`$PATH`) for one or more external + " programs. Expects one or more string arguments with program names. Returns + " a list with the absolute pathnames of all found programs. Here's an + " example: + " + " :echo xolox#misc#path#which('gvim', 'vim') + " ['/usr/local/bin/gvim', + " '/usr/bin/gvim', + " '/usr/local/bin/vim', + " '/usr/bin/vim'] + let extensions = s:windows_compatible ? split($PATHEXT, ';') : [''] + let matches = [] + let checked = {} + for program in a:000 + for directory in split($PATH, s:windows_compatible ? ';' : ':') + let directory = xolox#misc#path#absolute(directory) + if isdirectory(directory) + let found = 0 + for extension in extensions + let path = xolox#misc#path#merge(directory, program . extension) + if executable(path) + call add(matches, path) + let found = 1 + endif + endfor + if s:windows_compatible && ! found + " Maybe the extension is already contained in program; try without + " $PATHEXT. + let path = xolox#misc#path#merge(directory, program) + if executable(path) + call add(matches, path) + endif + endif + endif + endfor + endfor + return xolox#misc#list#unique(matches) +endfunction + +function! xolox#misc#path#split(path) " {{{1 + " Split a pathname (the first and only argument) into a list of pathname + " components. + " + " On Windows, pathnames starting with two slashes or backslashes are UNC + " paths where the leading slashes are significant... In this case we split + " like this: + " + " - Input: `'//server/share/directory'` + " - Result: `['//server', 'share', 'directory']` + " + " Everything except Windows is treated like UNIX until someone has a better + " suggestion :-). In this case we split like this: + " + " - Input: `'/foo/bar/baz'` + " - Result: `['/', 'foo', 'bar', 'baz']` + " + " To join a list of pathname components back into a single pathname string, + " use the `xolox#misc#path#join()` function. + if type(a:path) == type('') + if s:windows_compatible + if a:path =~ '^[\/][\/]' + " UNC pathname. + return split(a:path, '\%>2c[\/]\+') + else + " If it's not a UNC pathname we can simply split on slashes and + " backslashes, although we should preserve a leading slash (which + " denotes a pathname that is 'absolute to the current drive'). + let absolute = (a:path =~ '^[\/]') + let segments = split(a:path, '[\/]\+') + return absolute ? insert(segments, a:path[0]) : segments + endif + else + " Everything else is treated as UNIX. + let absolute = (a:path =~ '^/') + let segments = split(a:path, '/\+') + return absolute ? insert(segments, '/') : segments + endif + endif + return [] +endfunction + +function! xolox#misc#path#join(parts) " {{{1 + " Join a list of pathname components (the first and only argument) into a + " single pathname string. This is the counterpart to the + " `xolox#misc#path#split()` function and it expects a list of pathname + " components as returned by `xolox#misc#path#split()`. + if type(a:parts) == type([]) + if s:windows_compatible + return join(a:parts, xolox#misc#path#directory_separator()) + elseif get(a:parts, 0) == '/' + " Absolute path on UNIX (non-Windows). + return '/' . join(a:parts[1:], '/') + else + " Relative path on UNIX (non-Windows). + return join(a:parts, '/') + endif + endif + return '' +endfunction + +function! xolox#misc#path#directory_separator() " {{{1 + " Find the preferred directory separator for the platform and settings. + return exists('+shellslash') && &shellslash ? '/' : '\' +endfunction + +function! xolox#misc#path#absolute(path) " {{{1 + " Canonicalize and resolve a pathname, *regardless of whether it exists*. + " This is intended to support string comparison to determine whether two + " pathnames point to the same directory or file. + if type(a:path) == type('') + let path = a:path + " Make the pathname absolute. + if path =~ '^\~' + " Expand ~ to $HOME. + let path = $HOME . '/' . path[1:] + elseif xolox#misc#path#is_relative(path) + " Make relative pathnames absolute. + let path = getcwd() . '/' . path + endif + " Resolve symbolic links to find the canonical pathname. In my tests this + " also removes all symbolic pathname segments (`.' and `..'), even when + " the pathname does not exist. Also there used to be a bug in resolve() + " where it wouldn't resolve pathnames ending in a directory separator. + " Since it's not much trouble to work around, that's what we do. + let path = resolve(substitute(path, s:windows_compatible ? '[\/]\+$' : '/\+$', '', '')) + " Normalize directory separators (especially relevant on Windows). + let parts = xolox#misc#path#split(path) + if s:windows_compatible && parts[0] =~ '^[\/][\/]' + " Also normalize the two leading "directory separators" (I'm not + " sure what else to call them :-) in Windows UNC pathnames. + let parts[0] = repeat(xolox#misc#path#directory_separator(), 2) . parts[0][2:] + elseif s:windows_compatible && parts[0] =~ '^[\/]$' + " If a pathname is relative to the current drive we should add + " the drive letter in order to make the pathname absolute. + let parts[0] = matchstr(getcwd(), '^\a:') + endif + return xolox#misc#path#join(parts) + endif + return '' +endfunction + +function! xolox#misc#path#relative(path, base) " {{{1 + " Make an absolute pathname (the first argument) relative to a directory + " (the second argument). + let path = xolox#misc#path#split(a:path) + let base = xolox#misc#path#split(a:base) + while path != [] && base != [] && path[0] == base[0] + call remove(path, 0) + call remove(base, 0) + endwhile + let distance = repeat(['..'], len(base)) + return xolox#misc#path#join(distance + path) +endfunction + +function! xolox#misc#path#merge(parent, child, ...) " {{{1 + " Join a directory pathname and filename into a single pathname. + if type(a:parent) == type('') && type(a:child) == type('') + " TODO Use xolox#misc#path#is_relative()? + if s:windows_compatible + let parent = substitute(a:parent, '[\\/]\+$', '', '') + let child = substitute(a:child, '^[\\/]\+', '', '') + return parent . '\' . child + else + let parent = substitute(a:parent, '/\+$', '', '') + let child = substitute(a:child, '^/\+', '', '') + return parent . '/' . child + endif + endif + return '' +endfunction + +function! xolox#misc#path#commonprefix(paths) " {{{1 + " Find the common prefix of path components in a list of pathnames. + let common = xolox#misc#path#split(a:paths[0]) + for path in a:paths + let index = 0 + for segment in xolox#misc#path#split(path) + if len(common) <= index + break + elseif common[index] != segment + call remove(common, index, -1) + break + endif + let index += 1 + endfor + endfor + return xolox#misc#path#join(common) +endfunction + +function! xolox#misc#path#starts_with(a, b) " {{{1 + " Check whether the first pathname starts with the second pathname (expected + " to be a directory). This does not perform a regular string comparison; + " first it normalizes both pathnames, then it splits them into their + " pathname segments and then it compares the segments. + let a = xolox#misc#path#split(xolox#misc#path#absolute(a:a)) + let b = xolox#misc#path#split(xolox#misc#path#absolute(a:b)) + return a[0 : len(b) - 1] == b +endfunction + +function! xolox#misc#path#encode(path) " {{{1 + " Encode a pathname so it can be used as a filename. This uses URL encoding + " to encode special characters. + if s:windows_compatible + let mask = '[*|\\/:"<>?%]' + elseif xolox#misc#os#is_mac() + let mask = '[\\/%:]' + else + let mask = '[\\/%]' + endif + return substitute(a:path, mask, '\=printf("%%%x", char2nr(submatch(0)))', 'g') +endfunction + +function! xolox#misc#path#decode(encoded_path) " {{{1 + " Decode a pathname previously encoded with `xolox#misc#path#encode()`. + return substitute(a:encoded_path, '%\(\x\x\?\)', '\=nr2char("0x" . submatch(1))', 'g') +endfunction + +" xolox#misc#path#equals(a, b) - Check whether two pathnames point to the same file. {{{1 + +if s:windows_compatible + function! xolox#misc#path#equals(a, b) + return a:a ==? a:b || xolox#misc#path#absolute(a:a) ==? xolox#misc#path#absolute(a:b) + endfunction +else + function! xolox#misc#path#equals(a, b) + return a:a ==# a:b || xolox#misc#path#absolute(a:a) ==# xolox#misc#path#absolute(a:b) + endfunction +endif + +function! xolox#misc#path#is_relative(path) " {{{1 + " Returns true (1) when the pathname given as the first argument is + " relative, false (0) otherwise. + if a:path =~ '^\w\+://' + return 0 + elseif s:windows_compatible + return a:path !~ '^\(\w:\|[\\/]\)' + else + return a:path !~ '^/' + endif +endfunction + +function! xolox#misc#path#tempdir() " {{{1 + " Create a temporary directory and return the pathname of the directory. + if !exists('s:tempdir_counter') + let s:tempdir_counter = 1 + endif + if exists('*mkdir') + if s:windows_compatible + let template = $TMP . '\vim_tempdir_' + elseif filewritable('/tmp') == 2 + let template = '/tmp/vim_tempdir_' + endif + endif + if !exists('template') + throw "xolox#misc#path#tempdir() hasn't been implemented on your platform!" + endif + while 1 + let directory = template . s:tempdir_counter + try + call mkdir(directory, '', 0700) + return directory + catch /^Vim\%((\a\+)\)\=:E739/ + " Keep looking for a non-existing directory. + endtry + let s:tempdir_counter += 1 + endwhile +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/perm.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/perm.vim new file mode 100755 index 00000000..851a74d1 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/perm.vim @@ -0,0 +1,100 @@ +" Manipulation of UNIX file permissions. +" +" Author: Peter Odding +" Last Change: June 30, 2014 +" URL: http://peterodding.com/code/vim/misc/ +" +" Vim's [writefile()][] function cannot set file permissions for newly created +" files and although Vim script has a function to get file permissions (see +" [getfperm()][]) there is no equivalent for changing a file's permissions. +" +" This omission breaks the otherwise very useful idiom of updating a file by +" writing its new contents to a temporary file and then renaming the temporary +" file into place (which is as close as you're going to get to atomically +" updating a file's contents on UNIX) because the file's permissions will not +" be preserved! +" +" **Here's a practical example:** My [vim-easytags][] plug-in writes tags file +" updates to a temporary file and renames the temporary file into place. When +" I use `sudo -s` on Ubuntu Linux it preserves my environment variables so my +" `~/.vimrc` and the [vim-easytags][] plug-in are still loaded. Now when a +" tags file is written the file becomes owned by root (my effective user id in +" the `sudo` session). Once I leave the `sudo` session I can no longer update +" my tags file because it's now owned by root … ಠ_ಠ +" +" [getfperm()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#getfperm() +" [vim-easytags]: http://peterodding.com/code/vim/easytags/ +" [writefile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#writefile() + +function! xolox#misc#perm#update(fname, contents) + " Atomically update a file's contents while preserving the owner, group and + " mode. The first argument is the pathname of the file to update (a string). + " The second argument is the list of lines to be written to the file. Writes + " the new contents to a temporary file and renames the temporary file into + " place, thereby preventing readers from reading a partially written file. + " Returns 1 if the file is successfully updated, 0 otherwise. + " + " Note that if `xolox#misc#perm#get()` and `xolox#misc#perm#set()` cannot be + " used to preserve the file owner/group/mode the file is still updated using + " a rename (for compatibility with non-UNIX systems and incompatible + " `/usr/bin/stat` implementations) so in that case you can still lose the + " file's owner/group/mode. + let starttime = xolox#misc#timer#start() + let temporary_file = printf('%s.tmp', a:fname) + call xolox#misc#msg#debug("vim-misc %s: Writing new contents of %s to temporary file %s ..", g:xolox#misc#version, a:fname, temporary_file) + if writefile(a:contents, temporary_file) == 0 + call xolox#misc#perm#set(temporary_file, xolox#misc#perm#get(a:fname)) + call xolox#misc#msg#debug("vim-misc %s: Replacing %s with %s ..", g:xolox#misc#version, a:fname, temporary_file) + if rename(temporary_file, a:fname) == 0 + call xolox#misc#timer#stop("vim-misc %s: Successfully updated %s using atomic rename in %s.", g:xolox#misc#version, a:fname, starttime) + return 1 + endif + endif + if filereadable(temporary_file) + call delete(temporary_file) + endif + return 0 +endfunction + +function! xolox#misc#perm#get(fname) + " Get the owner, group and permissions of the pathname given as the first + " argument. Returns an opaque value which you can later pass to + " `xolox#misc#perm#set()`. + let pathname = xolox#misc#path#absolute(a:fname) + if filereadable(pathname) + let command = printf('stat --format %s %s', '%U:%G:%a', shellescape(pathname)) + let result = xolox#misc#os#exec({'command': command, 'check': 0}) + if result['exit_code'] == 0 && len(result['stdout']) >= 1 + let tokens = split(result['stdout'][0], ':') + if len(tokens) == 3 + let [owner, group, mode] = tokens + let mode = '0' . mode + call xolox#misc#msg#debug("vim-misc %s: File %s has owner %s, group %s, mode %s.", g:xolox#misc#version, pathname, owner, group, mode) + return [owner, group, mode] + endif + endif + endif + return [] +endfunction + +function! xolox#misc#perm#set(fname, perms) + " Set the permissions (the second argument) of the pathname given as the + " first argument. Expects a permissions value created by + " `xolox#misc#perm#get()`. + if !empty(a:perms) + let pathname = xolox#misc#path#absolute(a:fname) + let [owner, group, mode] = a:perms + if s:run('chown %s:%s %s', owner, group, pathname) && s:run('chmod %s %s', mode, pathname) + call xolox#misc#msg#debug("vim-misc %s: Successfully set %s owner to %s, group to %s and permissions to %s.", g:xolox#misc#version, pathname, owner, group, mode) + return 1 + endif + endif + return 0 +endfunction + +function! s:run(command, ...) + let args = map(copy(a:000), 'shellescape(v:val)') + call insert(args, a:command, 0) + let result = xolox#misc#os#exec({'command': call('printf', args), 'check': 0}) + return result['exit_code'] == 0 +endfunction diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/persist.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/persist.vim new file mode 100755 index 00000000..5b628fbf --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/persist.vim @@ -0,0 +1,50 @@ +" Persist/recall Vim values from/to files. +" +" Author: Peter Odding +" Last Change: June 30, 2014 +" URL: http://peterodding.com/code/vim/misc/ +" +" Vim's [string()][] function can be used to serialize Vim script values like +" numbers, strings, lists, dictionaries and composites of them to a string +" which can later be evaluated using the [eval()][] function to turn it back +" into the original value. This Vim script provides functions to use these +" functions to persist and recall Vim values from/to files. This is very +" useful for communication between (possibly concurrent) Vim processes. + +function! xolox#misc#persist#load(filename, ...) " {{{1 + " Read a Vim value like a number, string, list or dictionary from a file + " using [readfile()][] and [eval()][]. The first argument is the filename of + " the file to read (a string). The optional second argument specifies the + " default value which is returned when the file can't be loaded. This + " function returns the loaded value or the default value (which itself + " defaults to the integer 0). + " + " [eval()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#eval() + " [readfile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#readfile() + let default_value = exists('a:1') ? a:1 : 0 + try + let lines = readfile(a:filename) + return eval(join(lines, "\n")) + catch + return default_value + endtry +endfunction + +function! xolox#misc#persist#save(filename, value) " {{{1 + " Write a Vim value like a number, string, list or dictionary to a file + " using [string()][] and [writefile()][]. The first argument is the filename + " of the file to write (a string) and the second argument is the value to + " write (any value). + " + " This function writes the serialized value to an intermediate file which is + " then renamed into place atomically. This avoids issues with concurrent + " processes where for example a producer has written a partial file which is + " read by a consumer before the file is complete. In this case the consumer + " would read a corrupt value. The rename trick avoids this problem. + " + " [string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string() + " [writefile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#writefile() + return xolox#misc#perm#update(a:filename, split(string(a:value), "\n")) +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/str.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/str.vim new file mode 100755 index 00000000..edcab137 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/str.vim @@ -0,0 +1,74 @@ +" String handling. +" +" Author: Peter Odding +" Last Change: September 17, 2014 +" URL: http://peterodding.com/code/vim/misc/ + +function! xolox#misc#str#slug(s) " {{{1 + " Convert a string to a "slug" - something that can be safely used in + " filenames and URLs without worrying about quoting/escaping of special + " characters. + return join(split(tolower(a:s), '\W\+'), '-') +endfunction + +function! xolox#misc#str#ucfirst(s) " {{{1 + " Uppercase the first character in a string (the first argument). + return substitute(a:s, '^.', '\U\0', '') +endfunction + +function! xolox#misc#str#unescape(s) " {{{1 + " Remove back slash escapes from a string (the first argument). + return substitute(a:s, '\\\(\_.\)', '\1', 'g') +endfunction + +function! xolox#misc#str#compact(s) " {{{1 + " Compact whitespace in a string (the first argument). + return join(split(a:s), " ") +endfunction + +function! xolox#misc#str#trim(s) " {{{1 + " Trim all whitespace from the start and end of a string (the first + " argument). + return substitute(a:s, '^\_s*\(.\{-}\)\_s*$', '\1', '') +endfunction + +function! xolox#misc#str#indent(text, num_spaces) " {{{1 + " Indent all lines in a multi-line string (the first argument) with a + " specific number of *space characters* (the second argument, an integer). + let lines = split(a:text, "\n") + let indent = repeat(' ', a:num_spaces) + let [idx, limit] = [0, len(lines)] + while idx < limit + if lines[idx] =~ '\S' + let lines[idx] = indent . lines[idx] + endif + let idx += 1 + endwhile + return join(lines, "\n") +endfunction + +function! xolox#misc#str#dedent(text) " {{{1 + " Remove common whitespace from a multi line string. + let lines = split(a:text, "\n") + " First we need to determine the common indentation of all non-empty lines. + for line in lines + if line =~ '\S' + let indent = matchstr(line, '^\s*') + if !exists('common_indent') + let common_indent = indent + elseif len(indent) < len(common_indent) + let common_indent = indent + endif + endif + endfor + " Now we will strip the common indentation. + let [idx, limit] = [0, len(lines)] + let pattern = '^' . common_indent + while idx < limit + let lines[idx] = substitute(lines[idx], pattern, '', '') + let idx += 1 + endwhile + return join(lines, "\n") +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/test.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/test.vim new file mode 100755 index 00000000..df4d4651 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/test.vim @@ -0,0 +1,125 @@ +" Test runner & infrastructure for Vim plug-ins. +" +" Author: Peter Odding +" Last Change: June 2, 2013 +" URL: http://peterodding.com/code/vim/misc/ +" +" The Vim auto-load script `autoload/xolox/misc/test.vim` contains +" infrastructure that can be used to run an automated Vim plug-in test suite. +" It provides a framework for running test functions, keeping track of the +" test status, making assertions and reporting test results to the user. + +" The process handling tests cannot use the built-in "echo" command from the +" Windows shell because it has way too much idiosyncrasies for me to put up +" with. Seriously. Instead I'm using an "echo.exe" from the UnxUtils project. +if xolox#misc#os#is_win() + let g:xolox#misc#test#echo = xolox#misc#escape#shell(xolox#misc#path#merge(expand(':p:h'), 'echo.exe')) +else + let g:xolox#misc#test#echo = 'echo' +endif + +function! xolox#misc#test#reset() " {{{1 + " Reset counters for executed tests and passed/failed assertions. + let s:num_executed = 0 + let s:num_passed = 0 + let s:num_failed = 0 + let s:tests_started_at = xolox#misc#timer#start() +endfunction + +function! xolox#misc#test#summarize() " {{{1 + " Print a summary of test results, to be interpreted interactively. + call s:delimit_output() + call xolox#misc#timer#force("Took %s to run %s: %s passed, %s failed.", + \ s:tests_started_at, + \ xolox#misc#format#pluralize(s:num_executed, 'test', 'tests'), + \ xolox#misc#format#pluralize(s:num_passed, 'assertion', 'assertions'), + \ xolox#misc#format#pluralize(s:num_failed, 'assertion', 'assertions')) +endfunction + +function! xolox#misc#test#wrap(function) " {{{1 + " Call a function in a try/catch block and prevent exceptions from bubbling. + " The name of the function should be passed as the first and only argument; + " it should be a string containing the name of a Vim auto-load function. + let num_failed = s:num_failed + try + if s:num_passed + s:num_failed > 0 + call s:delimit_output() + endif + let test_name = split(a:function, '#')[-1] + let test_name = substitute(test_name, '_', ' ', 'g') + let test_name = substitute(test_name, '^.', '\U\0', '') + call xolox#misc#msg#info("Running test #%i: %s", s:num_executed + 1, test_name) + call call(a:function, []) + catch + call xolox#misc#msg#warn("Test %s raised exception:", a:function) + call xolox#misc#msg#warn("%s", v:exception) + call xolox#misc#msg#warn("(at %s)", v:throwpoint) + if num_failed == s:num_failed + " Make sure exceptions are counted as failures, but don't inflate the + " number of failed assertions when it's not needed (it can produce + " confusing test output). + call xolox#misc#test#failed() + endif + endtry + let s:num_executed += 1 +endfunction + +function! xolox#misc#test#passed() " {{{1 + " Record a test which succeeded. + let s:num_passed += 1 + call s:print_feedback() +endfunction + +function! xolox#misc#test#failed() " {{{1 + " Record a test which failed. + let s:num_failed += 1 + call s:print_feedback() +endfunction + +function! s:delimit_output() " {{{1 + " Print a delimiter between output of tests. + call xolox#misc#msg#info("%s", repeat("-", 40)) +endfunction + +function! s:print_feedback() " {{{1 + " Let the user know the status of the test suite. + call xolox#misc#msg#info("Test status: %s passed, %s failed ..", + \ xolox#misc#format#pluralize(s:num_passed, 'assertion', 'assertions'), + \ xolox#misc#format#pluralize(s:num_failed, 'assertion', 'assertions')) +endfunction + +function! xolox#misc#test#assert_true(expr) " {{{1 + " Check whether an expression is true. + if a:expr + call xolox#misc#test#passed() + else + call xolox#misc#test#failed() + let msg = "Expected value to be true, got %s instead" + throw printf(msg, string(a:expr)) + endif +endfunction + +function! xolox#misc#test#assert_equals(expected, received) " {{{1 + " Check whether two values are the same. + call xolox#misc#test#assert_same_type(a:expected, a:received) + if a:expected == a:received + call xolox#misc#test#passed() + else + call xolox#misc#test#failed() + let msg = "Expected value %s, received value %s!" + throw printf(msg, string(a:expected), string(a:received)) + endif +endfunction + +function! xolox#misc#test#assert_same_type(expected, received) " {{{1 + " Check whether two values are of the same type. + if type(a:expected) == type(a:received) + call xolox#misc#test#passed() + else + call xolox#misc#test#failed() + let msg = "Expected value of same type as %s, got value %s!" + throw printf(msg, string(a:expected), string(a:received)) + endif +endfunction + +call xolox#misc#test#reset() diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/tests.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/tests.vim new file mode 100755 index 00000000..f3af1cb8 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/tests.vim @@ -0,0 +1,301 @@ +" Tests for the miscellaneous Vim scripts. +" +" Author: Peter Odding +" Last Change: June , 2013 +" URL: http://peterodding.com/code/vim/misc/ +" +" The Vim auto-load script `autoload/xolox/misc/tests.vim` contains the +" automated test suite of the miscellaneous Vim scripts. Right now the +" coverage is not very high yet, but this will improve over time. + +let s:use_dll = 0 +let s:can_use_dll = xolox#misc#os#can_use_dll() + +function! xolox#misc#tests#run() " {{{1 + " Run the automated test suite of the miscellaneous Vim scripts. To be used + " interactively. Intended to be safe to execute irrespective of context. + call xolox#misc#test#reset() + " Run the tests. + call s:test_string_escaping() + call s:test_list_handling() + call s:test_option_handling() + call s:test_command_execution() + call s:test_string_handling() + call s:test_version_handling() + " Report a short summary to the user. + call xolox#misc#test#summarize() +endfunction + +function! s:wrap_exec_test(function) + " Wrapper for tests that use xolox#misc#os#exec(). If we're on Windows and + " the vim-shell plug-in is installed, the test will be run twice: Once with + " vim-shell disabled and once with vim-shell enabled. This makes sure that + " all code paths are tested as much as possible. + call xolox#misc#msg#debug("vim-misc %s: Temporarily disabling vim-shell so we can test vim-misc ..", g:xolox#misc#version) + let s:use_dll = 0 + call xolox#misc#test#wrap(a:function) + if s:can_use_dll + call xolox#misc#msg#debug("vim-misc %s: Re-enabling vim-shell so we can test that as well ..", g:xolox#misc#version) + let s:use_dll = 1 + call xolox#misc#test#wrap(a:function) + endif +endfunction + +" Tests for autoload/xolox/misc/escape.vim {{{1 + +function! s:test_string_escaping() + call xolox#misc#test#wrap('xolox#misc#tests#pattern_escaping') + call xolox#misc#test#wrap('xolox#misc#tests#substitute_escaping') + call s:wrap_exec_test('xolox#misc#tests#shell_escaping') +endfunction + +function! xolox#misc#tests#pattern_escaping() " {{{2 + " Test escaping of regular expression patterns with + " `xolox#misc#escape#pattern()`. + call xolox#misc#test#assert_equals('foo [qux] baz', substitute('foo [bar] baz', xolox#misc#escape#pattern('[bar]'), '[qux]', 'g')) + call xolox#misc#test#assert_equals('also very nasty', substitute('also ~ nasty', xolox#misc#escape#pattern('~'), 'very', 'g')) +endfunction + +function! xolox#misc#tests#substitute_escaping() " {{{2 + " Test escaping of substitution strings with + " `xolox#misc#escape#substitute()`. + call xolox#misc#test#assert_equals('nasty & tricky stuff', substitute('tricky stuff', 'tricky', xolox#misc#escape#substitute('nasty & tricky'), 'g')) +endfunction + +function! xolox#misc#tests#shell_escaping() " {{{2 + " Test escaping of shell arguments with `xolox#misc#escape#shell()`. + let expected_value = 'this < is > a | very " scary ^ string '' indeed' + let result = xolox#misc#os#exec({'command': g:xolox#misc#test#echo . ' ' . xolox#misc#escape#shell(expected_value), 'use_dll': s:use_dll}) + call xolox#misc#test#assert_equals(0, result['exit_code']) + call xolox#misc#test#assert_equals(0, result['exit_code']) + call xolox#misc#test#assert_same_type([], result['stdout']) + call xolox#misc#test#assert_equals(1, len(result['stdout'])) + " XXX On Windows using system() there's a trailing space I can't explain. + " However the point of this test was to show that all characters pass + " through unharmed, so for now I'll just ignore the space :-) + call xolox#misc#test#assert_equals(expected_value, xolox#misc#str#trim(result['stdout'][0])) +endfunction + +" Tests for autoload/xolox/misc/list.vim {{{1 + +function! s:test_list_handling() + call xolox#misc#test#wrap('xolox#misc#tests#making_a_list_unique') + call xolox#misc#test#wrap('xolox#misc#tests#binary_insertion') +endfunction + +function! xolox#misc#tests#making_a_list_unique() " {{{2 + " Test removing of duplicate values from lists with + " `xolox#misc#list#unique()`. + call xolox#misc#test#assert_equals([1, 2, 3, 4, 5], xolox#misc#list#unique([1, 1, 2, 3, 3, 4, 5, 5])) + " Should work for strings just as well. And it should preserve order. + call xolox#misc#test#assert_equals(['a', 'b', 'c'], xolox#misc#list#unique(['a', 'a', 'b', 'b', 'c'])) + " Just to make sure that lists without duplicate values pass through unharmed. + call xolox#misc#test#assert_equals([1, 2, 3, 4, 5], xolox#misc#list#unique([1, 2, 3, 4, 5])) +endfunction + +function! xolox#misc#tests#binary_insertion() " {{{2 + " Test the binary insertion algorithm implemented in + " `xolox#misc#list#binsert()`. + let list = ['a', 'B', 'e'] + " Insert 'c' (should end up between 'B' and 'e'). + call xolox#misc#list#binsert(list, 'c', 1) + call xolox#misc#test#assert_equals(['a', 'B', 'c', 'e'], list) + " Insert 'D' (should end up between 'c' and 'e'). + call xolox#misc#list#binsert(list, 'D', 1) + call xolox#misc#test#assert_equals(['a', 'B', 'c', 'D', 'e'], list) + " Insert 'f' (should end up after 'e', at the end). + call xolox#misc#list#binsert(list, 'f', 1) + call xolox#misc#test#assert_equals(['a', 'B', 'c', 'D', 'e', 'f'], list) +endfunction + +" Tests for autoload/xolox/misc/option.vim {{{1 + +function! s:test_option_handling() + call xolox#misc#test#wrap('xolox#misc#tests#getting_configuration_options') + call xolox#misc#test#wrap('xolox#misc#tests#splitting_of_multi_valued_options') + call xolox#misc#test#wrap('xolox#misc#tests#joining_of_multi_valued_options') +endfunction + +function! xolox#misc#tests#getting_configuration_options() " {{{2 + " Test getting of scoped plug-in configuration "options" with + " `xolox#misc#option#get()`. + let magic_name = 'a_variable_that_none_would_use' + call xolox#misc#test#assert_equals(0, xolox#misc#option#get(magic_name)) + " Test custom default values. + call xolox#misc#test#assert_equals([], xolox#misc#option#get(magic_name, [])) + " Set the option as a global variable. + let global_value = 'global variable' + let g:{magic_name} = global_value + call xolox#misc#test#assert_equals(global_value, xolox#misc#option#get(magic_name)) + " Set the option as a buffer local variable, thereby shadowing the global. + let local_value = 'buffer local variable' + let b:{magic_name} = local_value + call xolox#misc#test#assert_equals(local_value, xolox#misc#option#get(magic_name)) + " Sanity check that it's possible to unshadow as well. + unlet b:{magic_name} + call xolox#misc#test#assert_equals(global_value, xolox#misc#option#get(magic_name)) + " Cleanup after ourselves. + unlet g:{magic_name} + call xolox#misc#test#assert_equals(0, xolox#misc#option#get(magic_name)) +endfunction + +function! xolox#misc#tests#splitting_of_multi_valued_options() " {{{2 + " Test splitting of multi-valued Vim options with + " `xolox#misc#option#split()`. + call xolox#misc#test#assert_equals([], xolox#misc#option#split('')) + call xolox#misc#test#assert_equals(['just one value'], xolox#misc#option#split('just one value')) + call xolox#misc#test#assert_equals(['value 1', 'value 2'], xolox#misc#option#split('value 1,value 2')) + call xolox#misc#test#assert_equals(['value 1', 'value 2', 'tricky,value'], xolox#misc#option#split('value 1,value 2,tricky\,value')) +endfunction + +function! xolox#misc#tests#joining_of_multi_valued_options() " {{{2 + " Test joining of multi-valued Vim options with `xolox#misc#option#join()`. + call xolox#misc#test#assert_equals('', xolox#misc#option#join([])) + call xolox#misc#test#assert_equals('just one value', xolox#misc#option#join(['just one value'])) + call xolox#misc#test#assert_equals('value 1,value 2', xolox#misc#option#join(['value 1', 'value 2'])) + call xolox#misc#test#assert_equals('value 1,value 2,tricky\,value', xolox#misc#option#join(['value 1', 'value 2', 'tricky,value'])) +endfunction + +" Tests for autoload/xolox/misc/os.vim {{{1 + +function! s:test_command_execution() + call xolox#misc#test#wrap('xolox#misc#tests#finding_vim_on_the_search_path') + call s:wrap_exec_test('xolox#misc#tests#synchronous_command_execution') + call s:wrap_exec_test('xolox#misc#tests#synchronous_command_execution_with_stderr') + call s:wrap_exec_test('xolox#misc#tests#synchronous_command_execution_with_raising_of_errors') + call s:wrap_exec_test('xolox#misc#tests#synchronous_command_execution_without_raising_errors') + call s:wrap_exec_test('xolox#misc#tests#asynchronous_command_execution') +endfunction + +function! xolox#misc#tests#finding_vim_on_the_search_path() " {{{2 + " Test looking up Vim's executable on the search path using [v:progname] [] + " with `xolox#misc#os#find_vim()`. + " + " [v:progname]: http://vimdoc.sourceforge.net/htmldoc/eval.html#v:progname + let pathname = xolox#misc#os#find_vim() + call xolox#misc#test#assert_same_type('', pathname) + call xolox#misc#test#assert_true(executable(pathname)) +endfunction + +function! xolox#misc#tests#synchronous_command_execution() " {{{2 + " Test basic functionality of synchronous command execution with + " `xolox#misc#os#exec()`. + let result = xolox#misc#os#exec({'command': printf('%s output', g:xolox#misc#test#echo), 'use_dll': s:use_dll}) + call xolox#misc#test#assert_same_type({}, result) + call xolox#misc#test#assert_equals(0, result['exit_code']) + call xolox#misc#test#assert_equals(['output'], result['stdout']) +endfunction + +function! xolox#misc#tests#synchronous_command_execution_with_stderr() " {{{2 + " Test basic functionality of synchronous command execution with + " `xolox#misc#os#exec()` including the standard error stream (not available + " on Windows when vim-shell is not installed). + if !(xolox#misc#os#is_win() && !s:use_dll) + let result = xolox#misc#os#exec({'command': printf('%s output && %s errors >&2', g:xolox#misc#test#echo, g:xolox#misc#test#echo), 'use_dll': s:use_dll}) + call xolox#misc#test#assert_same_type({}, result) + call xolox#misc#test#assert_equals(0, result['exit_code']) + call xolox#misc#test#assert_equals(['output'], result['stdout']) + call xolox#misc#test#assert_equals(['errors'], result['stderr']) + endif +endfunction + +function! xolox#misc#tests#synchronous_command_execution_with_raising_of_errors() " {{{2 + " Test raising of errors during synchronous command execution with + " `xolox#misc#os#exec()`. + try + call xolox#misc#os#exec({'command': 'exit 1', 'use_dll': s:use_dll}) + call xolox#misc#test#assert_true(0) + catch + call xolox#misc#test#assert_true(1) + endtry +endfunction + +function! xolox#misc#tests#synchronous_command_execution_without_raising_errors() " {{{2 + " Test synchronous command execution without raising of errors with + " `xolox#misc#os#exec()`. + try + let result = xolox#misc#os#exec({'command': 'exit 42', 'check': 0, 'use_dll': s:use_dll}) + call xolox#misc#test#assert_true(1) + call xolox#misc#test#assert_equals(42, result['exit_code']) + catch + call xolox#misc#test#assert_true(0) + endtry +endfunction + +function! xolox#misc#tests#asynchronous_command_execution() " {{{2 + " Test the basic functionality of asynchronous command execution with + " `xolox#misc#os#exec()`. This runs the external command `mkdir` and tests + " that the side effect of creating the directory takes place. This might + " seem like a peculiar choice, but it's one of the few 100% portable + " commands (Windows + UNIX) that doesn't involve input/output streams. + let temporary_directory = xolox#misc#path#tempdir() + let random_name = printf('%i', localtime()) + let expected_directory = xolox#misc#path#merge(temporary_directory, random_name) + let command = 'mkdir ' . xolox#misc#escape#shell(expected_directory) + let result = xolox#misc#os#exec({'command': command, 'async': 1, 'use_dll': s:use_dll}) + call xolox#misc#test#assert_same_type({}, result) + " Make sure the command is really executed. + let timeout = localtime() + 30 + while !isdirectory(expected_directory) && localtime() < timeout + sleep 500 m + endwhile + call xolox#misc#test#assert_true(isdirectory(expected_directory)) +endfunction + +" Tests for autoload/xolox/misc/str.vim {{{1 + +function! s:test_string_handling() + call xolox#misc#test#wrap('xolox#misc#tests#string_case_transformation') + call xolox#misc#test#wrap('xolox#misc#tests#string_whitespace_compaction') + call xolox#misc#test#wrap('xolox#misc#tests#string_whitespace_trimming') + call xolox#misc#test#wrap('xolox#misc#tests#multiline_string_dedent') +endfunction + +function! xolox#misc#tests#string_case_transformation() + " Test string case transformation with `xolox#misc#str#ucfirst()`. + call xolox#misc#test#assert_equals('Foo', xolox#misc#str#ucfirst('foo')) + call xolox#misc#test#assert_equals('BAR', xolox#misc#str#ucfirst('BAR')) +endfunction + +function! xolox#misc#tests#string_whitespace_compaction() + " Test compaction of whitespace in strings with `xolox#misc#str#compact()`. + call xolox#misc#test#assert_equals('foo bar baz', xolox#misc#str#compact(' foo bar baz ')) + call xolox#misc#test#assert_equals('test', xolox#misc#str#compact("\ntest ")) +endfunction + +function! xolox#misc#tests#string_whitespace_trimming() + " Test trimming of whitespace in strings with `xolox#misc#str#trim()`. + call xolox#misc#test#assert_equals('foo bar baz', xolox#misc#str#trim("\nfoo bar baz ")) +endfunction + +function! xolox#misc#tests#multiline_string_dedent() + " Test dedenting of multi-line strings with `xolox#misc#str#dedent()`. + call xolox#misc#test#assert_equals('test', xolox#misc#str#dedent(' test')) + call xolox#misc#test#assert_equals("1\n\n2", xolox#misc#str#dedent(" 1\n\n 2")) + call xolox#misc#test#assert_equals("1\n\n 2", xolox#misc#str#dedent(" 1\n\n 2")) +endfunction + +" Tests for autoload/xolox/misc/version.vim {{{1 + +function! s:test_version_handling() + call xolox#misc#test#wrap('xolox#misc#tests#version_string_parsing') + call xolox#misc#test#wrap('xolox#misc#tests#version_string_comparison') +endfunction + +function! xolox#misc#tests#version_string_parsing() " {{{2 + " Test parsing of version strings with `xolox#misc#version#parse()`. + call xolox#misc#test#assert_equals([1], xolox#misc#version#parse('1')) + call xolox#misc#test#assert_equals([1, 5], xolox#misc#version#parse('1.5')) + call xolox#misc#test#assert_equals([1, 22, 3333, 44444, 55555], xolox#misc#version#parse('1.22.3333.44444.55555')) + call xolox#misc#test#assert_equals([1, 5], xolox#misc#version#parse('1x.5y')) +endfunction + +function! xolox#misc#tests#version_string_comparison() " {{{2 + " Test comparison of version strings with `xolox#misc#version#at_least()`. + call xolox#misc#test#assert_true(xolox#misc#version#at_least('1', '1')) + call xolox#misc#test#assert_true(!xolox#misc#version#at_least('1', '0')) + call xolox#misc#test#assert_true(xolox#misc#version#at_least('1', '2')) + call xolox#misc#test#assert_true(xolox#misc#version#at_least('1.2.3', '1.2.3')) + call xolox#misc#test#assert_true(!xolox#misc#version#at_least('1.2.3', '1.2')) + call xolox#misc#test#assert_true(xolox#misc#version#at_least('1.2.3', '1.2.4')) +endfunction diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/timer.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/timer.vim new file mode 100755 index 00000000..e97a1866 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/timer.vim @@ -0,0 +1,130 @@ +" Timing of long during operations. +" +" Author: Peter Odding +" Last Change: July 19, 2014 +" URL: http://peterodding.com/code/vim/misc/ + +if !exists('g:timer_enabled') + let g:timer_enabled = 0 +endif + +if !exists('g:timer_verbosity') + let g:timer_verbosity = 1 +endif + +let s:has_reltime = has('reltime') +let s:unique_marker = 'xolox#misc#timer#value' + +function! xolox#misc#timer#resumable() " {{{1 + " Create a resumable timer object. This returns an object (a dictionary with + " functions) with the following "methods": + " + " - `start()` instructs the timer object to start counting elapsed time + " (when a timer object is created it is not automatically started). + " + " - `stop()` instructs the timer object to stop counting elapsed time. + " This adds the time elapsed since `start()` was last called to the + " total elapsed time. This method will raise an error if called out of + " sequence. + " + " - `format()` takes the total elapsed time and reports it as a string + " containing a formatted floating point number. + " + " Timer objects are meant to accurately time short running operations so + " they're dependent on Vim's [reltime()][] and [reltimestr()][] functions. + " In order to make it possible to use timer objects in my Vim plug-ins + " unconditionally there's a fall back to [localtime()][] when [reltime()][] + " is not available. In this mode the timer objects are not very useful but + " at least they shouldn't raise errors. + " + " [localtime()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#localtime() + " [reltime()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#reltime() + " [reltimestr()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#reltimestr() + let object = {'total': [0, 0]} + function object.start() dict + if s:has_reltime + let self.current = reltime() + else + let self.current = localtime() + endif + endfunction + function object.stop() dict + if empty(get(self, 'current')) + throw "timer.stop() called on a timer that was never started!" + endif + if s:has_reltime + let elapsed_time_string = xolox#misc#str#trim(reltimestr(reltime(self.current))) + " This is a bit silly (converting to a string and then parsing that) but + " the value of reltime() is documented as being platform specific... + let [seconds, microseconds] = split(elapsed_time_string, '\.') + let self.total[0] += substitute(seconds, '^0*', '', '') + let self.total[1] += substitute(microseconds, '^0*', '', '') + let self.current = [] + else + let self.total[0] += localtime() - self.current + let self.current = 0 + endif + endfunction + function object.format() dict + let seconds = self.total[0] + let microseconds = self.total[1] + if microseconds >= 1000000 + let additional_seconds = microseconds / 1000000 + let seconds += additional_seconds + let microseconds -= additional_seconds * 1000000 + endif + return printf('%i.%06i', seconds, microseconds) + endfunction + return object +endfunction + +function! xolox#misc#timer#start() " {{{1 + " Start a timer. This returns a list which can later be passed to + " `xolox#misc#timer#stop()`. + return [s:unique_marker, s:has_reltime ? reltime() : localtime()] +endfunction + +function! xolox#misc#timer#stop(...) " {{{1 + " Show a formatted debugging message to the user, if the user has enabled + " increased verbosity by setting Vim's ['verbose'] [verbose] option to one + " (1) or higher. + " + " This function has the same argument handling as Vim's [printf()] [printf] + " function with one difference: At the point where you want the elapsed time + " to be embedded, you write `%s` and you pass the list returned by + " `xolox#misc#timer#start()` as an argument. + " + " [verbose]: http://vimdoc.sourceforge.net/htmldoc/options.html#'verbose' + " [printf]: http://vimdoc.sourceforge.net/htmldoc/eval.html#printf() + if (g:timer_enabled || &verbose >= g:timer_verbosity) + call call('xolox#misc#msg#info', map(copy(a:000), 'xolox#misc#timer#convert(v:val)')) + endif +endfunction + +function! xolox#misc#timer#force(...) " {{{1 + " Show a formatted message to the user. This function has the same argument + " handling as Vim's [printf()] [printf] function with one difference: At the + " point where you want the elapsed time to be embedded, you write `%s` and + " you pass the list returned by `xolox#misc#timer#start()` as an argument. + call call('xolox#misc#msg#info', map(copy(a:000), 'xolox#misc#timer#convert(v:val)')) +endfunction + +function! xolox#misc#timer#convert(value) " {{{1 + " Convert the value returned by `xolox#misc#timer#start()` to a string + " representation of the elapsed time since `xolox#misc#timer#start()` was + " called. Other values are returned unmodified (this allows using it with + " Vim's [map()][] function). + " + " [map()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#map() + if type(a:value) == type([]) && len(a:value) == 2 && a:value[0] == s:unique_marker + if s:has_reltime + let ts = xolox#misc#str#trim(reltimestr(reltime(a:value[1]))) + else + let ts = localtime() - a:value[1] + endif + return xolox#misc#format#timestamp(ts) + endif + return a:value +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/autoload/xolox/misc/version.vim b/sources_non_forked/vim-misc/autoload/xolox/misc/version.vim new file mode 100755 index 00000000..0f3ad673 --- /dev/null +++ b/sources_non_forked/vim-misc/autoload/xolox/misc/version.vim @@ -0,0 +1,34 @@ +" Version string handling. +" +" Author: Peter Odding +" Last Change: June 22, 2013 +" URL: http://peterodding.com/code/vim/misc/ + +function! xolox#misc#version#parse(version_string) + " Convert a version string to a list of integers. + let result = map(split(a:version_string, '\.'), 'v:val + 0') + call xolox#misc#msg#debug("vim-misc %s: Parsed version string %s into %s.", g:xolox#misc#version, string(a:version_string), string(result)) + return result +endfunction + +function! xolox#misc#version#at_least(expected_version, available_version) + " Check whether the second version string is equal to or greater than the + " first version string. Returns 1 (true) when it is, 0 (false) otherwise. + let expected_version = xolox#misc#version#parse(a:expected_version) + let available_version = xolox#misc#version#parse(a:available_version) + for idx in range(max([len(expected_version), len(available_version)])) + let expected_number = get(expected_version, idx, 0) + let available_number = get(available_version, idx, 0) + if available_number > expected_number + call xolox#misc#msg#debug("vim-misc %s: Available version (%s) is higher than expected version (%s).", g:xolox#misc#version, a:available_version, a:expected_version) + return 1 + elseif available_number < expected_number + call xolox#misc#msg#debug("vim-misc %s: Available version (%s) is lower than expected version (%s).", g:xolox#misc#version, a:available_version, a:expected_version) + return 0 + endif + endfor + call xolox#misc#msg#debug("vim-misc %s: Available version (%s) is equal to expected version (%s).", g:xolox#misc#version, a:available_version, a:expected_version) + return 1 +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-misc/doc/misc.txt b/sources_non_forked/vim-misc/doc/misc.txt new file mode 100755 index 00000000..3476c465 --- /dev/null +++ b/sources_non_forked/vim-misc/doc/misc.txt @@ -0,0 +1,1204 @@ +*misc.txt* Miscellaneous auto-load Vim scripts + +=============================================================================== +Contents ~ + + 1. Introduction |misc-introduction| + 2. Installation |misc-installation| + 3. Function documentation |misc-function-documentation| + 1. Asynchronous Vim script evaluation |misc-asynchronous-vim-script-evaluation| + 1. The |xolox#misc#async#call()| function + 2. The |xolox#misc#async#inside_child()| function + 3. The |xolox#misc#async#callback_to_parent()| function + 4. The |xolox#misc#async#periodic_callback()| function + 2. Handling of special buffers |misc-handling-of-special-buffers| + 1. The |xolox#misc#buffer#is_empty()| function + 2. The |xolox#misc#buffer#prepare()| function + 3. The |xolox#misc#buffer#lock()| function + 4. The |xolox#misc#buffer#unlock()| function + 3. Tab completion for user defined commands |misc-tab-completion-for-user-defined-commands| + 1. The |xolox#misc#complete#keywords()| function + 4. Rate limiting for Vim's CursorHold event |misc-rate-limiting-for-vims-cursorhold-event| + 1. The |xolox#misc#cursorhold#register()| function + 2. The |xolox#misc#cursorhold#autocmd()| function + 5. String escaping functions |misc-string-escaping-functions| + 1. The |xolox#misc#escape#pattern()| function + 2. The |xolox#misc#escape#substitute()| function + 3. The |xolox#misc#escape#shell()| function + 6. Human friendly string formatting for Vim |misc-human-friendly-string-formatting-for-vim| + 1. The |xolox#misc#format#pluralize()| function + 2. The |xolox#misc#format#timestamp()| function + 7. List handling functions |misc-list-handling-functions| + 1. The |xolox#misc#list#unique()| function + 2. The |xolox#misc#list#binsert()| function + 8. Functions to interact with the user |misc-functions-to-interact-with-user| + 1. The |xolox#misc#msg#info()| function + 2. The |xolox#misc#msg#warn()| function + 3. The |xolox#misc#msg#debug()| function + 9. Integration between Vim and its environment |misc-integration-between-vim-its-environment| + 1. The |xolox#misc#open#file()| function + 2. The |xolox#misc#open#url()| function + 10. Vim and plug-in option handling |misc-vim-plug-in-option-handling| + 1. The |xolox#misc#option#get()| function + 2. The |xolox#misc#option#split()| function + 3. The |xolox#misc#option#join()| function + 4. The |xolox#misc#option#split_tags()| function + 5. The |xolox#misc#option#join_tags()| function + 6. The |xolox#misc#option#eval_tags()| function + 11. Operating system interfaces |misc-operating-system-interfaces| + 1. The |xolox#misc#os#is_mac()| function + 2. The |xolox#misc#os#is_win()| function + 3. The |xolox#misc#os#find_vim()| function + 4. The |xolox#misc#os#exec()| function + 5. The |xolox#misc#os#can_use_dll()| function + 12. Pathname manipulation functions |misc-pathname-manipulation-functions| + 1. The |xolox#misc#path#which()| function + 2. The |xolox#misc#path#split()| function + 3. The |xolox#misc#path#join()| function + 4. The |xolox#misc#path#directory_separator()| function + 5. The |xolox#misc#path#absolute()| function + 6. The |xolox#misc#path#relative()| function + 7. The |xolox#misc#path#merge()| function + 8. The |xolox#misc#path#commonprefix()| function + 9. The |xolox#misc#path#starts_with()| function + 10. The |xolox#misc#path#encode()| function + 11. The |xolox#misc#path#decode()| function + 12. The |xolox#misc#path#is_relative()| function + 13. The |xolox#misc#path#tempdir()| function + 13. Manipulation of UNIX file permissions |misc-manipulation-of-unix-file-permissions| + 1. The |xolox#misc#perm#update()| function + 2. The |xolox#misc#perm#get()| function + 3. The |xolox#misc#perm#set()| function + 14. Persist/recall Vim values from/to files |misc-persist-recall-vim-values-from-to-files| + 1. The |xolox#misc#persist#load()| function + 2. The |xolox#misc#persist#save()| function + 15. String handling |misc-string-handling| + 1. The |xolox#misc#str#slug()| function + 2. The |xolox#misc#str#ucfirst()| function + 3. The |xolox#misc#str#unescape()| function + 4. The |xolox#misc#str#compact()| function + 5. The |xolox#misc#str#trim()| function + 6. The |xolox#misc#str#indent()| function + 7. The |xolox#misc#str#dedent()| function + 16. Test runner & infrastructure for Vim plug-ins |misc-test-runner-infrastructure-for-vim-plug-ins| + 1. The |xolox#misc#test#reset()| function + 2. The |xolox#misc#test#summarize()| function + 3. The |xolox#misc#test#wrap()| function + 4. The |xolox#misc#test#passed()| function + 5. The |xolox#misc#test#failed()| function + 6. The |xolox#misc#test#assert_true()| function + 7. The |xolox#misc#test#assert_equals()| function + 8. The |xolox#misc#test#assert_same_type()| function + 17. Tests for the miscellaneous Vim scripts |tests-for-miscellaneous-vim-scripts| + 1. The |xolox#misc#tests#run()| function + 2. The |xolox#misc#tests#pattern_escaping()| function + 3. The |xolox#misc#tests#substitute_escaping()| function + 4. The |xolox#misc#tests#shell_escaping()| function + 5. The |xolox#misc#tests#making_a_list_unique()| function + 6. The |xolox#misc#tests#binary_insertion()| function + 7. The |xolox#misc#tests#getting_configuration_options()| function + 8. The |xolox#misc#tests#splitting_of_multi_valued_options()| function + 9. The |xolox#misc#tests#joining_of_multi_valued_options()| function + 10. The |xolox#misc#tests#finding_vim_on_the_search_path()| function + 11. The |xolox#misc#tests#synchronous_command_execution()| function + 12. The |xolox#misc#tests#synchronous_command_execution_with_stderr()| function + 13. The |xolox#misc#tests#synchronous_command_execution_with_raising_of_errors()| +function + 14. The |xolox#misc#tests#synchronous_command_execution_without_raising_errors()| +function + 15. The |xolox#misc#tests#asynchronous_command_execution()| function + 16. The |xolox#misc#tests#string_case_transformation()| function + 17. The |xolox#misc#tests#string_whitespace_compaction()| function + 18. The |xolox#misc#tests#string_whitespace_trimming()| function + 19. The |xolox#misc#tests#multiline_string_dedent()| function + 20. The |xolox#misc#tests#version_string_parsing()| function + 21. The |xolox#misc#tests#version_string_comparison()| function + 18. Timing of long during operations |misc-timing-of-long-during-operations| + 1. The |xolox#misc#timer#resumable()| function + 2. The |xolox#misc#timer#start()| function + 3. The |xolox#misc#timer#stop()| function + 4. The |xolox#misc#timer#force()| function + 5. The |xolox#misc#timer#convert()| function + 19. Version string handling |misc-version-string-handling| + 1. The |xolox#misc#version#parse()| function + 2. The |xolox#misc#version#at_least()| function + 4. Contact |misc-contact| + 5. License |misc-license| + 6. References |misc-references| + +=============================================================================== + *misc-introduction* +Introduction ~ + +The vim-misc plug-in contains Vim scripts that are used by most of the Vim +plug-ins I've written [1] yet don't really belong with any single one of the +plug-ins. Basically it's an extended standard library of Vim script functions +that I wrote during the development of my Vim profile and plug-ins. + +In the past these scripts were bundled with each plug-in, however that turned +out to be a maintenance nightmare for me. That's why the miscellaneous scripts +are now a proper plug-in with their own page on Vim Online. + +Because the miscellaneous scripts are no longer bundled with my Vim plug-ins, +users are now required to install the miscellaneous scripts separately. This is +unfortunate for users who are upgrading from a previous release that did bundle +the miscellaneous scripts, but I don't see any way around this. Sorry! + +=============================================================================== + *misc-installation* +Installation ~ + +Please refer to the installation instructions [2] on GitHub. + +=============================================================================== + *misc-function-documentation* +Function documentation ~ + +Below is the documentation for the functions included in the miscellaneous +scripts. Anyone is free to use these functions in their own Vim profile and/or +plug-ins. I care about backwards compatibility so won't break it without a good +reason to do so. + +For those who are curious: The function descriptions given below were extracted +from the source code of the miscellaneous scripts using the Python module +'vimdoctool.py' included in vim-tools [3]. + +The documentation of the 95 functions below was extracted from 19 Vim scripts +on April 1, 2015 at 23:39. + +------------------------------------------------------------------------------- + *misc-asynchronous-vim-script-evaluation* +Asynchronous Vim script evaluation ~ + +The |xolox#misc#async#call()| function builds on top of |xolox#misc#os#exec()| +to support asynchronous evaluation of Vim scripts. The first (and for now only) +use case is my vim-easytags [4] plug-in which has a bunch of conflicting +requirements: + +1. I want the vim-easytags [4] plug-in to be as portable as possible. + Ideally everything is implemented in Vim script because that's the only + thing I can rely on to be available for all potential users of the plug- + in! + +2. Because of point one I've been forced to implement tags file reading, + parsing, (fold case) sorting and writing in Vim script. This is fine for + small tags files but once they grow to a couple of megabytes it becomes + annoying because Vim is unresponsive during tags file updates (key + presses are fortunately buffered due to Vim's input model but that + doesn't make it a nice user experience :-). + +3. I could (and did in the past) come up with all sorts of hacks to speed + things up without switching away from Vim script, but none of them are + going to solve the fundamental problem that Vim's unresponsive hiccups + become longer as tags files grow larger. + +By now it should be clear where this is heading: _Why not handle tags file +updates in a Vim process that runs in the background without blocking the Vim +process that the user is interacting with?_ It turns out that there are quite a +few details to take care of, but with those out of the way, it might just work! +I'm actually hoping to make asynchronous updates the default mode in vim- +easytags [4]. This means I need this functionality to be as portable and robust +as possible. + +**Status:** This code has seen little testing so I wouldn't trust it too much +just yet. On the other hand, as I said, my intention is to make this +functionality as portable and robust as possible. You be the judge :-). + +------------------------------------------------------------------------------- +The *xolox#misc#async#call()* function + +Call a Vim script function asynchronously by starting a hidden Vim process in +the background. Once the function returns the hidden Vim process terminates +itself. This function takes a single argument which is a dictionary with the +following key/value pairs: + +- **function** (required): The name of the Vim function to call inside the + child process (a string). I suggest using an |autoload| function for this, + see below. + +- **arguments** (optional): A list of arguments to pass to the function. This + list is serialized to a string using |string()| and deserialized using + |eval()|. + +- **callback** (optional): The name of a Vim function to call in the parent + process when the child process has completed (a string). + +- **clientserver** (optional): If this is true (1) the child process will + notify the parent process when it has finished (the default is true). This + works using Vim's client/server support which is not always available. As a + fall back Vim's |CursorHold| automatic command is also supported (although + the effect is not quite as instantaneous :-). + +This functionality is experimental and non trivial to use, so consider yourself +warned :-). + +**Limitations** + +I'm making this functionality available in vim-misc [5] because I think it can +be useful to other plug-ins, however if you are going to use it you should be +aware of the following limitations: + +- Because of the use of multiple processes this functionality is only + suitable for 'heavy' tasks. + +- The function arguments are serialized to a string which is passed to the + hidden Vim process as a command line argument, so the amount of data you + can pass will be limited by your operating environment. + +- The hidden Vim process is explicitly isolated from the user in several ways + (see below for more details). This is to make sure that the hidden Vim + processes are fast and don't clobber the user's editing sessions in any + way. + +**Changes to how Vim normally works** + +You have to be aware that the hidden Vim process is initialized in a specific +way that is very different from your regular Vim editing sessions: + +- Your |vimrc| file is ignored using the '-u NONE' command line option. + +- Your |gvimrc| file (if you even knew it existed ;-) is ignored using the + '-U NONE' command line option. + +- Plug-in loading is skipped using the '--noplugin' command line option. + +- Swap files (see |swap-file|) are disabled using the '-n' command line + option. This makes sure asynchronous Vim processes don't disturb the user's + editing session. + +- Your |viminfo| file is ignored using the '-i NONE' command line option. + Just like with swap files this makes sure asynchronous Vim processes don't + disturb the user's editing session. + +- No-compatible mode is enabled using the '-N' command line option (usually + the existence of your vimrc script would have achieved the same effect but + since we disable loading of your vimrc we need to spell things out for + Vim). + +**Use an auto-load function** + +The function you want to call is identified by its name which has to be +defined, but I just explained above that all regular initialization is disabled +for asynchronous Vim processes, so what gives? The answer is to use an +|autoload| function. This should work fine because the asynchronous Vim process +'inherits' the value of the |'runtimepath'| option from your editing session. + +------------------------------------------------------------------------------- +The *xolox#misc#async#inside_child()* function + +Entry point inside the hidden Vim process that runs in the background. Invoked +indirectly by |xolox#misc#async#call()| because it runs a command similar to +the following: +> + vim --cmd 'call xolox#misc#async#inside_child(...)' +< +This function is responsible for calling the user defined function, capturing +exceptions and reporting the results back to the parent Vim process using Vim's +client/server support or a temporary file. + +------------------------------------------------------------------------------- +The *xolox#misc#async#callback_to_parent()* function + +When Vim was compiled with client/server support this function (in the parent +process) will be called by |xolox#misc#async#inside_child()| (in the child +process) after the user defined function has returned. This enables more or +less instant callbacks after running an asynchronous function. + +------------------------------------------------------------------------------- +The *xolox#misc#async#periodic_callback()* function + +When client/server support is not being used the vim-misc plug-in improvises: +It uses Vim's |CursorHold| event to periodically check if an asynchronous +process has written its results to one of the expected temporary files. If a +response is found the temporary file is read and deleted and then +|xolox#misc#async#callback_to_parent()| is called to process the response. + +------------------------------------------------------------------------------- + *misc-handling-of-special-buffers* +Handling of special buffers ~ + +The functions defined here make it easier to deal with special Vim buffers that +contain text generated by a Vim plug-in. For example my vim-notes plug-in [6] +generates several such buffers: + +- :RecentNotes [7] lists recently modified notes +- :ShowTaggedNotes [8] lists notes grouped by tags +- etc. + +Because the text in these buffers is generated, Vim shouldn't bother with swap +files and it should never prompt the user whether to save changes to the +generated text. + +------------------------------------------------------------------------------- +The *xolox#misc#buffer#is_empty()* function + +Checks if the current buffer is an empty, unchanged buffer which can be reused. +Returns 1 if an empty buffer is found, 0 otherwise. + +------------------------------------------------------------------------------- +The *xolox#misc#buffer#prepare()* function + +Open a special buffer, i.e. a buffer that will hold generated contents, not +directly edited by the user. The buffer can be customized by passing a +dictionary with the following key/value pairs as the first argument: + +- **name** (required): The base name of the buffer (i.e. the base name of the + file loaded in the buffer, even though it isn't really a file and nothing + is really 'loaded' :-) + +- **path** (required): The pathname of the buffer. May be relevant if |:lcd| + or |'autochdir'| is being used. + +------------------------------------------------------------------------------- +The *xolox#misc#buffer#lock()* function + +Lock a special buffer so that its contents can no longer be edited. + +------------------------------------------------------------------------------- +The *xolox#misc#buffer#unlock()* function + +Unlock a special buffer so that its content can be updated. + +------------------------------------------------------------------------------- + *misc-tab-completion-for-user-defined-commands* +Tab completion for user defined commands ~ + +------------------------------------------------------------------------------- +The *xolox#misc#complete#keywords()* function + +This function can be used to perform keyword completion for user defined Vim +commands based on the contents of the current buffer. Here's an example of how +you would use it: +> + :command -nargs=* -complete=customlist,xolox#misc#complete#keywords MyCmd call s:MyCmd() +< +------------------------------------------------------------------------------- + *misc-rate-limiting-for-vims-cursorhold-event* +Rate limiting for Vim's CursorHold event ~ + +Several of my Vim plug-ins (e.g. vim-easytags [4], vim-notes [6] and vim- +session [9]) use Vim's |CursorHold| and |CursorHoldI| events to perform +periodic tasks when the user doesn't press any keys for a couple of seconds. +These events by default fire after four seconds, this is configurable using +Vim's |'updatetime'| option. The problem that this script solves is that there +are Vim plug-ins which set the |'updatetime'| option to unreasonably low +values, thereby breaking my Vim plug-ins and probably a lot of other Vim plug- +ins out there. When users complain about this I can tell them that another Vim +plug-in is to blame, but users don't care for the difference, their Vim is +broken! So I implemented a workaround. This script enables registration of +|CursorHold| event handlers with a configurable interval (expressed in +seconds). The event handlers will be called no more than once every interval. + +------------------------------------------------------------------------------- +The *xolox#misc#cursorhold#register()* function + +Register a |CursorHold| event handler with a custom interval. This function +takes a single argument which is a dictionary with the following fields: + +- **function** (required): The name of the event handler function (a string). + +- **arguments** (optional): A list of arguments to pass to the event handler + function (defaults to an empty list). + +- **interval** (optional): The number of seconds between calls to the event + handler (defaults to 4). + +------------------------------------------------------------------------------- +The *xolox#misc#cursorhold#autocmd()* function + +The 'top level event handler' that's called by Vim whenever the |CursorHold| or +|CursorHoldI| event fires. It iterates through the event handlers registered +using |xolox#misc#cursorhold#register()| and calls each event handler at the +appropriate interval, keeping track of the time when each event handler was +last run. + +------------------------------------------------------------------------------- + *misc-string-escaping-functions* +String escaping functions ~ + +------------------------------------------------------------------------------- +The *xolox#misc#escape#pattern()* function + +Takes a single string argument and converts it into a |:substitute| / +|substitute()| pattern string that matches the given string literally. + +------------------------------------------------------------------------------- +The *xolox#misc#escape#substitute()* function + +Takes a single string argument and converts it into a |:substitute| / +|substitute()| replacement string that inserts the given string literally. + +------------------------------------------------------------------------------- +The *xolox#misc#escape#shell()* function + +Takes a single string argument and converts it into a quoted command line +argument. + +I was going to add a long rant here about Vim's |'shellslash'| option, but +really, it won't make any difference. Let's just suffice to say that I have yet +to encounter a single person out there who uses this option for its intended +purpose (running a UNIX style shell on Microsoft Windows). + +------------------------------------------------------------------------------- + *misc-human-friendly-string-formatting-for-vim* +Human friendly string formatting for Vim ~ + +------------------------------------------------------------------------------- +The *xolox#misc#format#pluralize()* function + +Concatenate a counter (the first argument, expected to be an integer) with a +singular or plural label (the second and third arguments, both expected to be +strings). + +------------------------------------------------------------------------------- +The *xolox#misc#format#timestamp()* function + +Format a time stamp (a string containing a formatted floating point number) +into a human friendly format, for example 70 seconds is phrased as "1 minute +and 10 seconds". + +------------------------------------------------------------------------------- + *misc-list-handling-functions* +List handling functions ~ + +------------------------------------------------------------------------------- +The *xolox#misc#list#unique()* function + +Remove duplicate values from the given list in-place (preserves order). + +------------------------------------------------------------------------------- +The *xolox#misc#list#binsert()* function + +Performs in-place binary insertion, which depending on your use case can be +more efficient than calling Vim's |sort()| function after each insertion (in +cases where a single, final sort is not an option). Expects three arguments: + +1. A list +2. A value to insert +3. 1 (true) when case should be ignored, 0 (false) otherwise + +------------------------------------------------------------------------------- + *misc-functions-to-interact-with-user* +Functions to interact with the user ~ + +------------------------------------------------------------------------------- +The *xolox#misc#msg#info()* function + +Show a formatted informational message to the user. + +This function has the same argument handling as Vim's |printf()| function with +one notable difference: Any arguments which are not numbers or strings are +coerced to strings using Vim's |string()| function. + +In the case of |xolox#misc#msg#info()|, automatic string coercion simply makes +the function a bit easier to use. + +The messages emitted by this function have no highlighting. Previously these +messages were highlighted using the Title group (see |hl-Title|), but it was +pointed out in pull request 16 [10] that this group shouldn't be used for +informational messages because it is meant for titles and because of this some +color schemes use colors that stand out quite a bit, causing the informational +messages to look like errors. + +------------------------------------------------------------------------------- +The *xolox#misc#msg#warn()* function + +Show a formatted warning message to the user. + +This function has the same argument handling as the |xolox#misc#msg#info()| +function. + +------------------------------------------------------------------------------- +The *xolox#misc#msg#debug()* function + +Show a formatted debugging message to the user, _if the user has enabled +increased verbosity by setting Vim's |'verbose'| option to one (1) or higher_. + +This function has the same argument handling as the |xolox#misc#msg#info()| +function. + +In the case of |xolox#misc#msg#debug()|, automatic string coercion provides +lazy evaluation in the sense that complex data structures are only converted to +strings when the user has enabled increased verbosity. + +------------------------------------------------------------------------------- + *misc-integration-between-vim-its-environment* +Integration between Vim and its environment ~ + +------------------------------------------------------------------------------- +The *xolox#misc#open#file()* function + +Given a pathname or URL as the first argument, this opens the file with the +program associated with the file type. So for example a text file might open in +Vim, an '*.html' file would probably open in your web browser and a media file +would open in a media player. + +This should work on Windows, Mac OS X and most Linux distributions. If this +fails to find a file association, you can pass one or more external commands to +try as additional arguments. For example: +> + :call xolox#misc#open#file('/path/to/my/file', 'firefox', 'google-chrome') +< +This generally shouldn't be necessary but it might come in handy now and then. + +------------------------------------------------------------------------------- +The *xolox#misc#open#url()* function + +Given a URL as the first argument, this opens the URL in your preferred or best +available web browser: + +- In GUI environments a graphical web browser will open (or a new tab will be + created in an existing window) + +- In console Vim without a GUI environment, when you have any of 'lynx', + 'links' or 'w3m' installed it will launch a command line web browser in + front of Vim (temporarily suspending Vim) + +------------------------------------------------------------------------------- + *misc-vim-plug-in-option-handling* +Vim and plug-in option handling ~ + +------------------------------------------------------------------------------- +The *xolox#misc#option#get()* function + +Expects one or two arguments: 1. The name of a variable and 2. the default +value if the variable does not exist. + +Returns the value of the variable from a buffer local variable, global variable +or the default value, depending on which is defined. + +This is used by some of my Vim plug-ins for option handling, so that users can +customize options for specific buffers. + +------------------------------------------------------------------------------- +The *xolox#misc#option#split()* function + +Given a multi-value Vim option like |'runtimepath'| this returns a list of +strings. For example: +> + :echo xolox#misc#option#split(&runtimepath) + ['/home/peter/Projects/Vim/misc', + '/home/peter/Projects/Vim/colorscheme-switcher', + '/home/peter/Projects/Vim/easytags', + ...] +< +------------------------------------------------------------------------------- +The *xolox#misc#option#join()* function + +Given a list of strings like the ones returned by |xolox#misc#option#split()|, +this joins the strings together into a single value that can be used to set a +Vim option. + +------------------------------------------------------------------------------- +The *xolox#misc#option#split_tags()* function + +Customized version of |xolox#misc#option#split()| with specialized handling for +Vim's |'tags'| option. + +------------------------------------------------------------------------------- +The *xolox#misc#option#join_tags()* function + +Customized version of |xolox#misc#option#join()| with specialized handling for +Vim's |'tags'| option. + +------------------------------------------------------------------------------- +The *xolox#misc#option#eval_tags()* function + +Evaluate Vim's |'tags'| option without looking at the file system, i.e. this +will report tags files that don't exist yet. Expects the value of the |'tags'| +option as the first argument. If the optional second argument is 1 (true) only +the first match is returned, otherwise (so by default) a list with all matches +is returned. + +------------------------------------------------------------------------------- + *misc-operating-system-interfaces* +Operating system interfaces ~ + +------------------------------------------------------------------------------- +The *xolox#misc#os#is_mac()* function + +Returns 1 (true) when on Mac OS X, 0 (false) otherwise. You would expect this +to simply check the Vim feature list, but for some obscure reason the +'/usr/bin/vim' included in Mac OS X (verified on version 10.7.5) returns 0 +(false) in response to "has('mac')", so we check the output of 'uname' to avoid +false negatives. + +------------------------------------------------------------------------------- +The *xolox#misc#os#is_win()* function + +Returns 1 (true) when on Microsoft Windows, 0 (false) otherwise. + +------------------------------------------------------------------------------- +The *xolox#misc#os#find_vim()* function + +Returns the program name of Vim as a string. On Windows and UNIX this just +|v:progname| as an absolute pathname while on Mac OS X there is some special +magic to find MacVim's executable even though it's usually not on the +executable search path. If you want, you can override the value returned from +this function by setting the global variable 'g:xolox#misc#os#vim_progname'. + +By default the choice of console Vim vs graphical Vim is made based on the +value of |v:progname|, but if you have a preference you can pass the string +'vim' or 'gvim' as the first and only argument. + +------------------------------------------------------------------------------- +The *xolox#misc#os#exec()* function + +Execute an external command (hiding the console on Microsoft Windows when my +vim-shell plug-in [11] is installed). + +Expects a dictionary with the following key/value pairs as the first argument: + +- **command** (required): The command line to execute + +- **async** (optional): set this to 1 (true) to execute the command in the + background (asynchronously) + +- **stdin** (optional): a string or list of strings with the input for the + external command + +- **check** (optional): set this to 0 (false) to disable checking of the exit + code of the external command (by default an exception will be raised when + the command fails) + +Returns a dictionary with one or more of the following key/value pairs: + +- **command** (always available): the generated command line that was used to + run the external command + +- **exit_code** (only in synchronous mode): the exit status of the external + command (an integer, zero on success) + +- **stdout** (only in synchronous mode): the output of the command on the + standard output stream (a list of strings, one for each line) + +- **stderr** (only in synchronous mode): the output of the command on the + standard error stream (as a list of strings, one for each line) + +------------------------------------------------------------------------------- +The *xolox#misc#os#can_use_dll()* function + +If a) we're on Microsoft Windows, b) the vim-shell plug-in is installed and c) +the compiled DLL included in vim-shell works, we can use the vim-shell plug-in +to execute external commands! Returns 1 (true) if we can use the DLL, 0 (false) +otherwise. + +------------------------------------------------------------------------------- + *misc-pathname-manipulation-functions* +Pathname manipulation functions ~ + +------------------------------------------------------------------------------- +The *xolox#misc#path#which()* function + +Scan the executable search path ('$PATH') for one or more external programs. +Expects one or more string arguments with program names. Returns a list with +the absolute pathnames of all found programs. Here's an example: +> + :echo xolox#misc#path#which('gvim', 'vim') + ['/usr/local/bin/gvim', + '/usr/bin/gvim', + '/usr/local/bin/vim', + '/usr/bin/vim'] +< +------------------------------------------------------------------------------- +The *xolox#misc#path#split()* function + +Split a pathname (the first and only argument) into a list of pathname +components. + +On Windows, pathnames starting with two slashes or backslashes are UNC paths +where the leading slashes are significant... In this case we split like this: + +- Input: "'//server/share/directory'" +- Result: "['//server', 'share', 'directory']" + +Everything except Windows is treated like UNIX until someone has a better +suggestion :-). In this case we split like this: + +- Input: "'/foo/bar/baz'" +- Result: "['/', 'foo', 'bar', 'baz']" + +To join a list of pathname components back into a single pathname string, use +the |xolox#misc#path#join()| function. + +------------------------------------------------------------------------------- +The *xolox#misc#path#join()* function + +Join a list of pathname components (the first and only argument) into a single +pathname string. This is the counterpart to the |xolox#misc#path#split()| +function and it expects a list of pathname components as returned by +|xolox#misc#path#split()|. + +------------------------------------------------------------------------------- +The *xolox#misc#path#directory_separator()* function + +Find the preferred directory separator for the platform and settings. + +------------------------------------------------------------------------------- +The *xolox#misc#path#absolute()* function + +Canonicalize and resolve a pathname, _regardless of whether it exists_. This is +intended to support string comparison to determine whether two pathnames point +to the same directory or file. + +------------------------------------------------------------------------------- +The *xolox#misc#path#relative()* function + +Make an absolute pathname (the first argument) relative to a directory (the +second argument). + +------------------------------------------------------------------------------- +The *xolox#misc#path#merge()* function + +Join a directory pathname and filename into a single pathname. + +------------------------------------------------------------------------------- +The *xolox#misc#path#commonprefix()* function + +Find the common prefix of path components in a list of pathnames. + +------------------------------------------------------------------------------- +The *xolox#misc#path#starts_with()* function + +Check whether the first pathname starts with the second pathname (expected to +be a directory). This does not perform a regular string comparison; first it +normalizes both pathnames, then it splits them into their pathname segments and +then it compares the segments. + +------------------------------------------------------------------------------- +The *xolox#misc#path#encode()* function + +Encode a pathname so it can be used as a filename. This uses URL encoding to +encode special characters. + +------------------------------------------------------------------------------- +The *xolox#misc#path#decode()* function + +Decode a pathname previously encoded with |xolox#misc#path#encode()|. + +------------------------------------------------------------------------------- +The *xolox#misc#path#is_relative()* function + +Returns true (1) when the pathname given as the first argument is relative, +false (0) otherwise. + +------------------------------------------------------------------------------- +The *xolox#misc#path#tempdir()* function + +Create a temporary directory and return the pathname of the directory. + +------------------------------------------------------------------------------- + *misc-manipulation-of-unix-file-permissions* +Manipulation of UNIX file permissions ~ + +Vim's |writefile()| function cannot set file permissions for newly created +files and although Vim script has a function to get file permissions (see +|getfperm()|) there is no equivalent for changing a file's permissions. + +This omission breaks the otherwise very useful idiom of updating a file by +writing its new contents to a temporary file and then renaming the temporary +file into place (which is as close as you're going to get to atomically +updating a file's contents on UNIX) because the file's permissions will not be +preserved! + +**Here's a practical example:** My vim-easytags [4] plug-in writes tags file +updates to a temporary file and renames the temporary file into place. When I +use 'sudo -s' on Ubuntu Linux it preserves my environment variables so my +'~/.vimrc' and the vim-easytags [4] plug-in are still loaded. Now when a tags +file is written the file becomes owned by root (my effective user id in the +'sudo' session). Once I leave the 'sudo' session I can no longer update my tags +file because it's now owned by root … ಠ_ಠ + +------------------------------------------------------------------------------- +The *xolox#misc#perm#update()* function + +Atomically update a file's contents while preserving the owner, group and mode. +The first argument is the pathname of the file to update (a string). The second +argument is the list of lines to be written to the file. Writes the new +contents to a temporary file and renames the temporary file into place, thereby +preventing readers from reading a partially written file. Returns 1 if the file +is successfully updated, 0 otherwise. + +Note that if |xolox#misc#perm#get()| and |xolox#misc#perm#set()| cannot be used +to preserve the file owner/group/mode the file is still updated using a rename +(for compatibility with non-UNIX systems and incompatible '/usr/bin/stat' +implementations) so in that case you can still lose the file's +owner/group/mode. + +------------------------------------------------------------------------------- +The *xolox#misc#perm#get()* function + +Get the owner, group and permissions of the pathname given as the first +argument. Returns an opaque value which you can later pass to +|xolox#misc#perm#set()|. + +------------------------------------------------------------------------------- +The *xolox#misc#perm#set()* function + +Set the permissions (the second argument) of the pathname given as the first +argument. Expects a permissions value created by |xolox#misc#perm#get()|. + +------------------------------------------------------------------------------- + *misc-persist-recall-vim-values-from-to-files* +Persist/recall Vim values from/to files ~ + +Vim's |string()| function can be used to serialize Vim script values like +numbers, strings, lists, dictionaries and composites of them to a string which +can later be evaluated using the |eval()| function to turn it back into the +original value. This Vim script provides functions to use these functions to +persist and recall Vim values from/to files. This is very useful for +communication between (possibly concurrent) Vim processes. + +------------------------------------------------------------------------------- +The *xolox#misc#persist#load()* function + +Read a Vim value like a number, string, list or dictionary from a file using +|readfile()| and |eval()|. The first argument is the filename of the file to +read (a string). The optional second argument specifies the default value which +is returned when the file can't be loaded. This function returns the loaded +value or the default value (which itself defaults to the integer 0). + +------------------------------------------------------------------------------- +The *xolox#misc#persist#save()* function + +Write a Vim value like a number, string, list or dictionary to a file using +|string()| and |writefile()|. The first argument is the filename of the file to +write (a string) and the second argument is the value to write (any value). + +This function writes the serialized value to an intermediate file which is then +renamed into place atomically. This avoids issues with concurrent processes +where for example a producer has written a partial file which is read by a +consumer before the file is complete. In this case the consumer would read a +corrupt value. The rename trick avoids this problem. + +------------------------------------------------------------------------------- + *misc-string-handling* +String handling ~ + +------------------------------------------------------------------------------- +The *xolox#misc#str#slug()* function + +Convert a string to a "slug" - something that can be safely used in filenames +and URLs without worrying about quoting/escaping of special characters. + +------------------------------------------------------------------------------- +The *xolox#misc#str#ucfirst()* function + +Uppercase the first character in a string (the first argument). + +------------------------------------------------------------------------------- +The *xolox#misc#str#unescape()* function + +Remove back slash escapes from a string (the first argument). + +------------------------------------------------------------------------------- +The *xolox#misc#str#compact()* function + +Compact whitespace in a string (the first argument). + +------------------------------------------------------------------------------- +The *xolox#misc#str#trim()* function + +Trim all whitespace from the start and end of a string (the first argument). + +------------------------------------------------------------------------------- +The *xolox#misc#str#indent()* function + +Indent all lines in a multi-line string (the first argument) with a specific +number of _space characters_ (the second argument, an integer). + +------------------------------------------------------------------------------- +The *xolox#misc#str#dedent()* function + +Remove common whitespace from a multi line string. + +------------------------------------------------------------------------------- + *misc-test-runner-infrastructure-for-vim-plug-ins* +Test runner & infrastructure for Vim plug-ins ~ + +The Vim auto-load script 'autoload/xolox/misc/test.vim' contains infrastructure +that can be used to run an automated Vim plug-in test suite. It provides a +framework for running test functions, keeping track of the test status, making +assertions and reporting test results to the user. + +------------------------------------------------------------------------------- +The *xolox#misc#test#reset()* function + +Reset counters for executed tests and passed/failed assertions. + +------------------------------------------------------------------------------- +The *xolox#misc#test#summarize()* function + +Print a summary of test results, to be interpreted interactively. + +------------------------------------------------------------------------------- +The *xolox#misc#test#wrap()* function + +Call a function in a try/catch block and prevent exceptions from bubbling. The +name of the function should be passed as the first and only argument; it should +be a string containing the name of a Vim auto-load function. + +------------------------------------------------------------------------------- +The *xolox#misc#test#passed()* function + +Record a test which succeeded. + +------------------------------------------------------------------------------- +The *xolox#misc#test#failed()* function + +Record a test which failed. + +------------------------------------------------------------------------------- +The *xolox#misc#test#assert_true()* function + +Check whether an expression is true. + +------------------------------------------------------------------------------- +The *xolox#misc#test#assert_equals()* function + +Check whether two values are the same. + +------------------------------------------------------------------------------- +The *xolox#misc#test#assert_same_type()* function + +Check whether two values are of the same type. + +------------------------------------------------------------------------------- + *tests-for-miscellaneous-vim-scripts* +Tests for the miscellaneous Vim scripts ~ + +The Vim auto-load script 'autoload/xolox/misc/tests.vim' contains the automated +test suite of the miscellaneous Vim scripts. Right now the coverage is not very +high yet, but this will improve over time. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#run()* function + +Run the automated test suite of the miscellaneous Vim scripts. To be used +interactively. Intended to be safe to execute irrespective of context. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#pattern_escaping()* function + +Test escaping of regular expression patterns with +|xolox#misc#escape#pattern()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#substitute_escaping()* function + +Test escaping of substitution strings with |xolox#misc#escape#substitute()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#shell_escaping()* function + +Test escaping of shell arguments with |xolox#misc#escape#shell()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#making_a_list_unique()* function + +Test removing of duplicate values from lists with |xolox#misc#list#unique()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#binary_insertion()* function + +Test the binary insertion algorithm implemented in |xolox#misc#list#binsert()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#getting_configuration_options()* function + +Test getting of scoped plug-in configuration "options" with +|xolox#misc#option#get()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#splitting_of_multi_valued_options()* function + +Test splitting of multi-valued Vim options with |xolox#misc#option#split()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#joining_of_multi_valued_options()* function + +Test joining of multi-valued Vim options with |xolox#misc#option#join()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#finding_vim_on_the_search_path()* function + +Test looking up Vim's executable on the search path using |v:progname| with +|xolox#misc#os#find_vim()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#synchronous_command_execution()* function + +Test basic functionality of synchronous command execution with +|xolox#misc#os#exec()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#synchronous_command_execution_with_stderr()* function + +Test basic functionality of synchronous command execution with +|xolox#misc#os#exec()| including the standard error stream (not available on +Windows when vim-shell is not installed). + +------------------------------------------------------------------------------- +The *xolox#misc#tests#synchronous_command_execution_with_raising_of_errors()* +function + +Test raising of errors during synchronous command execution with +|xolox#misc#os#exec()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#synchronous_command_execution_without_raising_errors()* +function + +Test synchronous command execution without raising of errors with +|xolox#misc#os#exec()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#asynchronous_command_execution()* function + +Test the basic functionality of asynchronous command execution with +|xolox#misc#os#exec()|. This runs the external command 'mkdir' and tests that +the side effect of creating the directory takes place. This might seem like a +peculiar choice, but it's one of the few 100% portable commands (Windows + +UNIX) that doesn't involve input/output streams. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#string_case_transformation()* function + +Test string case transformation with |xolox#misc#str#ucfirst()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#string_whitespace_compaction()* function + +Test compaction of whitespace in strings with |xolox#misc#str#compact()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#string_whitespace_trimming()* function + +Test trimming of whitespace in strings with |xolox#misc#str#trim()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#multiline_string_dedent()* function + +Test dedenting of multi-line strings with |xolox#misc#str#dedent()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#version_string_parsing()* function + +Test parsing of version strings with |xolox#misc#version#parse()|. + +------------------------------------------------------------------------------- +The *xolox#misc#tests#version_string_comparison()* function + +Test comparison of version strings with |xolox#misc#version#at_least()|. + +------------------------------------------------------------------------------- + *misc-timing-of-long-during-operations* +Timing of long during operations ~ + +------------------------------------------------------------------------------- +The *xolox#misc#timer#resumable()* function + +Create a resumable timer object. This returns an object (a dictionary with +functions) with the following "methods": + +- 'start()' instructs the timer object to start counting elapsed time (when a + timer object is created it is not automatically started). + +- 'stop()' instructs the timer object to stop counting elapsed time. This + adds the time elapsed since 'start()' was last called to the total elapsed + time. This method will raise an error if called out of sequence. + +- 'format()' takes the total elapsed time and reports it as a string + containing a formatted floating point number. + +Timer objects are meant to accurately time short running operations so they're +dependent on Vim's |reltime()| and |reltimestr()| functions. In order to make +it possible to use timer objects in my Vim plug-ins unconditionally there's a +fall back to |localtime()| when |reltime()| is not available. In this mode the +timer objects are not very useful but at least they shouldn't raise errors. + +------------------------------------------------------------------------------- +The *xolox#misc#timer#start()* function + +Start a timer. This returns a list which can later be passed to +|xolox#misc#timer#stop()|. + +------------------------------------------------------------------------------- +The *xolox#misc#timer#stop()* function + +Show a formatted debugging message to the user, if the user has enabled +increased verbosity by setting Vim's |'verbose'| option to one (1) or higher. + +This function has the same argument handling as Vim's |printf()| function with +one difference: At the point where you want the elapsed time to be embedded, +you write '%s' and you pass the list returned by |xolox#misc#timer#start()| as +an argument. + +------------------------------------------------------------------------------- +The *xolox#misc#timer#force()* function + +Show a formatted message to the user. This function has the same argument +handling as Vim's |printf()| function with one difference: At the point where +you want the elapsed time to be embedded, you write '%s' and you pass the list +returned by |xolox#misc#timer#start()| as an argument. + +------------------------------------------------------------------------------- +The *xolox#misc#timer#convert()* function + +Convert the value returned by |xolox#misc#timer#start()| to a string +representation of the elapsed time since |xolox#misc#timer#start()| was called. +Other values are returned unmodified (this allows using it with Vim's |map()| +function). + +------------------------------------------------------------------------------- + *misc-version-string-handling* +Version string handling ~ + +------------------------------------------------------------------------------- +The *xolox#misc#version#parse()* function + +Convert a version string to a list of integers. + +------------------------------------------------------------------------------- +The *xolox#misc#version#at_least()* function + +Check whether the second version string is equal to or greater than the first +version string. Returns 1 (true) when it is, 0 (false) otherwise. + +=============================================================================== + *misc-contact* +Contact ~ + +If you have questions, bug reports, suggestions, etc. please open an issue or +pull request on GitHub [12]. Download links and documentation can be found on +the plug-in's homepage [13]. If you like the script please vote for it on Vim +Online [14]. + +=============================================================================== + *misc-license* +License ~ + +This software is licensed under the MIT license [15]. © 2015 Peter Odding +. + +=============================================================================== + *misc-references* +References ~ + +[1] http://peterodding.com/code/vim/ +[2] https://github.com/xolox/vim-misc/blob/master/INSTALL.md +[3] http://peterodding.com/code/vim/tools/ +[4] http://peterodding.com/code/vim/easytags/ +[5] http://peterodding.com/code/vim/misc/ +[6] http://peterodding.com/code/vim/notes/ +[7] http://peterodding.com/code/vim/notes/#recentnotes_command +[8] http://peterodding.com/code/vim/notes/#showtaggednotes_command +[9] http://peterodding.com/code/vim/session/ +[10] https://github.com/xolox/vim-misc/pull/16 +[11] http://peterodding.com/code/vim/shell/ +[12] http://github.com/xolox/vim-misc +[13] http://peterodding.com/code/vim/misc +[14] http://www.vim.org/scripts/script.php?script_id=4597 +[15] http://en.wikipedia.org/wiki/MIT_License + +vim: ft=help diff --git a/sources_non_forked/vim-misc/plugin/xolox/misc.vim b/sources_non_forked/vim-misc/plugin/xolox/misc.vim new file mode 100755 index 00000000..af65d553 --- /dev/null +++ b/sources_non_forked/vim-misc/plugin/xolox/misc.vim @@ -0,0 +1,19 @@ +" Vim plug-in +" Author: Peter Odding +" Last Change: June 21, 2014 +" URL: http://peterodding.com/code/vim/misc/ + +" Don't source the plug-in when it's already been loaded or &compatible is set. +if &cp || exists('g:loaded_xolox_misc') + finish +endif + +" Automatic commands used by the vim-misc plug-in. +augroup PluginXoloxMisc + autocmd! CursorHold,CursorHoldI * call xolox#misc#cursorhold#autocmd() +augroup END + +" Make sure the plug-in is only loaded once. +let g:loaded_xolox_misc = 1 + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-session-master/.gitignore b/sources_non_forked/vim-session-master/.gitignore new file mode 100755 index 00000000..926ccaaf --- /dev/null +++ b/sources_non_forked/vim-session-master/.gitignore @@ -0,0 +1 @@ +doc/tags diff --git a/sources_non_forked/vim-session-master/INSTALL.md b/sources_non_forked/vim-session-master/INSTALL.md new file mode 100755 index 00000000..bd09f8b8 --- /dev/null +++ b/sources_non_forked/vim-session-master/INSTALL.md @@ -0,0 +1,15 @@ +# Installation instructions + +*Please note that the vim-session plug-in requires my vim-misc plug-in which is separately distributed.* + +There are two ways to install the vim-session plug-in and it's up to you which you prefer, both options are explained below. Please note that below are generic installation instructions while some Vim plug-ins may have external dependencies, please refer to the plug-in's [readme](README.md) for details. + +## Installation using ZIP archives + +Unzip the most recent ZIP archives of the [vim-session](http://peterodding.com/code/vim/downloads/session.zip) and [vim-misc](http://peterodding.com/code/vim/downloads/misc.zip) plug-ins inside your Vim profile directory (usually this is `~/.vim` on UNIX and `%USERPROFILE%\vimfiles` on Windows), restart Vim and execute the command `:helptags ~/.vim/doc` (use `:helptags ~\vimfiles\doc` instead on Windows). + +If you get warnings about overwriting existing files while unpacking the ZIP archives you probably don't need to worry about this because it's most likely caused by files like `README.md`, `INSTALL.md` and `addon-info.json`. If these files bother you then you can remove them after unpacking the ZIP archives, they are not required to use the plug-in. + +## Installation using a Vim plug-in manager + +If you prefer you can also use [Pathogen](http://www.vim.org/scripts/script.php?script_id=2332), [Vundle](https://github.com/gmarik/vundle) or a similar tool to install and update the [vim-session](https://github.com/xolox/vim-session) and [vim-misc](https://github.com/xolox/vim-misc) plug-ins using local clones of the git repositories. This takes a bit of work to set up the first time but it makes updating much easier, and it keeps each plug-in in its own directory which helps to keep your Vim profile uncluttered. diff --git a/sources_non_forked/vim-session-master/README.md b/sources_non_forked/vim-session-master/README.md new file mode 100755 index 00000000..c38edaf1 --- /dev/null +++ b/sources_non_forked/vim-session-master/README.md @@ -0,0 +1,646 @@ +# Extended session management for Vim + +The vim-session plug-in improves upon [Vim](http://www.vim.org/)'s built-in [:mksession][mksession] command by enabling you to easily and (if you want) automatically persist and restore your Vim editing sessions. It works by generating a [Vim script](http://vimdoc.sourceforge.net/htmldoc/usr_41.html#script) that restores your current settings and the arrangement of tab pages and/or split windows and the files they contain. + +To persist your current editing session you can execute the `:SaveSession` command. If you don't provide a name for the session 'default' is used (you can change this name with an option). You're free to use whatever characters you like in session names. When you want to restore your session simply execute `:OpenSession`. Again the name 'default' is used if you don't provide one. When a session is active, has been changed and you quit Vim you'll be prompted whether you want to save the open session before quitting Vim: + +![Screenshot of auto-save prompt](https://raw.githubusercontent.com/xolox/vim-session/master/screenshots/session-save-prompt.png) + +If you want, the plug-in can also automatically save your session every few minutes (see the `g:session_autosave_periodic` option). When you start Vim without editing any files and the default session exists, you'll be prompted whether you want to restore the default session: + +![Screenshot of auto-open prompt](https://raw.githubusercontent.com/xolox/vim-session/master/screenshots/session-restore-prompt.png) + +When you start Vim with a custom [server name](http://vimdoc.sourceforge.net/htmldoc/remote.html#--servername) that matches one of the existing session names then the matching session will be automatically restored. For example I use several sessions to quickly edit my Vim plug-ins: + + $ gvim --servername easytags-plugin + $ gvim --servername session-plugin + $ # etc. + +The session scripts created by this plug-in are stored in the directory `~/.vim/sessions` (on UNIX) or `~\vimfiles\sessions` (on Windows) but you can change the location by setting `g:session_directory`. If you're curious what the session scripts generated by vim-session look like see the [sample below](http://peterodding.com/code/vim/session/#sample_session_script). + +If you're still getting to know the plug-in, the "Sessions" menu may help: It contains menu items for most commands defined by the plug-in. + +## Installation + +Please refer to the [installation instructions] [howto-install] available on GitHub. Once you've installed the plug-in the commands below will be available to you. + +## Commands + +Note that environment variables inside command arguments are expanded by the plug-in. + +### The `:SaveSession` command + +This command saves your current editing session just like Vim's built-in [:mksession][mksession] command does. The difference is that you don't pass a full pathname as argument but just a name, any name really. Press `` to get completion of existing session names. If you don't provide an argument the default session name is used, unless an existing session is open in which case the name of that session will be used. + +If the session you're trying to save is already active in another Vim instance you'll get a warning and nothing happens. You can use a bang (!) as in `:SaveSession! ...` to ignore the warning and save the session anyway. + +Your session script will be saved in the directory pointed to by the `g:session_directory` option. + +### The `:OpenSession` command + +This command is basically [:source][source] in disguise, but it supports tab completion of session names and it executes `:CloseSession` before opening the session. When you don't provide a session name and only a single session exists then that session is opened, otherwise the plug-in will ask you to select one from a list: + + Please select the session to restore: + + 1. vim-profile + 2. session-plugin + 3. etc. + + Type number and or click with mouse (empty cancels): + +If the session you're trying to open is already active in another Vim instance you'll get a warning and nothing happens. You can use a bang (!) as in `:OpenSession! ...` to ignore the warning and open the session anyway. + +Note also that when you use a bang (!) right after the command name existing tab pages and windows are closed, discarding any changes in the files you were editing! + +### The `:RestartVim` command + +This command saves your current editing session, restarts Vim and restores your editing session. This can come in handy when you're debugging Vim scripts which can't be easily/safely [reloaded using a more lightweight approach](http://peterodding.com/code/vim/reload/). It should work fine on Windows and UNIX alike but because of technical limitations it only works in graphical Vim. + +Any commands following the `:RestartVim` command are intercepted and executed after Vim is restarted and your session has been restored. This makes it easy to perform manual tests which involve restarting Vim, e.g. `:RestartVim | edit /path/to/file | call MyTest()`. + +### The `:CloseSession` command + +This command closes all but the current tab page and window and then edits a new, empty buffer. If a session is loaded when you execute this command the plug-in will first ask you whether you want to save that session. + +Note that when you use a bang (!) right after the command name existing tab pages and windows are closed, discarding any changes in the files you were editing! + +### The `:DeleteSession` command + +Using this command you can delete any of the sessions created by this plug-in. If the session you are trying to delete is currently active in another Vim instance you'll get a warning and nothing happens. You can use a bang (!) as in `:DeleteSession! ...` to ignore the warning and delete the session anyway. + +Note that this command only deletes the session script, it leaves your open tab pages and windows exactly as they were. + +### The `:ViewSession` command + +Execute this command to view the Vim script generated for a session. This command is useful when you need to review the generated Vim script repeatedly, for example while debugging or modifying the vim-session plug-in. + +### Tab scoped sessions + +When ['sessionoptions'] [sessionoptions] contains 'tabpages' (this is the default) session scripts will persist and restore all windows in all tab pages. When you remove 'tabpages' from ['sessionoptions'] [sessionoptions] you get a sort of light-weight sessions: They are constrained to a single tab page. Vim's [:mksession] [mksession] command and the vim-session plug-in both fully support this. + +You can change ['sessionoptions'] [sessionoptions] in your [vimrc script] [vimrc] but then you can never save a session including tab pages. To decide on the spot whether you want a global or tab scoped session, the vim-session plug-in defines the three commands documented below. + +Note that tab scoped sessions are regular session scripts, so when you load a tab scoped session using `:OpenSession` instead of `:OpenTabSession` the vim-session plug-in *assumes* it is a global session and will close all active tab pages before opening the tab scoped session. + +#### The `:OpenTabSession` command + +Just like `:OpenSession` but applies only to the current tab page. + +#### The `:SaveTabSession` command + +Just like `:SaveSession` but applies only to the current tab page. + +#### The `:AppendTabSession` command + +This command opens a new tab page and loads the given tab scoped session in that tab page. You can give this command a count just like [:tabnew] [tabnew]. + +#### The `:CloseTabSession` command + +Just like `:CloseSession` but applies only to the current tab page. + +## Options + +The following Vim options and plug-in options (global variables) can be used to configure the plug-in to your preferences. + +### The `sessionoptions` setting + +Because the vim-session plug-in uses Vim's [:mksession][mksession] command you can change how it works by setting ['sessionoptions'][sessionoptions] in your [vimrc script] [vimrc], for example: + + " If you only want to save the current tab page: + set sessionoptions-=tabpages + + " If you don't want help windows to be restored: + set sessionoptions-=help + +A lot of people don't like Vim's default behavior of saving hidden and unloaded buffers in sessions (which vim-session inherits due to the use of [:mksession][mksession]). To disable this behavior you can add the following line to your [vimrc script] [vimrc]: + + " Don't save hidden and unloaded buffers in sessions. + set sessionoptions-=buffers + +Note that the vim-session plug-in automatically and unconditionally executes the following change just before saving a session: + + " Don't persist options and mappings because it can corrupt sessions. + set sessionoptions-=options + +### The `g:session_directory` option + +This option controls the location of your session scripts. Its default value is `~/.vim/sessions` (on UNIX) or `~\vimfiles\sessions` (on Windows). If you don't mind the default you don't have to do anything; the directory will be created for you. Note that a leading `~` is expanded to your current home directory (`$HOME` on UNIX, `%USERPROFILE%` on Windows). + +### The `g:session_lock_directory` option + +The vim-session plug-in uses lock files to prevent double loading of sessions. The default location (directory) of these lock files depends on a couple of factors: + +1. If you have explicitly set the `g:session_lock_directory` option that defines the directory. +2. If the directory `/var/lock` exists and is writable that is used as a sane default. +3. As a sane fall back for platforms where `/var/lock` is not available the directory that stores the session scripts themselves is used. + +### The `g:session_lock_enabled` option + +Depending on your workflow locking of editing sessions can get annoying at times, so if you don't care about opening a session more than once and potentially "losing a version of your session" then you can use this option to completely disable session locking as follows: + + " Disable all session locking - I know what I'm doing :-). + let g:session_lock_enabled = 0 + +### The `g:session_default_name` option + +The name of the default session without directory or filename extension (you'll never guess what the default is). + +### The `g:session_default_overwrite` option + +If you set this to true (1), every Vim instance without an explicit session loaded will overwrite the default session (the last Vim instance wins). + +### The `g:session_extension` option + +The filename extension of session scripts. This should include the dot that separates the basename from the extension. Defaults to '.vim'. + +### The `g:session_autoload` option + +By default this option is set to `'prompt'`. This means that when you start Vim without opening any files and the default session script exists, the session plug-in will ask whether you want to restore your default session. When you set this option to `'yes'` and you start Vim without opening any files the default session will be restored without a prompt. To completely disable automatic loading you can set this option to `'no'`. + +### The `g:session_autosave` option + +By default this option is set to `'prompt'`. When you've opened a session and you quit Vim, the session plug-in will ask whether you want to save the changes to your session. Set this option to `'yes'` to always automatically save open sessions when you quit Vim. To completely disable automatic saving you can set this option to `'no'`. + +### The `g:session_autosave_to` option + +If `g:session_autosave` is `'yes'` and this option is a nonempty string, automatic session saving always saves to the session with the name given by `g:session_autosave_to` regardless of what the current session is or any other options. In particular, `g:session_default_overwrite` does not have any effect. By default this option isn't set so none of this applies. Refer to [pull request 81] [81] for a more detailed use case. + +### The `g:session_autosave_periodic` option + +This option sets the interval in minutes for automatic, periodic saving of active sessions. The default is zero which disables the feature. + +Note that when the plug-in automatically saves a session (because you enabled this feature) the plug-in will not prompt for your permission. + +### The `g:session_autosave_silent` option + +If you set this option to true (1) the messages normally emitted by automatic, periodic saving of active sessions are silenced. + +### The `g:session_verbose_messages` option + +The session load/save prompts are quite verbose by default because they explain how to disable the prompts. If you find the additional explanation distracting you can lower the verbosity by setting this option to 0 (false) in your [vimrc script] [vimrc]. + +### The `g:session_default_to_last` option + +By default this option is set to false (0). When you set this option to true (1) and you start Vim, the session plug-in will open your last used session instead of the default session. Note that the session plug-in will still show you the dialog asking whether you want to restore the last used session. To get rid of the dialog you have to set `g:session_autoload` to `'yes'`. + +### The `g:session_persist_font` option + +By default the plug-in will save the GUI font with the session to be reused the next time that session is loaded, this can be disabled by adding the following line to your [vimrc script] [vimrc]: + + :let g:session_persist_font = 0 + +### The `g:session_persist_colors` option + +By default the plug-in will save the color scheme and the ['background' option] [bg] with the session to be reused the next time that session is loaded, this can be disabled by adding the following line to your [vimrc script] [vimrc]: + + :let g:session_persist_colors = 0 + +### The `g:session_persist_globals` option + +The vim-session plug-in uses Vim's [:mksession] [mksession] command but it changes ['sessionoptions'][sessionoptions] so that Vim options and mappings are not persisted. The plug-in does this because persistence of options and mappings can break loading of sessions, in other words it's fragile (in my opinion). + +If you want the plug-in to persist specific global variables or options you can add their names to the list `g:session_persist_globals` in your [vimrc script] [vimrc]: + + " Persist the value of the global option 'makeprg'. + let g:session_persist_globals = ['&makeprg'] + +Because the [vimrc script] [vimrc] is loaded before the plug-in you have to define the list yourself. To persist multiple values: + + " Persist all options related to :make. + let g:session_persist_globals = ['&makeprg', '&makeef'] + +Here's how you persist global variables: (in this case the variables of the session plug-in itself :-) + + " Persist the options of the session plug-in using the session plug-in... + let g:session_persist_globals = ['&sessionoptions'] + call add(g:session_persist_globals, 'g:session_autoload') + call add(g:session_persist_globals, 'g:session_autosave') + call add(g:session_persist_globals, 'g:session_default_to_last') + call add(g:session_persist_globals, 'g:session_persist_globals') + +The example above doesn't persist the `g:session_directory` variable because this variable is used before loading a session script so persisting it inside the session script is pointless. + +### The `g:session_restart_environment` option + +This option is a list of environment variable names (without the dollar signs) that the `:RestartVim` command will pass on to the new instance of Vim. This option is only useful on UNIX. By default the three environment variables `$TERM`, `$VIM` and `$VIMRUNTIME` are included in this list. + +### The `g:session_command_aliases` option + +The names of the commands defined by the session plug-in start with the action they perform, followed by the string 'Session'. Some people prefer it the other way around because they find it easier to remember and you can type `:Session` to get completion of all available commands (actually this works with the other style as well if you type `:*Session` but I digress). If you are one of those people you can enable this option in your [vimrc script] [vimrc] like this: + + :let g:session_command_aliases = 1 + +When this option is enabled the session plug-in will define the following command aliases: + + * `SessionOpen` is an alias for `OpenSession` + * `SessionView` is an alias for `ViewSession` + * `SessionSave` is an alias for `SaveSession` + * `SessionDelete` is an alias for `DeleteSession` + * `SessionClose` is an alias for `CloseSession` + +Then there are the command aliases for tab scoped sessions: + + * `SessionTabOpen` is an alias for `OpenTabSession` + * `SessionTabSave` is an alias for `SaveTabSession` + * `SessionTabAppend` is an alias for `AppendTabSession` + * `SessionTabClose` is an alias for `CloseTabSession` + +The aliases support tab completion just like the real commands; they're exactly the same except for the names. + +When you enable the aliases, the default command names will still be available. If you really don't like them, feel free to delete them using [:delcommand] [delcommand]. + +### The `g:session_menu` option + +By default the plug-in installs a top level menu. If you don't like this you can disable it by adding the following line to your [vimrc script] [vimrc]: + + :let g:session_menu = 0 + +### The `g:session_name_suggestion_function` option + +The default completion of the `:SaveSession` command is based on the names of the existing sessions. You can add your own suggestions using this option by setting the option to the name of a Vim script function. By default this option is set to an example function that suggests the name of the current git or Mercurial feature branch (when you're working in a version control repository). + +### The `g:loaded_session` option + +This variable isn't really an option but if you want to avoid loading the vim-session plug-in you can set this variable to any value in your [vimrc script] [vimrc]: + + :let g:loaded_session = 1 + +## Compatibility with other plug-ins + +Vim's [:mksession][mksession] command isn't really compatible with plug-ins that create buffers with generated content and because of this the vim-session plug-in includes specific workarounds for a couple of popular plug-ins: + + * [BufExplorer](http://www.vim.org/scripts/script.php?script_id=42), [Conque Shell](http://www.vim.org/scripts/script.php?script_id=2771), [NERD tree](http://www.vim.org/scripts/script.php?script_id=1658), [Project](http://www.vim.org/scripts/script.php?script_id=69) and [taglist](http://www.vim.org/scripts/script.php?script_id=273) windows are supported; + * When [shell.vim](http://peterodding.com/code/vim/shell/) is installed Vim's full-screen state is persisted; + * The [netrw](http://vimdoc.sourceforge.net/htmldoc/pi_netrw.html#netrw-start) plug-in supports sessions out of the box. + +If your favorite plug-in doesn't work with the vim-session plug-in drop me a mail and I'll see what I can do. Please include a link to the plug-in in your e-mail so that I can install and test the plug-in. + +## Function reference + + + +The documentation of the 39 functions below was extracted from +2 Vim scripts on April 1, 2015 at 22:22. + +### Public API for the vim-session plug-in + +#### The `xolox#session#save_session()` function + +Save the current Vim editing session to a Vim script using the +[:mksession] [] command and some additional Vim magic provided by the +vim-session plug-in. When the generated session script is later sourced +using the [:source] [] command (possibly in another process or even on +another machine) it will restore the editing session to its previous state +(provided all of the files involved in the session are still there at +their original locations). + +The first argument is expected to be a list, it will be extended with the +lines to be added to the session script. The second argument is expected +to be the filename under which the script will later be saved (it's +embedded in a comment at the top of the script). + +[:mksession]: http://vimdoc.sourceforge.net/htmldoc/starting.html#:mksession +[:source]: http://vimdoc.sourceforge.net/htmldoc/repeat.html#:source + +#### The `xolox#session#save_globals()` function + +Serialize the values of the global variables configured by the user with +the `g:session_persist_globals` option. The first argument is expected to +be a list, it will be extended with the lines to be added to the session +script. + +#### The `xolox#session#save_features()` function + +Save the current state of the following Vim features: + +- Whether syntax highlighting is enabled (`:syntax on`) +- Whether file type detection is enabled (`:filetype on`) +- Whether file type plug-ins are enabled (`:filetype plugin on`) +- Whether file type indent plug-ins are enabled (`:filetype indent on`) + +The first argument is expected to be a list, it will be extended with the +lines to be added to the session script. + +#### The `xolox#session#save_colors()` function + +Save the current color scheme and background color. The first argument is +expected to be a list, it will be extended with the lines to be added to +the session script. + +#### The `xolox#session#save_fullscreen()` function + +Save the full screen state of Vim. This function provides integration +between my [vim-session] [] and [vim-shell] [] plug-ins. The first +argument is expected to be a list, it will be extended with the lines to +be added to the session script. + +[vim-session]: http://peterodding.com/code/vim/session +[vim-shell]: http://peterodding.com/code/vim/shell + +#### The `xolox#session#save_qflist()` function + +Save the contents of the quick-fix list. The first argument is expected to +be a list, it will be extended with the lines to be added to the session +script. + +#### The `xolox#session#save_state()` function + +Wrapper for the [:mksession] [] command that slightly massages the +generated Vim script to get rid of some strange quirks in the way Vim +generates sessions. Also implements support for buffers with content that +was generated by other Vim plug-ins. The first argument is expected to +be a list, it will be extended with the lines to be added to the session +script. + +#### The `xolox#session#save_special_windows()` function + +Implements support for buffers with content that was generated by other +Vim plug-ins. The first argument is expected to be a list, it will be +extended with the lines to be added to the session script. + +#### The `xolox#session#auto_load()` function + +Automatically load the default or last used session when Vim starts. +Normally called by the [VimEnter] [] automatic command event. + +[VimEnter]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#VimEnter + +#### The `xolox#session#is_empty()` function + +Check that the user has started Vim without editing any files. Used by +`xolox#session#auto_load()` to determine whether automatic session loading +should be performed. Currently checks the following conditions: + +1. That the current buffer is either empty (contains no lines and is not + modified) or showing [vim-startify] []. +2. That the buffer list either empty or persistent. + +[vim-startify]: https://github.com/mhinz/vim-startify/ + +#### The `xolox#session#auto_save()` function + +Automatically save the current editing session when Vim is closed. +Normally called by the [VimLeavePre] [] automatic command event. + +[VimLeavePre]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#VimLeavePre + +#### The `xolox#session#auto_save_periodic()` function + +Automatically saves the current editing session every few minutes. +Normally called by the [CursorHold] [] and [CursorHoldI] [] automatic +command events. + +[CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold +[CursorHoldI]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHoldI + +#### The `xolox#session#auto_unlock()` function + +Automatically unlock all sessions when Vim quits. Normally called by the +[VimLeavePre] [] automatic command event. + +[VimLeavePre]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#VimLeavePre + +#### The `xolox#session#prompt_for_name()` function + +Prompt the user to select one of the existing sessions. The first argument +is expected to be a string describing what will be done to the session +once it's been selected. Returns the name of the selected session as a +string. If no session is selected an empty string is returned. Here's +an example of what the prompt looks like: + + :call xolox#session#prompt_for_name('trash') + + Please select the session to trash: + + 1. first-session + 2. second-session + 3. third-session + + Type number and or click with mouse (empty cancels): + +If only a single session exists there's nothing to choose from so the name +of that session will be returned directly, without prompting the user. + +#### The `xolox#session#name_to_path()` function + +Convert the name of a session (the first argument, expected to be a +string) to an absolute pathname. Any special characters in the session +name will be encoded using URL encoding. This means you're free to use +whatever naming conventions you like (regardless of special characters +like slashes). Returns a string. + +#### The `xolox#session#path_to_name()` function + +Convert the absolute pathname of a session script (the first argument, +expected to be a string) to a session name. This function assumes the +absolute pathname refers to the configured session directory, but it does +not check for it nor does it require it (it simple takes the base name +of the absolute pathname of the session script and decodes it). Returns a +string. + +#### The `xolox#session#get_names()` function + +Get the names of all available sessions. This scans the directory +configured with `g:session_directory` for files that end with the suffix +configured with `g:session_extension`, takes the base name of each file +and decodes any URL encoded characters. Returns a list of strings. + +If the first argument is true (1) then the user defined function +configured with `g:session_name_suggestion_function` is called to find +suggested session names, which are prefixed to the list of available +sessions, otherwise the argument should be false (0). + +#### The `xolox#session#complete_names()` function + +Completion function for user defined Vim commands. Used by commands like +`:OpenSession` and `:DeleteSession` (but not `:SaveSession`) to support +user friendly completion. + +#### The `xolox#session#complete_names_with_suggestions()` function + +Completion function for the Vim command `:SaveSession`. + +#### The `xolox#session#is_tab_scoped()` function + +Determine whether the current session is tab scoped or global. Returns 1 +(true) when the session is tab scoped, 0 (false) otherwise. + +#### The `xolox#session#find_current_session()` function + +Find the name of the current tab scoped or global session. Returns a +string. If no session is active an empty string is returned. + +#### The `xolox#session#get_label()` function + +Get a human readable label based on the scope (tab scoped or global) and +name of a session. The first argument is the name (a string) and the +second argument is a boolean indicating the scope of the session; 1 (true) +means tab scoped and 0 (false) means global scope. Returns a string. + +#### The `xolox#session#options_include()` function + +Check whether Vim's [sessionoptions] [] option includes the keyword given +as the first argument (expected to be a string). Returns 1 (true) when it +does, 0 (false) otherwise. + +[sessionoptions]: http://vimdoc.sourceforge.net/htmldoc/options.html#'sessionoptions' + +#### The `xolox#session#include_tabs()` function + +Check whether Vim's [sessionoptions] [] option includes the `tabpages` +keyword. Returns 1 (true) when it does, 0 (false) otherwise. + +#### The `xolox#session#change_tab_options()` function + +Temporarily change Vim's [sessionoptions] [] option so we can save a tab +scoped session. Saves a copy of the original value to be restored later. + +#### The `xolox#session#restore_tab_options()` function + +Restore the original value of Vim's [sessionoptions] [] option. + +#### The `xolox#session#locking_enabled()` function + +Check whether session locking is enabled. Returns true (1) when locking is +enabled, false (0) otherwise. + +By default session locking is enabled but users can opt-out by setting +`g:session_lock_enabled` to false (0). + +### Example function for session name suggestions + +#### The `xolox#session#suggestions#vcs_feature_branch()` function + +This function implements an example of a function that can be used with +the `g:session_name_suggestion_function` option. It finds the name of the +current git or Mercurial feature branch (if any) and suggests this name as +the name for the session that is being saved with :SaveSession. Returns a +list with one string on success and an empty list on failure. + + + +## Troubleshooting + +### Using multiple platforms (multi boot, Cygwin, etc.) + +Session scripts cannot be shared between platforms because they contain absolute pathnames that most certainly won't match between e.g. Windows and Linux or even Windows and Cygwin. The best you can do is keep separate session scripts for different platforms (and I would certainly consider Cygwin a separate platform altogether :-). For more information please refer to [issue 85] [85]. + +## Contact + +If you have questions, bug reports, suggestions, etc. the author can be contacted at . The latest version is available at and . If you like the script please vote for it on [Vim Online](http://www.vim.org/scripts/script.php?script_id=3150). + +## License + +This software is licensed under the [MIT license](http://en.wikipedia.org/wiki/MIT_License). +© 2015 Peter Odding <> and Ingo Karkat. + +Thanks go out to everyone who has helped to improve the vim-session plug-in (whether through pull requests, bug reports or personal e-mails). + +## Sample session script + +Here's an example session script generated by the vim-session plug-in while I was editing the plug-in itself in Vim: + + " ~/.vim/sessions/example.vim: Vim session script. + " Created by session.vim on 30 August 2010 at 05:26:28. + " Open this file in Vim and run :source % to restore your session. + + set guioptions=aegit + set guifont=Monaco\ 13 + if exists('g:syntax_on') != 1 | syntax on | endif + if exists('g:did_load_filetypes') != 1 | filetype on | endif + if exists('g:did_load_ftplugin') != 1 | filetype plugin on | endif + if exists('g:did_indent_on') != 1 | filetype indent on | endif + if !exists('g:colors_name') || g:colors_name != 'slate' | colorscheme slate | endif + call setqflist([]) + let SessionLoad = 1 + if &cp | set nocp | endif + let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 + let v:this_session=expand(":p") + silent only + cd ~/Development/Vim/vim-session + if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' + let s:wipebuf = bufnr('%') + endif + set shortmess=aoO + badd +473 ~/Development/Vim/vim-session/autoload.vim + badd +1 ~/Development/Vim/vim-session/README.md + badd +1 ~/Development/Vim/vim-session/session.vim + badd +1 ~/Development/Vim/vim-session/TODO.md + set lines=43 columns=167 + edit ~/Development/Vim/vim-session/README.md + set splitbelow splitright + set nosplitbelow + set nosplitright + wincmd t + set winheight=1 winwidth=1 + argglobal + let s:l = 28 - ((27 * winheight(0) + 21) / 42) + if s:l < 1 | let s:l = 1 | endif + exe s:l + normal! zt + 28 + normal! 0 + tabedit ~/Development/Vim/vim-session/TODO.md + set splitbelow splitright + set nosplitbelow + set nosplitright + wincmd t + set winheight=1 winwidth=1 + argglobal + let s:l = 6 - ((5 * winheight(0) + 21) / 42) + if s:l < 1 | let s:l = 1 | endif + exe s:l + normal! zt + 6 + normal! 0 + tabedit ~/Development/Vim/vim-session/session.vim + set splitbelow splitright + set nosplitbelow + set nosplitright + wincmd t + set winheight=1 winwidth=1 + argglobal + let s:l = 17 - ((16 * winheight(0) + 21) / 42) + if s:l < 1 | let s:l = 1 | endif + exe s:l + normal! zt + 17 + normal! 014l + tabedit ~/Development/Vim/vim-session/autoload.vim + set splitbelow splitright + set nosplitbelow + set nosplitright + wincmd t + set winheight=1 winwidth=1 + argglobal + let s:l = 473 - ((41 * winheight(0) + 21) / 42) + if s:l < 1 | let s:l = 1 | endif + exe s:l + normal! zt + 473 + normal! 018l + tabnext 4 + if exists('s:wipebuf') + silent exe 'bwipe ' . s:wipebuf + endif + unlet! s:wipebuf + set winheight=1 winwidth=1 shortmess=filnxtToO + let s:sx = expand(":p:r")."x.vim" + if file_readable(s:sx) + exe "source " . fnameescape(s:sx) + endif + let &so = s:so_save | let &siso = s:siso_save + doautoall SessionLoadPost + unlet SessionLoad + + +[81]: https://github.com/xolox/vim-session/pull/81 +[85]: https://github.com/xolox/vim-session/issues/85 +[bg]: http://vimdoc.sourceforge.net/htmldoc/options.html#'background' +[delcommand]: http://vimdoc.sourceforge.net/htmldoc/map.html#:delcommand +[howto-install]: https://github.com/xolox/vim-session/blob/master/INSTALL.md +[mksession]: http://vimdoc.sourceforge.net/htmldoc/starting.html#:mksession +[sessionoptions]: http://vimdoc.sourceforge.net/htmldoc/options.html#%27sessionoptions%27 +[source]: http://vimdoc.sourceforge.net/htmldoc/repeat.html#:source +[tabnew]: http://vimdoc.sourceforge.net/htmldoc/tabpage.html#:tabnew +[vimrc]: http://vimdoc.sourceforge.net/htmldoc/starting.html#vimrc diff --git a/sources_non_forked/vim-session-master/TODO.md b/sources_non_forked/vim-session-master/TODO.md new file mode 100755 index 00000000..2819b4c7 --- /dev/null +++ b/sources_non_forked/vim-session-master/TODO.md @@ -0,0 +1,5 @@ +# To-do list + + * Vim's `:mksession` command doesn't support location list windows, find a good workaround? + * Try to find a more or less generic solution to restoring buffers with content generated at runtime by Vim plug-ins like the [NERD tree](http://www.vim.org/scripts/script.php?script_id=1658) and [Tag List](http://www.vim.org/scripts/script.php?script_id=273). + * Add a [SwapExists](http://vimdoc.sourceforge.net/htmldoc/autocmd.html#SwapExists) example to the documentation which enables multiple Vim processes to edit the same files without [E325 warnings](http://vimdoc.sourceforge.net/htmldoc/usr_11.html#E325). diff --git a/sources_non_forked/vim-session-master/addon-info.json b/sources_non_forked/vim-session-master/addon-info.json new file mode 100755 index 00000000..6106cc5e --- /dev/null +++ b/sources_non_forked/vim-session-master/addon-info.json @@ -0,0 +1 @@ +{"vim_script_nr": 3150, "dependencies": {"vim-misc": {}}, "homepage": "http://peterodding.com/code/vim/session", "name": "vim-session"} \ No newline at end of file diff --git a/sources_non_forked/vim-session-master/autoload/xolox/session.vim b/sources_non_forked/vim-session-master/autoload/xolox/session.vim new file mode 100755 index 00000000..1f580044 --- /dev/null +++ b/sources_non_forked/vim-session-master/autoload/xolox/session.vim @@ -0,0 +1,1158 @@ +" Public API for the vim-session plug-in. +" +" Author: Peter Odding +" Last Change: November 1, 2015 +" URL: http://peterodding.com/code/vim/session/ + +let g:xolox#session#version = '2.13.1' + +" Public API for session persistence. {{{1 + +function! xolox#session#save_session(commands, filename) " {{{2 + " Save the current Vim editing session to a Vim script using the + " [:mksession] [] command and some additional Vim magic provided by the + " vim-session plug-in. When the generated session script is later sourced + " using the [:source] [] command (possibly in another process or even on + " another machine) it will restore the editing session to its previous state + " (provided all of the files involved in the session are still there at + " their original locations). + " + " The first argument is expected to be a list, it will be extended with the + " lines to be added to the session script. The second argument is expected + " to be the filename under which the script will later be saved (it's + " embedded in a comment at the top of the script). + " + " [:mksession]: http://vimdoc.sourceforge.net/htmldoc/starting.html#:mksession + " [:source]: http://vimdoc.sourceforge.net/htmldoc/repeat.html#:source + let is_all_tabs = xolox#session#include_tabs() + call add(a:commands, '" ' . a:filename . ':') + call add(a:commands, '" Vim session script' . (is_all_tabs ? '' : ' for a single tab page') . '.') + call add(a:commands, '" Created by session.vim ' . g:xolox#session#version . ' on ' . strftime('%d %B %Y at %H:%M:%S.')) + call add(a:commands, '" Open this file in Vim and run :source % to restore your session.') + call add(a:commands, '') + if &verbose >= 1 + call add(a:commands, 'set verbose=' . &verbose) + endif + " We save the GUI options only for global sessions, not for tab scoped + " sessions. Also, if the Vim we're currently running in doesn't have GUI + " support, Vim will report &go as an empty string. We should never persist + " this value if the user didn't specifically set it! Otherwise the next time + " the session is restored in a GUI Vim, things will look funky :-). + if has('gui') && is_all_tabs + call add(a:commands, 'set guioptions=' . escape(&go, ' "\')) + if xolox#misc#option#get('session_persist_font', 1) + call add(a:commands, 'silent! set guifont=' . escape(&gfn, ' "\')) + endif + endif + call xolox#session#save_globals(a:commands) + if is_all_tabs + call xolox#session#save_features(a:commands) + if g:session_persist_colors + call xolox#session#save_colors(a:commands) + endif + endif + call xolox#session#save_qflist(a:commands) + call xolox#session#save_state(a:commands) + if is_all_tabs + call xolox#session#save_fullscreen(a:commands) + call add(a:commands, 'doautoall SessionLoadPost') + else + call add(a:commands, 'let s:winrestcmd = winrestcmd()') + call add(a:commands, 'windo doautocmd SessionLoadPost') + call s:jump_to_window(a:commands, tabpagenr(), winnr()) + call add(a:commands, 'silent! execute s:winrestcmd') + endif + call add(a:commands, 'unlet SessionLoad') + call add(a:commands, '" vim: ft=vim ro nowrap smc=128') +endfunction + +function! xolox#session#save_globals(commands) " {{{2 + " Serialize the values of the global variables configured by the user with + " the `g:session_persist_globals` option. The first argument is expected to + " be a list, it will be extended with the lines to be added to the session + " script. + for global in g:session_persist_globals + call add(a:commands, printf("let %s = %s", global, string(eval(global)))) + endfor +endfunction + +function! xolox#session#save_features(commands) " {{{2 + " Save the current state of the following Vim features: + " + " - Whether syntax highlighting is enabled (`:syntax on`) + " - Whether file type detection is enabled (`:filetype on`) + " - Whether file type plug-ins are enabled (`:filetype plugin on`) + " - Whether file type indent plug-ins are enabled (`:filetype indent on`) + " + " The first argument is expected to be a list, it will be extended with the + " lines to be added to the session script. + let template = "if exists('%s') != %i | %s %s | endif" + for [global, command] in [ + \ ['g:syntax_on', 'syntax'], + \ ['g:did_load_filetypes', 'filetype'], + \ ['g:did_load_ftplugin', 'filetype plugin'], + \ ['g:did_indent_on', 'filetype indent']] + let active = exists(global) + let toggle = active ? 'on' : 'off' + call add(a:commands, printf(template, global, active, command, toggle)) + endfor +endfunction + +function! xolox#session#save_colors(commands) " {{{2 + " Save the current color scheme and background color. The first argument is + " expected to be a list, it will be extended with the lines to be added to + " the session script. + call add(a:commands, 'if &background != ' . string(&background)) + call add(a:commands, "\tset background=" . &background) + call add(a:commands, 'endif') + if exists('g:colors_name') && type(g:colors_name) == type('') && g:colors_name != '' + let template = "if !exists('g:colors_name') || g:colors_name != %s | colorscheme %s | endif" + call add(a:commands, printf(template, string(g:colors_name), fnameescape(g:colors_name))) + endif +endfunction + +function! xolox#session#save_fullscreen(commands) " {{{2 + " Save the full screen state of Vim. This function provides integration + " between my [vim-session] [] and [vim-shell] [] plug-ins. The first + " argument is expected to be a list, it will be extended with the lines to + " be added to the session script. + " + " [vim-session]: http://peterodding.com/code/vim/session + " [vim-shell]: http://peterodding.com/code/vim/shell + try + let commands = xolox#shell#persist_fullscreen() + if !empty(commands) + call add(a:commands, "try") + for line in commands + call add(a:commands, " " . line) + endfor + if has('gui_running') && (has('gui_gtk') || has('gui_gtk2') || has('gui_gnome')) + " Without this hack GVim on GTK doesn't preserve the window size. + call add(a:commands, " call feedkeys(\":set lines=" . &lines . " columns=" . &columns . "\\\")") + endif + call add(a:commands, "catch " . '/^Vim\%((\a\+)\)\=:E117/') + call add(a:commands, " \" Ignore missing full-screen plug-in.") + call add(a:commands, "endtry") + endif + catch /^Vim\%((\a\+)\)\=:E117/ + " Ignore missing full-screen functionality. + endtry +endfunction + +function! xolox#session#save_qflist(commands) " {{{2 + " Save the contents of the quick-fix list. The first argument is expected to + " be a list, it will be extended with the lines to be added to the session + " script. + if has('quickfix') + let qf_list = [] + for qf_entry in getqflist() + if has_key(qf_entry, 'bufnr') + if !has_key(qf_entry, 'filename') + let qf_entry.filename = bufname(qf_entry.bufnr) + endif + unlet qf_entry.bufnr + endif + call add(qf_list, qf_entry) + endfor + call add(a:commands, 'call setqflist(' . string(qf_list) . ')') + endif +endfunction + +function! xolox#session#save_state(commands) " {{{2 + " Wrapper for the [:mksession] [] command that slightly massages the + " generated Vim script to get rid of some strange quirks in the way Vim + " generates sessions. Also implements support for buffers with content that + " was generated by other Vim plug-ins. The first argument is expected to + " be a list, it will be extended with the lines to be added to the session + " script. + let tempfile = tempname() + let ssop_save = &sessionoptions + try + " The default value of &sessionoptions includes "options" which causes + " :mksession to include all Vim options and mappings in generated session + " scripts. This can significantly increase the size of session scripts + " which makes them slower to generate and evaluate. It can also be a bit + " buggy, e.g. it breaks Ctrl-S when :runtime mswin.vim has been used. The + " value of &sessionoptions is changed temporarily to avoid these issues. + set ssop-=options + execute 'mksession' fnameescape(tempfile) + let lines = readfile(tempfile) + " Remove the mode line added by :mksession because we'll add our own in + " xolox#session#save_session(). + call s:eat_trailing_line(lines, '" vim: set ft=vim :') + " Remove the "SessionLoadPost" event firing at the end of the :mksession + " output. We will fire the event ourselves when we're really done. + call s:eat_trailing_line(lines, 'unlet SessionLoad') + call s:eat_trailing_line(lines, 'doautoall SessionLoadPost') + call xolox#session#save_special_windows(lines) + if !xolox#session#include_tabs() + " Customize the output of :mksession for tab scoped sessions. + let buffers = tabpagebuflist() + call map(lines, 's:tabpage_filter(buffers, v:val)') + endif + call extend(a:commands, map(lines, 's:state_filter(v:val)')) + " Re-implement Vim's special handling of the initial, empty buffer. + call add(a:commands, "if exists('s:wipebuf')") + call add(a:commands, " if empty(bufname(s:wipebuf))") + call s:cleanup_after_plugin(a:commands, 's:wipebuf') + call add(a:commands, " endif") + call add(a:commands, "endif") + return 1 + finally + let &sessionoptions = ssop_save + call delete(tempfile) + endtry +endfunction + +function! s:eat_trailing_line(session, line) " {{{3 + " Remove matching, trailing strings from a list of strings. + if a:session[-1] == a:line + call remove(a:session, -1) + endif +endfunction + +function! s:tabpage_filter(buffers, line) " {{{3 + " Change output of :mksession if for single tab page. + if a:line =~ '^badd +\d\+ ' + " The :mksession command adds all open buffers to a session even for tab + " scoped sessions. That makes sense, but we want only the buffers in the + " tab page to be included. That's why we filter out any references to the + " rest of the buffers from the script generated by :mksession. + let pathname = matchstr(a:line, '^badd +\d\+ \zs.*') + let bufnr = bufnr('^' . pathname . '$') + if index(a:buffers, bufnr) == -1 + return '" ' . a:line + endif + elseif a:line =~ '^let v:this_session\s*=' + " The :mksession command unconditionally adds the global v:this_session + " variable definition to the session script, but we want a differently + " scoped variable for tab scoped sessions. + return substitute(a:line, 'v:this_session', 't:this_session', 'g') + endif + " Preserve all other lines. + return a:line +endfunction + +function! s:state_filter(line) " {{{3 + " Various changes to the output of :mksession. + if a:line =~ '^normal!\? zo$' + " Silence "E490: No fold found" errors. + return 'silent! ' . a:line + elseif a:line =~ '^file .\{-}\ 0 && winnr('$') > 1 + call add(a:session, winrestcmd) + endif +endfunction + +function! s:check_special_window(session) + " If we detected a special window and the argument to the command is not a + " pathname, this variable should be set to false to disable normalization. + let do_normalize_path = 1 + let bufname = expand('%:t') + if exists('b:NERDTreeRoot') + if !has_key(s:nerdtrees, bufnr('%')) + let command = 'NERDTree' + let argument = b:NERDTreeRoot.path.str() + let s:nerdtrees[bufnr('%')] = 1 + else + let command = 'NERDTreeMirror' + let argument = '' + endif + elseif bufname == '[BufExplorer]' + let command = 'BufExplorer' + let argument = '' + elseif bufname == '__Tag_List__' + let command = 'Tlist' + let argument = '' + elseif exists('g:proj_running') && g:proj_running == bufnr('%') + let command = 'Project' + let argument = expand('%:p') + elseif exists('b:ConqueTerm_Idx') + let command = 'ConqueTerm' + let argument = g:ConqueTerm_Terminals[b:ConqueTerm_Idx]['program_name'] + let do_normalize_path = 0 + elseif &filetype == 'netrw' + let command = 'edit' + let argument = bufname('%') + elseif &buftype == 'quickfix' + let command = 'cwindow' + let argument = '' + endif + if exists('command') + call s:jump_to_window(a:session, tabpagenr(), winnr()) + call add(a:session, 'let s:bufnr_save = bufnr("%")') + call add(a:session, 'let s:cwd_save = getcwd()') + if argument == '' + call add(a:session, command) + else + if do_normalize_path + let argument = fnamemodify(argument, ':~') + if xolox#session#options_include('slash') + let argument = substitute(argument, '\', '/', 'g') + endif + endif + call add(a:session, command . ' ' . fnameescape(argument)) + endif + call s:cleanup_after_plugin(a:session, 's:bufnr_save') + call add(a:session, 'execute "cd" fnameescape(s:cwd_save)') + return 1 + endif +endfunction + +function! s:jump_to_window(session, tabpage, window) + call add(a:session, a:window . 'wincmd w') + if xolox#session#include_tabs() + call add(a:session, 'tabnext ' . a:tabpage) + endif +endfunction + +function! s:nerdtree_persist() + " Remember current working directory and whether NERDTree is loaded. + if exists('b:NERDTreeRoot') + return 'NERDTree ' . fnameescape(b:NERDTreeRoot.path.str()) . ' | only' + else + return 'cd ' . fnameescape(getcwd()) + endif +endfunction + +function! s:cleanup_after_plugin(commands, bufnr_var) + call add(a:commands, "if !getbufvar(" . a:bufnr_var . ", '&modified')") + call add(a:commands, " let s:wipebuflines = getbufline(" . a:bufnr_var . ", 1, '$')") + call add(a:commands, " if len(s:wipebuflines) <= 1 && empty(get(s:wipebuflines, 0, ''))") + call add(a:commands, " silent execute 'bwipeout' " . a:bufnr_var) + call add(a:commands, " endif") + call add(a:commands, "endif") +endfunction + +" Automatic commands to manage the default session. {{{1 + +function! xolox#session#auto_load() " {{{2 + " Automatically load the default or last used session when Vim starts. + " Normally called by the [VimEnter] [] automatic command event. + " + " [VimEnter]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#VimEnter + if g:session_autoload == 'no' + return + endif + " Check that the user has started Vim without editing any files. + if xolox#session#is_empty() + " Check whether a session matching the user-specified server name exists. + if v:servername !~ '^\cgvim\d*$' + for session in xolox#session#get_names(0) + if v:servername ==? session + call xolox#session#open_cmd(session, '', 'OpenSession') + return + endif + endfor + endif + " Default to the last used session or the default session? + let [has_last_session, session] = s:get_last_or_default_session() + let path = xolox#session#name_to_path(session) + if (g:session_default_to_last == 0 || has_last_session) && filereadable(path) && !s:session_is_locked(session, 'OpenSession') + " Compose the message for the prompt. + let is_default_session = (session == g:session_default_name) + let msg = printf("Do you want to restore your %s editing session%s?", + \ is_default_session ? 'default' : 'last used', + \ is_default_session ? '' : printf(' (%s)', session)) + " Prepare the list of choices. + let choices = ["&Restore", "&Don't Restore"] + if g:session_default_to_last && has_last_session + call add(choices, "&Forget") + endif + " Prompt the user (if not configured otherwise). + let choice = s:prompt(msg, choices, 'g:session_autoload') + if choice == 1 + call xolox#session#open_cmd(session, '', 'OpenSession') + elseif choice == 3 + call s:last_session_forget() + endif + endif + endif +endfunction + +function! xolox#session#is_empty() " {{{2 + " Check that the user has started Vim without editing any files. Used by + " `xolox#session#auto_load()` to determine whether automatic session loading + " should be performed. Currently checks the following conditions: + " + " 1. That the current buffer is either empty (contains no lines and is not + " modified) or showing [vim-startify] []. + " 2. That the buffer list either empty or persistent. + " + " [vim-startify]: https://github.com/mhinz/vim-startify/ + let current_buffer_is_empty = (&modified == 0 && getline(1, '$') == ['']) + let current_buffer_is_startify = (&filetype == 'startify') + let buffer_list_is_empty = (bufname('%') == '' && empty(filter(range(1, bufnr('$')), 'buflisted(v:val) && v:val != ' . bufnr('')))) + let buffer_list_is_persistent = (index(xolox#misc#option#split(&viminfo), '%') >= 0) + return (current_buffer_is_empty || current_buffer_is_startify) && (buffer_list_is_empty || buffer_list_is_persistent) +endfunction + +function! xolox#session#auto_save() " {{{2 + " Automatically save the current editing session when Vim is closed. + " Normally called by the [VimLeavePre] [] automatic command event. + " + " [VimLeavePre]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#VimLeavePre + if v:dying + " We won't save the session if Vim is not terminating normally. + return + endif + if g:session_autosave == 'no' + " We won't save the session if auto-save is explicitly disabled. + return + endif + " Get the name of the session for automatic saving. + let name = xolox#misc#option#get('session_autosave_to') + if empty(name) + " Get the name of the active session (if any). + let name = xolox#session#find_current_session() + " If no session is active and the user doesn't have any sessions yet, + " help them get started by suggesting to create the default session. + if empty(name) && (empty(xolox#session#get_names(0)) || g:session_default_overwrite) + let name = g:session_default_name + endif + endif + " Prompt the user to save the active/first/default session? + if !empty(name) + let is_tab_scoped = xolox#session#is_tab_scoped() + let msg = "Do you want to save your %s before quitting Vim?" + if s:prompt(printf(msg, xolox#session#get_label(name, is_tab_scoped)), ["&Save", "&Don't Save"], 'g:session_autosave') == 1 + if g:session_default_overwrite && (name == g:session_default_name) + let bang = '!' + else + let bang = '' + endif + if is_tab_scoped + call xolox#session#save_tab_cmd(name, bang, 'SaveTabSession') + else + call xolox#session#save_cmd(name, bang, 'SaveSession') + endif + endif + endif +endfunction + +function! xolox#session#auto_save_periodic() " {{{2 + " Automatically saves the current editing session every few minutes. + " Normally called by the [CursorHold] [] and [CursorHoldI] [] automatic + " command events. + " + " [CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold + " [CursorHoldI]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHoldI + if g:session_autosave_periodic > 0 + let interval = g:session_autosave_periodic * 60 + let next_save = s:session_last_flushed + interval + if localtime() > next_save + let name = xolox#session#find_current_session() + if !empty(name) + if xolox#session#is_tab_scoped() + let function = 'xolox#session#save_tab_cmd' + let arguments = [name, '', 'SaveTabSession'] + else + let function = 'xolox#session#save_cmd' + let arguments = [name, '', 'SaveSession'] + endif + if xolox#misc#option#get('session_autosave_silent', 0) + " Silence informational messages perceived as noisy. + " https://github.com/xolox/vim-session/issues/120 + silent call call(function, arguments) + else + call call(function, arguments) + endif + endif + endif + endif +endfunction + +function! s:flush_session() + let s:session_last_flushed = localtime() +endfunction + +if !exists('s:session_last_flushed') + call s:flush_session() +endif + +function! xolox#session#auto_unlock() " {{{2 + " Automatically unlock all sessions when Vim quits. Normally called by the + " [VimLeavePre] [] automatic command event. + " + " [VimLeavePre]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#VimLeavePre + if xolox#session#locking_enabled() + let i = 0 + while i < len(s:lock_files) + let lock_file = s:lock_files[i] + if delete(lock_file) == 0 + call remove(s:lock_files, i) + else + let i += 1 + endif + endwhile + endif +endfunction + +" Commands that enable users to manage multiple sessions. {{{1 + +function! s:prompt(msg, choices, option_name) + let option_value = eval(a:option_name) + if option_value == 'yes' + return 1 + elseif option_value == 'no' + return 0 + else + if g:session_verbose_messages + let format = "%s\n\nNote that you can permanently disable this dialog by adding the following line to your %s script:\n\n\t:let %s = 'no'" + let prompt = printf(format, a:msg, xolox#misc#os#is_win() ? '~\_vimrc' : '~/.vimrc', a:option_name) + else + let prompt = a:msg + endif + return confirm(prompt, join(a:choices, "\n"), 1, 'Question') + endif +endfunction + +function! xolox#session#open_cmd(name, bang, command) abort " {{{2 + let name = s:unescape(a:name) + if empty(name) + let name = xolox#session#prompt_for_name('restore') + endif + if name == '' + return -1 + else + let starttime = xolox#misc#timer#start() + let path = xolox#session#name_to_path(name) + if !filereadable(path) + let msg = "session.vim %s: The %s session at %s doesn't exist!" + call xolox#misc#msg#warn(msg, g:xolox#session#version, string(name), fnamemodify(path, ':~')) + return 0 + elseif a:bang == '!' || !s:session_is_locked(name, a:command) + let oldcwd = s:nerdtree_persist() + call xolox#session#close_cmd(a:bang, 1, name != xolox#session#find_current_session(), a:command) + call s:lock_session(path) + execute 'source' fnameescape(path) + if xolox#session#is_tab_scoped() + call s:lock_session(path) " Retroactively (this is only known after the session has been loaded) add the tabpage to the lock. + let t:session_old_cwd = oldcwd + let session_type = 'tab scoped' + else + let g:session_old_cwd = oldcwd + let session_type = 'global' + endif + call s:last_session_persist(name) + call s:flush_session() + call xolox#misc#timer#stop("session.vim %s: Opened %s %s session in %s.", g:xolox#session#version, session_type, string(name), starttime) + call xolox#misc#msg#info("session.vim %s: Opened %s %s session from %s.", g:xolox#session#version, session_type, string(name), fnamemodify(path, ':~')) + endif + endif + return 1 +endfunction + +function! xolox#session#view_cmd(name) abort " {{{2 + let name = s:unescape(a:name) + " Default to the current session? + if empty(name) + let name = xolox#session#find_current_session() + endif + " Prompt the user to select a session. + if empty(name) + let name = xolox#session#prompt_for_name('view') + endif + if name != '' + let path = xolox#session#name_to_path(name) + if !filereadable(path) + let msg = "session.vim %s: The %s session at %s doesn't exist!" + call xolox#misc#msg#warn(msg, g:xolox#session#version, string(name), fnamemodify(path, ':~')) + else + if has('gui_running') + execute 'tab drop' fnameescape(path) + else + execute 'tabedit' fnameescape(path) + endif + call xolox#misc#msg#info("session.vim %s: Viewing session script %s.", g:xolox#session#version, fnamemodify(path, ':~')) + endif + endif +endfunction + +function! xolox#session#save_cmd(name, bang, command) abort " {{{2 + let starttime = xolox#misc#timer#start() + let name = s:unescape(a:name) + if empty(name) + let name = xolox#session#find_current_session() + endif + if empty(name) + let name = g:session_default_name + endif + let path = xolox#session#name_to_path(name) + let friendly_path = fnamemodify(path, ':~') + if a:bang == '!' || !s:session_is_locked(name, a:command) + let lines = [] + call xolox#session#save_session(lines, friendly_path) + if xolox#misc#os#is_win() && !xolox#session#options_include('unix') + call map(lines, 'v:val . "\r"') + endif + if writefile(lines, path) != 0 + let msg = "session.vim %s: Failed to save %s session to %s!" + call xolox#misc#msg#warn(msg, g:xolox#session#version, string(name), friendly_path) + else + call s:last_session_persist(name) + call s:flush_session() + let label = xolox#session#get_label(name, !xolox#session#include_tabs()) + call xolox#misc#timer#stop("session.vim %s: Saved %s in %s.", g:xolox#session#version, label, starttime) + call xolox#misc#msg#info("session.vim %s: Saved %s to %s.", g:xolox#session#version, label, friendly_path) + if xolox#session#include_tabs() + let v:this_session = path + else + let t:this_session = path + endif + call s:lock_session(path) + endif + endif +endfunction + +function! xolox#session#delete_cmd(name, bang) " {{{2 + let name = s:unescape(a:name) + if empty(name) + let name = xolox#session#prompt_for_name('delete') + endif + if name != '' + let path = xolox#session#name_to_path(name) + if !filereadable(path) + let msg = "session.vim %s: The %s session at %s doesn't exist!" + call xolox#misc#msg#warn(msg, g:xolox#session#version, string(name), fnamemodify(path, ':~')) + elseif a:bang == '!' || !s:session_is_locked(name, 'DeleteSession') + if delete(path) != 0 + let msg = "session.vim %s: Failed to delete %s session at %s!" + call xolox#misc#msg#warn(msg, g:xolox#session#version, string(name), fnamemodify(path, ':~')) + else + call s:unlock_session(path) + let msg = "session.vim %s: Deleted %s session at %s." + call xolox#misc#msg#info(msg, g:xolox#session#version, string(name), fnamemodify(path, ':~')) + endif + endif + endif +endfunction + +function! xolox#session#close_cmd(bang, silent, save_allowed, command) abort " {{{2 + let is_all_tabs = xolox#session#include_tabs() + let name = xolox#session#find_current_session() + if name != '' + if a:save_allowed + let msg = "Do you want to save your %s before closing it?" + let label = xolox#session#get_label(name, !is_all_tabs) + if s:prompt(printf(msg, label), ["&Save", "&Don't Save"], 'g:session_autosave') == 1 + call xolox#session#save_cmd(name, a:bang, a:command) + endif + else + call xolox#misc#msg#debug("session.vim %s: Session reset requested, not saving changes to session ..", g:xolox#session#version) + endif + call s:unlock_session(xolox#session#name_to_path(name)) + endif + " Close al but the current tab page? + if is_all_tabs && tabpagenr('$') > 1 + execute 'tabonly' . a:bang + endif + " Close all but the current window. + if winnr('$') > 1 + execute 'only' . a:bang + endif + " Start editing a new, empty buffer. + execute 'enew' . a:bang + " Close all but the current buffer. + let bufnr_save = bufnr('%') + let all_buffers = is_all_tabs ? range(1, bufnr('$')) : tabpagebuflist() + for bufnr in all_buffers + if buflisted(bufnr) && bufnr != bufnr_save + execute 'silent bdelete' bufnr + endif + endfor + " Restore working directory (and NERDTree?) from before :OpenSession. + if is_all_tabs && exists('g:session_old_cwd') + execute g:session_old_cwd + unlet g:session_old_cwd + elseif !is_all_tabs && exists('t:session_old_cwd') + execute t:session_old_cwd + unlet t:session_old_cwd + endif + call s:flush_session() + if !a:silent + let msg = "session.vim %s: Closed %s." + let label = xolox#session#get_label(xolox#session#find_current_session(), !is_all_tabs) + call xolox#misc#msg#info(msg, g:xolox#session#version, label) + endif + if xolox#session#is_tab_scoped() + let t:this_session = '' + else + let v:this_session = '' + endif + return 1 +endfunction + +function! xolox#session#open_tab_cmd(name, bang, command) abort " {{{2 + try + call xolox#session#change_tab_options() + call xolox#session#open_cmd(a:name, a:bang, a:command) + finally + call xolox#session#restore_tab_options() + endtry +endfunction + +function! xolox#session#save_tab_cmd(name, bang, command) abort " {{{2 + try + call xolox#session#change_tab_options() + call xolox#session#save_cmd(a:name, a:bang, a:command) + finally + call xolox#session#restore_tab_options() + endtry +endfunction + +function! xolox#session#append_tab_cmd(name, bang, count, command) abort " {{{2 + try + call xolox#session#change_tab_options() + let original_tabpage = tabpagenr() + execute printf('%stabnew', a:count == -1 ? '' : a:count) + let status = xolox#session#open_cmd(a:name, a:bang, a:command) + if status <= 0 && empty(bufname('')) + tabclose + if tabpagenr() != original_tabpage + execute original_tabpage . 'tabnext' + endif + if status == 0 + " Switching tab pages cleared the warning message. Repeat it now. + call xolox#misc#msg#warn(get(g:xolox_messages, -1, '')) + endif + endif + finally + call xolox#session#restore_tab_options() + endtry +endfunction + +function! xolox#session#close_tab_cmd(bang, command) abort " {{{2 + let save_allowed = xolox#session#is_tab_scoped() + try + call xolox#session#change_tab_options() + call xolox#session#close_cmd(a:bang, 0, save_allowed, a:command) + finally + call xolox#session#restore_tab_options() + endtry +endfunction + +function! xolox#session#restart_cmd(bang, args) abort " {{{2 + if !has('gui_running') + " In console Vim we can't start a new Vim and kill the old one... + let msg = "session.vim %s: The :RestartVim command only works in graphical Vim!" + call xolox#misc#msg#warn(msg, g:xolox#session#version) + else + " Save the current session (if there is no active + " session we will create a session called "restart"). + let name = xolox#session#find_current_session() + if empty(name) + let name = 'restart' + endif + call xolox#session#save_cmd(name, a:bang, 'RestartVim') + " Generate the Vim command line. + let progname = xolox#misc#escape#shell(xolox#misc#os#find_vim()) + let command = progname . ' -g -c ' . xolox#misc#escape#shell('OpenSession\! ' . fnameescape(name)) + let args = matchstr(a:args, '^\s*|\s*\zs.\+$') + if !empty(args) + let command .= ' -c ' . xolox#misc#escape#shell(args) + endif + if !empty(v:servername) + let command .= ' --servername ' . xolox#misc#escape#shell(v:servername) + endif + " Close the session, releasing the session lock. + call xolox#session#close_cmd(a:bang, 0, 1, 'RestartVim') + " Start the new Vim instance. + if xolox#misc#os#is_win() + " On Microsoft Windows. + execute '!start' command + else + " On anything other than Windows (UNIX like). + let cmdline = [] + for variable in g:session_restart_environment + call add(cmdline, variable . '=' . xolox#misc#escape#shell(fnameescape(eval('$' . variable)))) + endfor + call add(cmdline, command) + call add(cmdline, printf("--cmd ':set enc=%s'", escape(&enc, '\ '))) + silent execute '!' join(cmdline, ' ') '&' + endif + " Close Vim. + silent quitall + endif +endfunction + +" Miscellaneous functions. {{{1 + +function! s:unescape(s) " {{{2 + " Undo escaping of special characters (preceded by a backslash). + let s = substitute(a:s, '\\\(.\)', '\1', 'g') + " Expand any environment variables in the user input. + let s = substitute(s, '\(\$[A-Za-z0-9_]\+\)', '\=expand(submatch(1))', 'g') + return s +endfunction + +function! xolox#session#prompt_for_name(action) " {{{2 + " Prompt the user to select one of the existing sessions. The first argument + " is expected to be a string describing what will be done to the session + " once it's been selected. Returns the name of the selected session as a + " string. If no session is selected an empty string is returned. Here's + " an example of what the prompt looks like: + " + " :call xolox#session#prompt_for_name('trash') + " + " Please select the session to trash: + " + " 1. first-session + " 2. second-session + " 3. third-session + " + " Type number and or click with mouse (empty cancels): + " + " If only a single session exists there's nothing to choose from so the name + " of that session will be returned directly, without prompting the user. + let sessions = sort(xolox#session#get_names(0), 1) + if len(sessions) == 1 + return sessions[0] + elseif !empty(sessions) + let lines = copy(sessions) + for i in range(len(sessions)) + let lines[i] = ' ' . (i + 1) . '. ' . lines[i] + endfor + redraw + sleep 100 m + echo "\nPlease select the session to " . a:action . ":" + sleep 100 m + let i = inputlist([''] + lines + ['']) + if i >= 1 && i <= len(sessions) + return sessions[i - 1] + endif + endif + return '' +endfunction + +function! xolox#session#name_to_path(name) " {{{2 + " Convert the name of a session (the first argument, expected to be a + " string) to an absolute pathname. Any special characters in the session + " name will be encoded using URL encoding. This means you're free to use + " whatever naming conventions you like (regardless of special characters + " like slashes). Returns a string. + let directory = xolox#misc#path#absolute(g:session_directory) + let filename = xolox#misc#path#encode(a:name) . g:session_extension + return xolox#misc#path#merge(directory, filename) +endfunction + +function! xolox#session#path_to_name(path) " {{{2 + " Convert the absolute pathname of a session script (the first argument, + " expected to be a string) to a session name. This function assumes the + " absolute pathname refers to the configured session directory, but it does + " not check for it nor does it require it (it simple takes the base name + " of the absolute pathname of the session script and decodes it). Returns a + " string. + return xolox#misc#path#decode(fnamemodify(a:path, ':t:r')) +endfunction + +function! xolox#session#get_names(include_suggestions) " {{{2 + " Get the names of all available sessions. This scans the directory + " configured with `g:session_directory` for files that end with the suffix + " configured with `g:session_extension`, takes the base name of each file + " and decodes any URL encoded characters. Returns a list of strings. + " + " If the first argument is true (1) then the user defined function + " configured with `g:session_name_suggestion_function` is called to find + " suggested session names, which are prefixed to the list of available + " sessions, otherwise the argument should be false (0). + let directory = xolox#misc#path#absolute(g:session_directory) + let filenames = split(glob(xolox#misc#path#merge(directory, '*' . g:session_extension)), "\n") + call map(filenames, 'xolox#session#path_to_name(v:val)') + if a:include_suggestions && !empty(g:session_name_suggestion_function) + let suggested_names = call(g:session_name_suggestion_function, []) + let filenames = suggested_names + filenames + endif + return filenames +endfunction + +function! xolox#session#complete_names(arg, line, pos) " {{{2 + " Completion function for user defined Vim commands. Used by commands like + " `:OpenSession` and `:DeleteSession` (but not `:SaveSession`) to support + " user friendly completion. + let names = filter(xolox#session#get_names(0), 'v:val =~ a:arg') + return map(names, 'fnameescape(v:val)') +endfunction + +function! xolox#session#complete_names_with_suggestions(arg, line, pos) " {{{2 + " Completion function for the Vim command `:SaveSession`. + let names = filter(xolox#session#get_names(1), 'v:val =~ a:arg') + return map(names, 'fnameescape(v:val)') +endfunction + +function! xolox#session#is_tab_scoped() " {{{2 + " Determine whether the current session is tab scoped or global. Returns 1 + " (true) when the session is tab scoped, 0 (false) otherwise. + return exists('t:this_session') +endfunction + +function! xolox#session#find_current_session() " {{{2 + " Find the name of the current tab scoped or global session. Returns a + " string. If no session is active an empty string is returned. + for variable in ['t:this_session', 'v:this_session'] + if exists(variable) + let filename = eval(variable) + if !empty(filename) + let directory = fnamemodify(filename, ':p:h') + if xolox#misc#path#equals(directory, g:session_directory) + return xolox#session#path_to_name(filename) + endif + endif + endif + endfor + return '' +endfunction + +function! xolox#session#get_label(name, is_tab_scoped) " {{{2 + " Get a human readable label based on the scope (tab scoped or global) and + " name of a session. The first argument is the name (a string) and the + " second argument is a boolean indicating the scope of the session; 1 (true) + " means tab scoped and 0 (false) means global scope. Returns a string. + if a:name == g:session_default_name + let description = 'default editing session' + else + let description = printf('editing session %s', string(a:name)) + endif + if a:is_tab_scoped + let description = printf('tab scoped %s', description) + endif + return description +endfunction + +function! xolox#session#options_include(value) " {{{2 + " Check whether Vim's [sessionoptions] [] option includes the keyword given + " as the first argument (expected to be a string). Returns 1 (true) when it + " does, 0 (false) otherwise. + " + " [sessionoptions]: http://vimdoc.sourceforge.net/htmldoc/options.html#'sessionoptions' + return index(xolox#misc#option#split(&sessionoptions), a:value) >= 0 +endfunction + +" Tab scoped sessions: {{{2 + +function! xolox#session#include_tabs() " {{{3 + " Check whether Vim's [sessionoptions] [] option includes the `tabpages` + " keyword. Returns 1 (true) when it does, 0 (false) otherwise. + return xolox#session#options_include('tabpages') +endfunction + +function! xolox#session#change_tab_options() " {{{3 + " Temporarily change Vim's [sessionoptions] [] option so we can save a tab + " scoped session. Saves a copy of the original value to be restored later. + let s:ssop_save = &sessionoptions + " Only persist the current tab page. + set sessionoptions-=tabpages + " Don't persist the size and position of the Vim window. + set ssop-=winpos ssop-=resize +endfunction + +function! xolox#session#restore_tab_options() " {{{3 + " Restore the original value of Vim's [sessionoptions] [] option. + if exists('s:ssop_save') + let &ssop = s:ssop_save + unlet s:ssop_save + endif +endfunction + +" Default to last used session: {{{2 + +function! s:last_session_file() + let directory = xolox#misc#path#absolute(g:session_directory) + return xolox#misc#path#merge(directory, 'last-session.txt') +endfunction + +function! s:last_session_persist(name) + if g:session_default_to_last + if writefile([a:name], s:last_session_file()) != 0 + call xolox#misc#msg#warn("session.vim %s: Failed to persist name of last used session!", g:xolox#session#version) + endif + endif +endfunction + +function! s:last_session_forget() + let last_session_file = s:last_session_file() + if filereadable(last_session_file) && delete(last_session_file) != 0 + call xolox#misc#msg#warn("session.vim %s: Failed to delete name of last used session!", g:xolox#session#version) + endif +endfunction + +function! s:get_last_or_default_session() + let last_session_file = s:last_session_file() + let has_last_session = filereadable(last_session_file) + if g:session_default_to_last && has_last_session + let lines = readfile(last_session_file) + return [has_last_session, lines[0]] + else + return [has_last_session, g:session_default_name] + endif +endfunction + +" Lock file management: {{{2 + +if !exists('s:lock_files') + let s:lock_files = [] +endif + +function! xolox#session#locking_enabled() + " Check whether session locking is enabled. Returns true (1) when locking is + " enabled, false (0) otherwise. + " + " By default session locking is enabled but users can opt-out by setting + " `g:session_lock_enabled` to false (0). + return xolox#misc#option#get('session_lock_enabled', 1) +endfunction + +function! s:vim_instance_id() + let id = {'pid': getpid()} + if !empty(v:servername) + let id['servername'] = v:servername + endif + if !xolox#session#include_tabs() || xolox#session#is_tab_scoped() + let id['tabpage'] = tabpagenr() + endif + return id +endfunction + +function! s:lock_file_path(session_path) + let directory = xolox#misc#option#get('session_lock_directory', '') + if empty(directory) + " Stale lock files can be really annoying, especially after a reboot + " because that just shouldn't happen - it's always a bug. References: + " - https://github.com/xolox/vim-session/issues/97 + " - https://github.com/xolox/vim-session/issues/110 + " One simple way to give a large group of users what they want is to use a + " volatile directory that is specifically meant for storing lock files. + " I've decided to make this the default when possible. The best reference + " I've been able to find on the proper system wide location for lock files + " is the following (yes, I know, it's Linux specific, so sue me): + " http://www.tldp.org/LDP/Linux-Filesystem-Hierarchy/html/var.html + let global_lock_directory = '/var/lock' + if filewritable(global_lock_directory) == 2 + let directory = global_lock_directory + endif + endif + if !empty(directory) + let pathname = xolox#misc#path#merge(directory, xolox#misc#path#encode(a:session_path)) + else + let pathname = a:session_path + endif + return pathname . '.lock' +endfunction + +function! s:lock_session(session_path) + if !xolox#session#locking_enabled() + return 1 + endif + let lock_file = s:lock_file_path(a:session_path) + if xolox#misc#persist#save(lock_file, s:vim_instance_id()) + if index(s:lock_files, lock_file) == -1 + call add(s:lock_files, lock_file) + endif + return 1 + endif +endfunction + +function! s:unlock_session(session_path) + if !xolox#session#locking_enabled() + return 1 + endif + let lock_file = s:lock_file_path(a:session_path) + if delete(lock_file) == 0 + let idx = index(s:lock_files, lock_file) + if idx >= 0 + call remove(s:lock_files, idx) + endif + return 1 + endif +endfunction + +function! s:session_is_locked(session_name, command) + if !xolox#session#locking_enabled() + return 0 + endif + let session_path = xolox#session#name_to_path(a:session_name) + let lock_file = s:lock_file_path(session_path) + if filereadable(lock_file) + let this_instance = s:vim_instance_id() + let other_instance = xolox#misc#persist#load(lock_file) + let arguments = [g:xolox#session#version, string(a:session_name)] + if this_instance == other_instance + " Session belongs to current Vim instance and tab page. + return 0 + elseif this_instance['pid'] == other_instance['pid'] + if has_key(other_instance, 'tabpage') + let msg = "session.vim %s: The %s session is already loaded in tab page %s." + call add(arguments, other_instance['tabpage']) + else + let msg = "session.vim %s: The %s session is already loaded in this Vim." + endif + else + let msg = "session.vim %s: The %s session is locked by another Vim instance %s." + if has_key(other_instance, 'servername') + call add(arguments, 'named ' . other_instance['servername']) + else + call add(arguments, 'with PID ' . other_instance['pid']) + endif + let msg .= " If that doesn't seem right maybe you forcefully closed Vim or it crashed?" + endif + let msg .= " Use the command ':%s! %s' to override." + call extend(arguments, [a:command, a:session_name]) + call call('xolox#misc#msg#warn', [msg] + arguments) + return 1 + endif +endfunction + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-session-master/autoload/xolox/session/suggestions.vim b/sources_non_forked/vim-session-master/autoload/xolox/session/suggestions.vim new file mode 100755 index 00000000..1f844762 --- /dev/null +++ b/sources_non_forked/vim-session-master/autoload/xolox/session/suggestions.vim @@ -0,0 +1,42 @@ +" Example function for session name suggestions. +" +" Author: Peter Odding +" Last Change: July 6, 2014 +" URL: http://peterodding.com/code/vim/session/ + +function! xolox#session#suggestions#vcs_feature_branch() " {{{1 + " This function implements an example of a function that can be used with + " the `g:session_name_suggestion_function` option. It finds the name of the + " current git or Mercurial feature branch (if any) and suggests this name as + " the name for the session that is being saved with :SaveSession. Returns a + " list with one string on success and an empty list on failure. + let [kind, directory] = xolox#session#suggestions#find_vcs_repository() + if kind == 'git' + let command = 'git rev-parse --abbrev-ref HEAD' + let names_to_ignore = ['master'] + elseif kind == 'hg' + let command = 'hg branch' + let names_to_ignore = ['default'] + else + return [] + endif + let result = xolox#misc#os#exec({'command': command, 'check': 0}) + if result['exit_code'] == 0 && !empty(result['stdout']) + let branch_name = xolox#misc#str#trim(result['stdout'][0]) + if !empty(branch_name) && index(names_to_ignore, branch_name) == -1 + return [xolox#misc#str#slug(branch_name)] + endif + endif + return [] +endfunction + +function! xolox#session#suggestions#find_vcs_repository() + for name in ['git', 'hg'] + let match = finddir('.' . name, '.;') + if !empty(match) + let directory = fnamemodify(match, ':h') + return [name, directory] + endif + endfor + return ['', ''] +endfunction diff --git a/sources_non_forked/vim-session-master/doc/session.txt b/sources_non_forked/vim-session-master/doc/session.txt new file mode 100755 index 00000000..2148461f --- /dev/null +++ b/sources_non_forked/vim-session-master/doc/session.txt @@ -0,0 +1,960 @@ +*session.txt* Extended session management for Vim + +=============================================================================== +Contents ~ + + 1. Introduction |session-introduction| + 2. Installation |session-installation| + 3. Commands |session-commands| + 1. The |:SaveSession| command + 2. The |:OpenSession| command + 3. The |:RestartVim| command + 4. The |:CloseSession| command + 5. The |:DeleteSession| command + 6. The |:ViewSession| command + 7. Tab scoped sessions |tab-scoped-sessions| + 1. The |:OpenTabSession| command + 2. The |:SaveTabSession| command + 3. The |:AppendTabSession| command + 4. The |:CloseTabSession| command + 4. Options |session-options| + 1. The |sessionoptions| setting + 2. The |g:session_directory| option + 3. The |g:session_lock_directory| option + 4. The |g:session_lock_enabled| option + 5. The |g:session_default_name| option + 6. The |g:session_default_overwrite| option + 7. The |g:session_extension| option + 8. The |g:session_autoload| option + 9. The |g:session_autosave| option + 10. The |g:session_autosave_to| option + 11. The |g:session_autosave_periodic| option + 12. The |g:session_autosave_silent| option + 13. The |g:session_verbose_messages| option + 14. The |g:session_default_to_last| option + 15. The |g:session_persist_font| option + 16. The |g:session_persist_colors| option + 17. The |g:session_persist_globals| option + 18. The |g:session_restart_environment| option + 19. The |g:session_command_aliases| option + 20. The |g:session_menu| option + 21. The |g:session_name_suggestion_function| option + 22. The |g:loaded_session| option + 5. Compatibility with other plug-ins |session-compatibility-with-other-plug-ins| + 6. Function reference |session-function-reference| + 1. Public API for the vim-session plug-in |public-api-for-vim-session-plug-in| + 1. The |xolox#session#save_session()| function + 2. The |xolox#session#save_globals()| function + 3. The |xolox#session#save_features()| function + 4. The |xolox#session#save_colors()| function + 5. The |xolox#session#save_fullscreen()| function + 6. The |xolox#session#save_qflist()| function + 7. The |xolox#session#save_state()| function + 8. The |xolox#session#save_special_windows()| function + 9. The |xolox#session#auto_load()| function + 10. The |xolox#session#is_empty()| function + 11. The |xolox#session#auto_save()| function + 12. The |xolox#session#auto_save_periodic()| function + 13. The |xolox#session#auto_unlock()| function + 14. The |xolox#session#prompt_for_name()| function + 15. The |xolox#session#name_to_path()| function + 16. The |xolox#session#path_to_name()| function + 17. The |xolox#session#get_names()| function + 18. The |xolox#session#complete_names()| function + 19. The |xolox#session#complete_names_with_suggestions()| function + 20. The |xolox#session#is_tab_scoped()| function + 21. The |xolox#session#find_current_session()| function + 22. The |xolox#session#get_label()| function + 23. The |xolox#session#options_include()| function + 24. The |xolox#session#include_tabs()| function + 25. The |xolox#session#change_tab_options()| function + 26. The |xolox#session#restore_tab_options()| function + 27. The |xolox#session#locking_enabled()| function + 2. Example function for session name suggestions |example-function-for-session-name-suggestions| + 1. The |xolox#session#suggestions#vcs_feature_branch()| function + 7. Troubleshooting |session-troubleshooting| + 1. Using multiple platforms (multi boot, Cygwin, etc.) |session-using-multiple-platforms| + 8. Contact |session-contact| + 9. License |session-license| + 10. Sample session script |sample-session-script| + 11. References |session-references| + +=============================================================================== + *session-introduction* +Introduction ~ + +The vim-session plug-in improves upon Vim's built-in |:mksession| command by +enabling you to easily and (if you want) automatically persist and restore your +Vim editing sessions. It works by generating a Vim |script| that restores your +current settings and the arrangement of tab pages and/or split windows and the +files they contain. + +To persist your current editing session you can execute the |:SaveSession| +command. If you don't provide a name for the session 'default' is used (you can +change this name with an option). You're free to use whatever characters you +like in session names. When you want to restore your session simply execute +|:OpenSession|. Again the name 'default' is used if you don't provide one. When +a session is active, has been changed and you quit Vim you'll be prompted +whether you want to save the open session before quitting Vim: + + Image: Screenshot of auto-save prompt (see reference [1]) + +If you want, the plug-in can also automatically save your session every few +minutes (see the |g:session_autosave_periodic| option). When you start Vim +without editing any files and the default session exists, you'll be prompted +whether you want to restore the default session: + + Image: Screenshot of auto-open prompt (see reference [2]) + +When you start Vim with a custom server name (see |--servername|) that matches +one of the existing session names then the matching session will be +automatically restored. For example I use several sessions to quickly edit my +Vim plug-ins: +> + $ gvim --servername easytags-plugin + $ gvim --servername session-plugin + $ # etc. +< +The session scripts created by this plug-in are stored in the directory +'~/.vim/sessions' (on UNIX) or '~\vimfiles\sessions' (on Windows) but you can +change the location by setting |g:session_directory|. If you're curious what +the session scripts generated by vim-session look like see the sample below +[3]. + +If you're still getting to know the plug-in, the "Sessions" menu may help: It +contains menu items for most commands defined by the plug-in. + +=============================================================================== + *session-installation* +Installation ~ + +Please refer to the installation instructions [4] available on GitHub. Once +you've installed the plug-in the commands below will be available to you. + +=============================================================================== + *session-commands* +Commands ~ + +Note that environment variables inside command arguments are expanded by the +plug-in. + +------------------------------------------------------------------------------- +The *:SaveSession* command + +This command saves your current editing session just like Vim's built-in +|:mksession| command does. The difference is that you don't pass a full +pathname as argument but just a name, any name really. Press '' to get +completion of existing session names. If you don't provide an argument the +default session name is used, unless an existing session is open in which case +the name of that session will be used. + +If the session you're trying to save is already active in another Vim instance +you'll get a warning and nothing happens. You can use a bang (!) as in +':SaveSession! ...' to ignore the warning and save the session anyway. + +Your session script will be saved in the directory pointed to by the +|g:session_directory| option. + +------------------------------------------------------------------------------- +The *:OpenSession* command + +This command is basically |:source| in disguise, but it supports tab completion +of session names and it executes |:CloseSession| before opening the session. +When you don't provide a session name and only a single session exists then +that session is opened, otherwise the plug-in will ask you to select one from a +list: +> + Please select the session to restore: + + 1. vim-profile + 2. session-plugin + 3. etc. + + Type number and or click with mouse (empty cancels): +< +If the session you're trying to open is already active in another Vim instance +you'll get a warning and nothing happens. You can use a bang (!) as in +':OpenSession! ...' to ignore the warning and open the session anyway. + +Note also that when you use a bang (!) right after the command name existing +tab pages and windows are closed, discarding any changes in the files you were +editing! + +------------------------------------------------------------------------------- +The *:RestartVim* command + +This command saves your current editing session, restarts Vim and restores your +editing session. This can come in handy when you're debugging Vim scripts which +can't be easily/safely reloaded using a more lightweight approach [5]. It +should work fine on Windows and UNIX alike but because of technical limitations +it only works in graphical Vim. + +Any commands following the |:RestartVim| command are intercepted and executed +after Vim is restarted and your session has been restored. This makes it easy +to perform manual tests which involve restarting Vim, e.g. ':RestartVim | edit +/path/to/file | call MyTest()'. + +------------------------------------------------------------------------------- +The *:CloseSession* command + +This command closes all but the current tab page and window and then edits a +new, empty buffer. If a session is loaded when you execute this command the +plug-in will first ask you whether you want to save that session. + +Note that when you use a bang (!) right after the command name existing tab +pages and windows are closed, discarding any changes in the files you were +editing! + +------------------------------------------------------------------------------- +The *:DeleteSession* command + +Using this command you can delete any of the sessions created by this plug-in. +If the session you are trying to delete is currently active in another Vim +instance you'll get a warning and nothing happens. You can use a bang (!) as in +':DeleteSession! ...' to ignore the warning and delete the session anyway. + +Note that this command only deletes the session script, it leaves your open tab +pages and windows exactly as they were. + +------------------------------------------------------------------------------- +The *:ViewSession* command + +Execute this command to view the Vim script generated for a session. This +command is useful when you need to review the generated Vim script repeatedly, +for example while debugging or modifying the vim-session plug-in. + +------------------------------------------------------------------------------- + *tab-scoped-sessions* +Tab scoped sessions ~ + +When |'sessionoptions'| contains 'tabpages' (this is the default) session +scripts will persist and restore all windows in all tab pages. When you remove +'tabpages' from |'sessionoptions'| you get a sort of light-weight sessions: +They are constrained to a single tab page. Vim's |:mksession| command and the +vim-session plug-in both fully support this. + +You can change |'sessionoptions'| in your |vimrc| script but then you can never +save a session including tab pages. To decide on the spot whether you want a +global or tab scoped session, the vim-session plug-in defines the three +commands documented below. + +Note that tab scoped sessions are regular session scripts, so when you load a +tab scoped session using |:OpenSession| instead of |:OpenTabSession| the vim- +session plug-in _assumes_ it is a global session and will close all active tab +pages before opening the tab scoped session. + +------------------------------------------------------------------------------- +The *:OpenTabSession* command + +Just like |:OpenSession| but applies only to the current tab page. + +------------------------------------------------------------------------------- +The *:SaveTabSession* command + +Just like |:SaveSession| but applies only to the current tab page. + +------------------------------------------------------------------------------- +The *:AppendTabSession* command + +This command opens a new tab page and loads the given tab scoped session in +that tab page. You can give this command a count just like |:tabnew|. + +------------------------------------------------------------------------------- +The *:CloseTabSession* command + +Just like |:CloseSession| but applies only to the current tab page. + +=============================================================================== + *session-options* +Options ~ + +The following Vim options and plug-in options (global variables) can be used to +configure the plug-in to your preferences. + +------------------------------------------------------------------------------- +The *sessionoptions* setting + +Because the vim-session plug-in uses Vim's |:mksession| command you can change +how it works by setting |'sessionoptions'| in your |vimrc| script, for example: +> + " If you only want to save the current tab page: + set sessionoptions-=tabpages + + " If you don't want help windows to be restored: + set sessionoptions-=help +< +A lot of people don't like Vim's default behavior of saving hidden and unloaded +buffers in sessions (which vim-session inherits due to the use of +|:mksession|). To disable this behavior you can add the following line to your +|vimrc| script: +> + " Don't save hidden and unloaded buffers in sessions. + set sessionoptions-=buffers +< +Note that the vim-session plug-in automatically and unconditionally executes +the following change just before saving a session: +> + " Don't persist options and mappings because it can corrupt sessions. + set sessionoptions-=options +< +------------------------------------------------------------------------------- +The *g:session_directory* option + +This option controls the location of your session scripts. Its default value is +'~/.vim/sessions' (on UNIX) or '~\vimfiles\sessions' (on Windows). If you don't +mind the default you don't have to do anything; the directory will be created +for you. Note that a leading '~' is expanded to your current home directory +('$HOME' on UNIX, '%USERPROFILE%' on Windows). + +------------------------------------------------------------------------------- +The *g:session_lock_directory* option + +The vim-session plug-in uses lock files to prevent double loading of sessions. +The default location (directory) of these lock files depends on a couple of +factors: + +1. If you have explicitly set the |g:session_lock_directory| option that + defines the directory. + +2. If the directory '/var/lock' exists and is writable that is used as a + sane default. + +3. As a sane fall back for platforms where '/var/lock' is not available the + directory that stores the session scripts themselves is used. + +------------------------------------------------------------------------------- +The *g:session_lock_enabled* option + +Depending on your workflow locking of editing sessions can get annoying at +times, so if you don't care about opening a session more than once and +potentially "losing a version of your session" then you can use this option to +completely disable session locking as follows: +> + " Disable all session locking - I know what I'm doing :-). + let g:session_lock_enabled = 0 +< +------------------------------------------------------------------------------- +The *g:session_default_name* option + +The name of the default session without directory or filename extension (you'll +never guess what the default is). + +------------------------------------------------------------------------------- +The *g:session_default_overwrite* option + +If you set this to true (1), every Vim instance without an explicit session +loaded will overwrite the default session (the last Vim instance wins). + +------------------------------------------------------------------------------- +The *g:session_extension* option + +The filename extension of session scripts. This should include the dot that +separates the basename from the extension. Defaults to '.vim'. + +------------------------------------------------------------------------------- +The *g:session_autoload* option + +By default this option is set to "'prompt'". This means that when you start Vim +without opening any files and the default session script exists, the session +plug-in will ask whether you want to restore your default session. When you set +this option to "'yes'" and you start Vim without opening any files the default +session will be restored without a prompt. To completely disable automatic +loading you can set this option to "'no'". + +------------------------------------------------------------------------------- +The *g:session_autosave* option + +By default this option is set to "'prompt'". When you've opened a session and +you quit Vim, the session plug-in will ask whether you want to save the changes +to your session. Set this option to "'yes'" to always automatically save open +sessions when you quit Vim. To completely disable automatic saving you can set +this option to "'no'". + +------------------------------------------------------------------------------- +The *g:session_autosave_to* option + +If |g:session_autosave| is "'yes'" and this option is a nonempty string, +automatic session saving always saves to the session with the name given by +|g:session_autosave_to| regardless of what the current session is or any other +options. In particular, |g:session_default_overwrite| does not have any effect. +By default this option isn't set so none of this applies. Refer to pull request +81 [6] for a more detailed use case. + +------------------------------------------------------------------------------- +The *g:session_autosave_periodic* option + +This option sets the interval in minutes for automatic, periodic saving of +active sessions. The default is zero which disables the feature. + +Note that when the plug-in automatically saves a session (because you enabled +this feature) the plug-in will not prompt for your permission. + +------------------------------------------------------------------------------- +The *g:session_autosave_silent* option + +If you set this option to true (1) the messages normally emitted by automatic, +periodic saving of active sessions are silenced. + +------------------------------------------------------------------------------- +The *g:session_verbose_messages* option + +The session load/save prompts are quite verbose by default because they explain +how to disable the prompts. If you find the additional explanation distracting +you can lower the verbosity by setting this option to 0 (false) in your |vimrc| +script. + +------------------------------------------------------------------------------- +The *g:session_default_to_last* option + +By default this option is set to false (0). When you set this option to true +(1) and you start Vim, the session plug-in will open your last used session +instead of the default session. Note that the session plug-in will still show +you the dialog asking whether you want to restore the last used session. To get +rid of the dialog you have to set |g:session_autoload| to "'yes'". + +------------------------------------------------------------------------------- +The *g:session_persist_font* option + +By default the plug-in will save the GUI font with the session to be reused the +next time that session is loaded, this can be disabled by adding the following +line to your |vimrc| script: +> + :let g:session_persist_font = 0 +< +------------------------------------------------------------------------------- +The *g:session_persist_colors* option + +By default the plug-in will save the color scheme and the |'background'| option +with the session to be reused the next time that session is loaded, this can be +disabled by adding the following line to your |vimrc| script: +> + :let g:session_persist_colors = 0 +< +------------------------------------------------------------------------------- +The *g:session_persist_globals* option + +The vim-session plug-in uses Vim's |:mksession| command but it changes +|'sessionoptions'| so that Vim options and mappings are not persisted. The +plug-in does this because persistence of options and mappings can break loading +of sessions, in other words it's fragile (in my opinion). + +If you want the plug-in to persist specific global variables or options you can +add their names to the list |g:session_persist_globals| in your |vimrc| script: +> + " Persist the value of the global option 'makeprg'. + let g:session_persist_globals = ['&makeprg'] +< +Because the |vimrc| script is loaded before the plug-in you have to define the +list yourself. To persist multiple values: +> + " Persist all options related to :make. + let g:session_persist_globals = ['&makeprg', '&makeef'] +< +Here's how you persist global variables: (in this case the variables of the +session plug-in itself :-) +> + " Persist the options of the session plug-in using the session plug-in... + let g:session_persist_globals = ['&sessionoptions'] + call add(g:session_persist_globals, 'g:session_autoload') + call add(g:session_persist_globals, 'g:session_autosave') + call add(g:session_persist_globals, 'g:session_default_to_last') + call add(g:session_persist_globals, 'g:session_persist_globals') +< +The example above doesn't persist the |g:session_directory| variable because +this variable is used before loading a session script so persisting it inside +the session script is pointless. + +------------------------------------------------------------------------------- +The *g:session_restart_environment* option + +This option is a list of environment variable names (without the dollar signs) +that the |:RestartVim| command will pass on to the new instance of Vim. This +option is only useful on UNIX. By default the three environment variables +'$TERM', '$VIM' and '$VIMRUNTIME' are included in this list. + +------------------------------------------------------------------------------- +The *g:session_command_aliases* option + +The names of the commands defined by the session plug-in start with the action +they perform, followed by the string 'Session'. Some people prefer it the other +way around because they find it easier to remember and you can type +':Session' to get completion of all available commands (actually this +works with the other style as well if you type ':*Session' but I digress). +If you are one of those people you can enable this option in your |vimrc| +script like this: +> + :let g:session_command_aliases = 1 +< +When this option is enabled the session plug-in will define the following +command aliases: + +- 'SessionOpen' is an alias for 'OpenSession' +- 'SessionView' is an alias for 'ViewSession' +- 'SessionSave' is an alias for 'SaveSession' +- 'SessionDelete' is an alias for 'DeleteSession' +- 'SessionClose' is an alias for 'CloseSession' + +Then there are the command aliases for tab scoped sessions: + +- 'SessionTabOpen' is an alias for 'OpenTabSession' +- 'SessionTabSave' is an alias for 'SaveTabSession' +- 'SessionTabAppend' is an alias for 'AppendTabSession' +- 'SessionTabClose' is an alias for 'CloseTabSession' + +The aliases support tab completion just like the real commands; they're exactly +the same except for the names. + +When you enable the aliases, the default command names will still be available. +If you really don't like them, feel free to delete them using |:delcommand|. + +------------------------------------------------------------------------------- +The *g:session_menu* option + +By default the plug-in installs a top level menu. If you don't like this you +can disable it by adding the following line to your |vimrc| script: +> + :let g:session_menu = 0 +< +------------------------------------------------------------------------------- +The *g:session_name_suggestion_function* option + +The default completion of the |:SaveSession| command is based on the names of +the existing sessions. You can add your own suggestions using this option by +setting the option to the name of a Vim script function. By default this option +is set to an example function that suggests the name of the current git or +Mercurial feature branch (when you're working in a version control repository). + +------------------------------------------------------------------------------- +The *g:loaded_session* option + +This variable isn't really an option but if you want to avoid loading the vim- +session plug-in you can set this variable to any value in your |vimrc| script: +> + :let g:loaded_session = 1 +< +=============================================================================== + *session-compatibility-with-other-plug-ins* +Compatibility with other plug-ins ~ + +Vim's |:mksession| command isn't really compatible with plug-ins that create +buffers with generated content and because of this the vim-session plug-in +includes specific workarounds for a couple of popular plug-ins: + +- BufExplorer [7], Conque Shell [8], NERD tree [9], Project [10] and taglist + [11] windows are supported; +- When shell.vim [12] is installed Vim's full-screen state is persisted; +- The netrw (see |netrw-start|) plug-in supports sessions out of the box. + +If your favorite plug-in doesn't work with the vim-session plug-in drop me a +mail and I'll see what I can do. Please include a link to the plug-in in your +e-mail so that I can install and test the plug-in. + +=============================================================================== + *session-function-reference* +Function reference ~ + +The documentation of the 39 functions below was extracted from 2 Vim scripts on +April 1, 2015 at 22:22. + +------------------------------------------------------------------------------- + *public-api-for-vim-session-plug-in* +Public API for the vim-session plug-in ~ + +------------------------------------------------------------------------------- +The *xolox#session#save_session()* function + +Save the current Vim editing session to a Vim script using the |:mksession| +command and some additional Vim magic provided by the vim-session plug-in. When +the generated session script is later sourced using the |:source| command +(possibly in another process or even on another machine) it will restore the +editing session to its previous state (provided all of the files involved in +the session are still there at their original locations). + +The first argument is expected to be a list, it will be extended with the lines +to be added to the session script. The second argument is expected to be the +filename under which the script will later be saved (it's embedded in a comment +at the top of the script). + +------------------------------------------------------------------------------- +The *xolox#session#save_globals()* function + +Serialize the values of the global variables configured by the user with the +|g:session_persist_globals| option. The first argument is expected to be a +list, it will be extended with the lines to be added to the session script. + +------------------------------------------------------------------------------- +The *xolox#session#save_features()* function + +Save the current state of the following Vim features: + +- Whether syntax highlighting is enabled (':syntax on') +- Whether file type detection is enabled (':filetype on') +- Whether file type plug-ins are enabled (':filetype plugin on') +- Whether file type indent plug-ins are enabled (':filetype indent on') + +The first argument is expected to be a list, it will be extended with the lines +to be added to the session script. + +------------------------------------------------------------------------------- +The *xolox#session#save_colors()* function + +Save the current color scheme and background color. The first argument is +expected to be a list, it will be extended with the lines to be added to the +session script. + +------------------------------------------------------------------------------- +The *xolox#session#save_fullscreen()* function + +Save the full screen state of Vim. This function provides integration between +my vim-session [13] and vim-shell [14] plug-ins. The first argument is expected +to be a list, it will be extended with the lines to be added to the session +script. + +------------------------------------------------------------------------------- +The *xolox#session#save_qflist()* function + +Save the contents of the quick-fix list. The first argument is expected to be a +list, it will be extended with the lines to be added to the session script. + +------------------------------------------------------------------------------- +The *xolox#session#save_state()* function + +Wrapper for the |:mksession| command that slightly massages the generated Vim +script to get rid of some strange quirks in the way Vim generates sessions. +Also implements support for buffers with content that was generated by other +Vim plug-ins. The first argument is expected to be a list, it will be extended +with the lines to be added to the session script. + +------------------------------------------------------------------------------- +The *xolox#session#save_special_windows()* function + +Implements support for buffers with content that was generated by other Vim +plug-ins. The first argument is expected to be a list, it will be extended with +the lines to be added to the session script. + +------------------------------------------------------------------------------- +The *xolox#session#auto_load()* function + +Automatically load the default or last used session when Vim starts. Normally +called by the |VimEnter| automatic command event. + +------------------------------------------------------------------------------- +The *xolox#session#is_empty()* function + +Check that the user has started Vim without editing any files. Used by +|xolox#session#auto_load()| to determine whether automatic session loading +should be performed. Currently checks the following conditions: + +1. That the current buffer is either empty (contains no lines and is not + modified) or showing vim-startify [15]. +2. That the buffer list either empty or persistent. + +------------------------------------------------------------------------------- +The *xolox#session#auto_save()* function + +Automatically save the current editing session when Vim is closed. Normally +called by the |VimLeavePre| automatic command event. + +------------------------------------------------------------------------------- +The *xolox#session#auto_save_periodic()* function + +Automatically saves the current editing session every few minutes. Normally +called by the |CursorHold| and |CursorHoldI| automatic command events. + +------------------------------------------------------------------------------- +The *xolox#session#auto_unlock()* function + +Automatically unlock all sessions when Vim quits. Normally called by the +|VimLeavePre| automatic command event. + +------------------------------------------------------------------------------- +The *xolox#session#prompt_for_name()* function + +Prompt the user to select one of the existing sessions. The first argument is +expected to be a string describing what will be done to the session once it's +been selected. Returns the name of the selected session as a string. If no +session is selected an empty string is returned. Here's an example of what the +prompt looks like: +> + :call xolox#session#prompt_for_name('trash') + + Please select the session to trash: + + 1. first-session + 2. second-session + 3. third-session + + Type number and or click with mouse (empty cancels): +< +If only a single session exists there's nothing to choose from so the name of +that session will be returned directly, without prompting the user. + +------------------------------------------------------------------------------- +The *xolox#session#name_to_path()* function + +Convert the name of a session (the first argument, expected to be a string) to +an absolute pathname. Any special characters in the session name will be +encoded using URL encoding. This means you're free to use whatever naming +conventions you like (regardless of special characters like slashes). Returns a +string. + +------------------------------------------------------------------------------- +The *xolox#session#path_to_name()* function + +Convert the absolute pathname of a session script (the first argument, expected +to be a string) to a session name. This function assumes the absolute pathname +refers to the configured session directory, but it does not check for it nor +does it require it (it simple takes the base name of the absolute pathname of +the session script and decodes it). Returns a string. + +------------------------------------------------------------------------------- +The *xolox#session#get_names()* function + +Get the names of all available sessions. This scans the directory configured +with |g:session_directory| for files that end with the suffix configured with +|g:session_extension|, takes the base name of each file and decodes any URL +encoded characters. Returns a list of strings. + +If the first argument is true (1) then the user defined function configured +with |g:session_name_suggestion_function| is called to find suggested session +names, which are prefixed to the list of available sessions, otherwise the +argument should be false (0). + +------------------------------------------------------------------------------- +The *xolox#session#complete_names()* function + +Completion function for user defined Vim commands. Used by commands like +|:OpenSession| and |:DeleteSession| (but not |:SaveSession|) to support user +friendly completion. + +------------------------------------------------------------------------------- +The *xolox#session#complete_names_with_suggestions()* function + +Completion function for the Vim command |:SaveSession|. + +------------------------------------------------------------------------------- +The *xolox#session#is_tab_scoped()* function + +Determine whether the current session is tab scoped or global. Returns 1 (true) +when the session is tab scoped, 0 (false) otherwise. + +------------------------------------------------------------------------------- +The *xolox#session#find_current_session()* function + +Find the name of the current tab scoped or global session. Returns a string. If +no session is active an empty string is returned. + +------------------------------------------------------------------------------- +The *xolox#session#get_label()* function + +Get a human readable label based on the scope (tab scoped or global) and name +of a session. The first argument is the name (a string) and the second argument +is a boolean indicating the scope of the session; 1 (true) means tab scoped and +0 (false) means global scope. Returns a string. + +------------------------------------------------------------------------------- +The *xolox#session#options_include()* function + +Check whether Vim's sessionoptions (see |'sessionoptions'|) option includes the +keyword given as the first argument (expected to be a string). Returns 1 (true) +when it does, 0 (false) otherwise. + +------------------------------------------------------------------------------- +The *xolox#session#include_tabs()* function + +Check whether Vim's sessionoptions (see |'sessionoptions'|) option includes the +'tabpages' keyword. Returns 1 (true) when it does, 0 (false) otherwise. + +------------------------------------------------------------------------------- +The *xolox#session#change_tab_options()* function + +Temporarily change Vim's sessionoptions (see |'sessionoptions'|) option so we +can save a tab scoped session. Saves a copy of the original value to be +restored later. + +------------------------------------------------------------------------------- +The *xolox#session#restore_tab_options()* function + +Restore the original value of Vim's sessionoptions (see |'sessionoptions'|) +option. + +------------------------------------------------------------------------------- +The *xolox#session#locking_enabled()* function + +Check whether session locking is enabled. Returns true (1) when locking is +enabled, false (0) otherwise. + +By default session locking is enabled but users can opt-out by setting +|g:session_lock_enabled| to false (0). + +------------------------------------------------------------------------------- + *example-function-for-session-name-suggestions* +Example function for session name suggestions ~ + +------------------------------------------------------------------------------- +The *xolox#session#suggestions#vcs_feature_branch()* function + +This function implements an example of a function that can be used with the +|g:session_name_suggestion_function| option. It finds the name of the current +git or Mercurial feature branch (if any) and suggests this name as the name for +the session that is being saved with :SaveSession. Returns a list with one +string on success and an empty list on failure. + +=============================================================================== + *session-troubleshooting* +Troubleshooting ~ + +------------------------------------------------------------------------------- + *session-using-multiple-platforms* +Using multiple platforms (multi boot, Cygwin, etc.) ~ + +Session scripts cannot be shared between platforms because they contain +absolute pathnames that most certainly won't match between e.g. Windows and +Linux or even Windows and Cygwin. The best you can do is keep separate session +scripts for different platforms (and I would certainly consider Cygwin a +separate platform altogether :-). For more information please refer to issue 85 +[16]. + +=============================================================================== + *session-contact* +Contact ~ + +If you have questions, bug reports, suggestions, etc. the author can be +contacted at peter@peterodding.com. The latest version is available at +http://peterodding.com/code/vim/session/ and http://github.com/xolox/vim- +session. If you like the script please vote for it on Vim Online [17]. + +=============================================================================== + *session-license* +License ~ + +This software is licensed under the MIT license [18]. © 2015 Peter Odding + and Ingo Karkat. + +Thanks go out to everyone who has helped to improve the vim-session plug-in +(whether through pull requests, bug reports or personal e-mails). + +=============================================================================== + *sample-session-script* +Sample session script ~ + +Here's an example session script generated by the vim-session plug-in while I +was editing the plug-in itself in Vim: +> + " ~/.vim/sessions/example.vim: Vim session script. + " Created by session.vim on 30 August 2010 at 05:26:28. + " Open this file in Vim and run :source % to restore your session. + + set guioptions=aegit + set guifont=Monaco\ 13 + if exists('g:syntax_on') != 1 | syntax on | endif + if exists('g:did_load_filetypes') != 1 | filetype on | endif + if exists('g:did_load_ftplugin') != 1 | filetype plugin on | endif + if exists('g:did_indent_on') != 1 | filetype indent on | endif + if !exists('g:colors_name') || g:colors_name != 'slate' | colorscheme slate | endif + call setqflist([]) + let SessionLoad = 1 + if &cp | set nocp | endif + let s:so_save = &so | let s:siso_save = &siso | set so=0 siso=0 + let v:this_session=expand(":p") + silent only + cd ~/Development/Vim/vim-session + if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == '' + let s:wipebuf = bufnr('%') + endif + set shortmess=aoO + badd +473 ~/Development/Vim/vim-session/autoload.vim + badd +1 ~/Development/Vim/vim-session/README.md + badd +1 ~/Development/Vim/vim-session/session.vim + badd +1 ~/Development/Vim/vim-session/TODO.md + set lines=43 columns=167 + edit ~/Development/Vim/vim-session/README.md + set splitbelow splitright + set nosplitbelow + set nosplitright + wincmd t + set winheight=1 winwidth=1 + argglobal + let s:l = 28 - ((27 * winheight(0) + 21) / 42) + if s:l < 1 | let s:l = 1 | endif + exe s:l + normal! zt + 28 + normal! 0 + tabedit ~/Development/Vim/vim-session/TODO.md + set splitbelow splitright + set nosplitbelow + set nosplitright + wincmd t + set winheight=1 winwidth=1 + argglobal + let s:l = 6 - ((5 * winheight(0) + 21) / 42) + if s:l < 1 | let s:l = 1 | endif + exe s:l + normal! zt + 6 + normal! 0 + tabedit ~/Development/Vim/vim-session/session.vim + set splitbelow splitright + set nosplitbelow + set nosplitright + wincmd t + set winheight=1 winwidth=1 + argglobal + let s:l = 17 - ((16 * winheight(0) + 21) / 42) + if s:l < 1 | let s:l = 1 | endif + exe s:l + normal! zt + 17 + normal! 014l + tabedit ~/Development/Vim/vim-session/autoload.vim + set splitbelow splitright + set nosplitbelow + set nosplitright + wincmd t + set winheight=1 winwidth=1 + argglobal + let s:l = 473 - ((41 * winheight(0) + 21) / 42) + if s:l < 1 | let s:l = 1 | endif + exe s:l + normal! zt + 473 + normal! 018l + tabnext 4 + if exists('s:wipebuf') + silent exe 'bwipe ' . s:wipebuf + endif + unlet! s:wipebuf + set winheight=1 winwidth=1 shortmess=filnxtToO + let s:sx = expand(":p:r")."x.vim" + if file_readable(s:sx) + exe "source " . fnameescape(s:sx) + endif + let &so = s:so_save | let &siso = s:siso_save + doautoall SessionLoadPost + unlet SessionLoad +< +=============================================================================== + *session-references* +References ~ + +[1] https://raw.githubusercontent.com/xolox/vim-session/master/screenshots/session-save-prompt.png +[2] https://raw.githubusercontent.com/xolox/vim-session/master/screenshots/session-restore-prompt.png +[3] http://peterodding.com/code/vim/session/#sample_session_script +[4] https://github.com/xolox/vim-session/blob/master/INSTALL.md +[5] http://peterodding.com/code/vim/reload/ +[6] https://github.com/xolox/vim-session/pull/81 +[7] http://www.vim.org/scripts/script.php?script_id=42 +[8] http://www.vim.org/scripts/script.php?script_id=2771 +[9] http://www.vim.org/scripts/script.php?script_id=1658 +[10] http://www.vim.org/scripts/script.php?script_id=69 +[11] http://www.vim.org/scripts/script.php?script_id=273 +[12] http://peterodding.com/code/vim/shell/ +[13] http://peterodding.com/code/vim/session +[14] http://peterodding.com/code/vim/shell +[15] https://github.com/mhinz/vim-startify/ +[16] https://github.com/xolox/vim-session/issues/85 +[17] http://www.vim.org/scripts/script.php?script_id=3150 +[18] http://en.wikipedia.org/wiki/MIT_License + +vim: ft=help diff --git a/sources_non_forked/vim-session-master/plugin/session.vim b/sources_non_forked/vim-session-master/plugin/session.vim new file mode 100755 index 00000000..d465ef91 --- /dev/null +++ b/sources_non_forked/vim-session-master/plugin/session.vim @@ -0,0 +1,205 @@ +" Vim script +" Author: Peter Odding +" Last Change: July 6, 2014 +" URL: http://peterodding.com/code/vim/session/ + +" Support for automatic update using the GLVS plug-in. +" GetLatestVimScripts: 3150 1 :AutoInstall: session.zip + +" Don't load the plug-in when &compatible is set or it was already loaded. +if &cp || exists('g:loaded_session') + finish +endif + +" Make sure vim-misc is installed. {{{1 + +try + " The point of this code is to do something completely innocent while making + " sure the vim-misc plug-in is installed. We specifically don't use Vim's + " exists() function because it doesn't load auto-load scripts that haven't + " already been loaded yet (last tested on Vim 7.3). + call type(g:xolox#misc#version) +catch + echomsg "Warning: The vim-session plug-in requires the vim-misc plug-in which seems not to be installed! For more information please review the installation instructions in the readme (also available on the homepage and on GitHub). The vim-session plug-in will now be disabled." + let g:loaded_session = 1 + finish +endtry + +" Configuration defaults. {{{1 + +" The name of the default session (without directory or filename extension). +if !exists('g:session_default_name') + let g:session_default_name = 'default' +endif + +" If you set this to 1 (true), every Vim instance without an explicit session +" loaded will overwrite the default session (the last Vim instance wins). +if !exists('g:session_default_overwrite') + let g:session_default_overwrite = 0 +endif + +" The file extension of session scripts. +if !exists('g:session_extension') + let g:session_extension = '.vim' +endif + +" When you start Vim without opening any files the plug-in will prompt you +" whether you want to load the default session. Other supported values for +" this option are 'yes' (to load the default session without prompting) and +" 'no' (don't prompt and don't load the default session). +if !exists('g:session_autoload') + let g:session_autoload = 'prompt' +endif + +" When you quit Vim the plug-in will prompt you whether you want to save your +" current session. Other supported values for this option are 'yes' (to save +" the session without prompting) and 'no' (don't prompt and don't save the +" session). +if !exists('g:session_autosave') + let g:session_autosave = 'prompt' +endif + +" Periodically save the active session automatically? Set this to the +" auto-save interval in minutes. The value zero disables the feature +" (this is the default). +if !exists('g:session_autosave_periodic') + let g:session_autosave_periodic = 0 +endif + +" Define the verbosity of messages. +if !exists('g:session_verbose_messages') + let g:session_verbose_messages = 1 +endif + +" The session plug-in can automatically open sessions in three ways: based on +" Vim's server name, by remembering the last used session or by opening the +" default session. Enable this option to use the second approach. +if !exists('g:session_default_to_last') + let g:session_default_to_last = 0 +endif + +" List with global variables and &options to persist between sessions. +if !exists('g:session_persist_globals') + let g:session_persist_globals = [] +endif + +" On UNIX the :RestartVim command will pass the following environment +" variables on to the new instance of Vim. +if !exists('g:session_restart_environment') + let g:session_restart_environment = ['TERM', 'VIM', 'VIMRUNTIME'] +endif + +" The default directory where session scripts are stored. +if !exists('g:session_directory') + if xolox#misc#os#is_win() + let g:session_directory = '~\vimfiles\sessions' + else + let g:session_directory = '~/.vim/sessions' + endif +endif + +" Define session command aliases of the form "Session" + Action in addition +" to the real command names which are of the form Action + "Session"? +if !exists('g:session_command_aliases') + let g:session_command_aliases = 0 +endif + +" Allow to turn off the menu. +if !exists('g:session_menu') + let g:session_menu = 1 +endif + +" Toggle the persistence of color schemes and the 'background' option. +if !exists('g:session_persist_colors') + let g:session_persist_colors = 1 +endif + +" Enable user defined session name completion suggestions for :SaveSession. +if !exists('g:session_name_suggestion_function') + let g:session_name_suggestion_function = 'xolox#session#suggestions#vcs_feature_branch' +endif + +" Make sure the sessions directory exists and is writable. {{{1 + +let s:directory = fnamemodify(g:session_directory, ':p') +if !isdirectory(s:directory) + call mkdir(s:directory, 'p') +endif +if filewritable(s:directory) != 2 + let s:msg = "session.vim %s: The sessions directory %s isn't writable!" + call xolox#misc#msg#warn(s:msg, g:xolox#session#version, string(s:directory)) + unlet s:msg + finish +endif +unlet s:directory + +" Menu items to make the plug-in more accessible. {{{1 + +if g:session_menu + amenu 400.10 &Sessions.&Open\ session\.\.\.:OpenSession :OpenSession + amenu 400.20 &Sessions.&Save\ session\.\.\.:SaveSession :SaveSession + amenu 400.30 &Sessions.&Close\ session\.\.\.:CloseSession :CloseSession + amenu 400.40 &Sessions.&Delete\ session\.\.\.:DeleteSession :DeleteSession + amenu 400.50 &Sessions.&View\ session\.\.\.:ViewSession :ViewSession + amenu 400.60 &Sessions.-Sep1- : + amenu 400.70 &Sessions.Open\ tab\ session\.\.\.:OpenTabSession :OpenTabSession + amenu 400.80 &Sessions.&Append\ tab\ session\.\.\.:AppendTabSession :AppendTabSession + amenu 400.90 &Sessions.Save\ tab\ session\.\.\.:SaveTabSession :SaveTabSession + amenu 400.100 &Sessions.Close\ tab\ session\.\.\.:CloseTabSession :CloseTabSession + amenu 400.110 &Sessions.-Sep2- : + amenu 400.120 &Sessions.&Restart\ Vim\.\.\.:RestartVim :RestartVim +endif + +" Automatic commands for automatic session management. {{{1 + +augroup PluginSession + autocmd! + au VimEnter * nested call xolox#session#auto_load() + au VimLeavePre * call xolox#session#auto_save() + au VimLeavePre * call xolox#session#auto_unlock() +augroup END + +call xolox#misc#cursorhold#register({'function': 'xolox#session#auto_save_periodic', 'interval': 60}) + +" Plug-in commands (user defined commands). {{{1 + +" Define commands that enable users to manage multiple named, heavy-weight +" sessions (used to persist/restore a complete Vim editing session including +" one or more tab pages). +command! -bar -bang -nargs=? -complete=customlist,xolox#session#complete_names OpenSession call xolox#session#open_cmd(, , 'OpenSession') +command! -bar -nargs=? -complete=customlist,xolox#session#complete_names ViewSession call xolox#session#view_cmd() +command! -bar -bang -nargs=? -complete=customlist,xolox#session#complete_names_with_suggestions SaveSession call xolox#session#save_cmd(, , 'SaveSession') +command! -bar -bang -nargs=? -complete=customlist,xolox#session#complete_names DeleteSession call xolox#session#delete_cmd(, ) +command! -bar -bang CloseSession call xolox#session#close_cmd(, 0, 1, 'CloseSession') + +" Define commands that enable users to manage multiple named, light-weight +" sessions (used to persist/restore the window layout of a single tab page). +command! -bar -bang -nargs=? -complete=customlist,xolox#session#complete_names OpenTabSession call xolox#session#open_tab_cmd(, , 'OpenTabSession') +command! -bar -bang -nargs=? -complete=customlist,xolox#session#complete_names SaveTabSession call xolox#session#save_tab_cmd(, , 'SaveTabSession') +command! -bar -bang -range=-1 -nargs=? -complete=customlist,xolox#session#complete_names AppendTabSession call xolox#session#append_tab_cmd(, , , 'AppendTabSession') +command! -bar -bang CloseTabSession call xolox#session#close_tab_cmd(, 'CloseTabSession') + +" Define a command to restart Vim editing sessions. +command! -bang -nargs=* -complete=command RestartVim call xolox#session#restart_cmd(, ) + +" Plug-in command aliases. {{{2 + +if g:session_command_aliases + " Define command aliases of the form "Session" + Action in addition to + " the real command names which are of the form Action + "Session" (above). + command! -bar -bang -nargs=? -complete=customlist,xolox#session#complete_names SessionOpen call xolox#session#open_cmd(, , 'SessionOpen') + command! -bar -nargs=? -complete=customlist,xolox#session#complete_names SessionView call xolox#session#view_cmd() + command! -bar -bang -nargs=? -complete=customlist,xolox#session#complete_names SessionSave call xolox#session#save_cmd(, , 'SessionSave') + command! -bar -bang -nargs=? -complete=customlist,xolox#session#complete_names SessionDelete call xolox#session#delete_cmd(, ) + command! -bar -bang SessionClose call xolox#session#close_cmd(, 0, 1, 'SessionClose') + command! -bar -bang -nargs=? -complete=customlist,xolox#session#complete_names SessionTabOpen call xolox#session#open_tab_cmd(, , 'SessionTabOpen') + command! -bar -bang -nargs=? -complete=customlist,xolox#session#complete_names SessionTabSave call xolox#session#save_tab_cmd(, , 'SessionTabSave') + command! -bar -bang -range=-1 -nargs=? -complete=customlist,xolox#session#complete_names SessionTabAppend call xolox#session#append_tab_cmd(, , , 'SessionTabAppend') + command! -bar -bang SessionTabClose call xolox#session#close_tab_cmd(, 'SessionTabClose') +endif + +" Don't reload the plug-in once it has loaded successfully. {{{1 + +let g:loaded_session = 1 + +" vim: ts=2 sw=2 et diff --git a/sources_non_forked/vim-session-master/screenshots/session-restore-prompt.png b/sources_non_forked/vim-session-master/screenshots/session-restore-prompt.png new file mode 100755 index 0000000000000000000000000000000000000000..2e52ea376de25166c93779e45191953ce19b07b5 GIT binary patch literal 22330 zcmb@ubyOT((=Qr=ySs%1cXtgQ+#$HTyAw3HyF+kycXwxScZb3CPM-IC>wNOwd(R(d z&FY@sy{&pzb#?Wxsyb9&RvZxy5AM^aPl%EdB8s0rfz^YKr(vK#dt35^PS78iqoVlt zPnDAd$Djg~ft0w&r;oqCoQ|S+&>2`e2@S_jpWxB|ZeX9%GH^gAp`9dUM4>mqkx?K& zDbRC)dVcvNDI%oowsMx~>ZPo*GSu}TD|s17O8Se{Bk?O7TqR{2rHj#mvl_tLS;bAw z)p?=ed<9Eei1xG*#>S-5wQOeyAry#h3{m(96)!KZtLy8YsVQV# zUEK(*@SwCbJPS)pDz1bA@YkKvO{YEp)w-KXwAUT%cP=vg0Eh2&RT7uzT1OPLuy4|h zJyaQlZxG(sD+QOwjnvf;gVgNlh#`Hy;xaR3oSoUoLTYc}3uTkv$zlAzWUzYypTyO@ z^Aoze1rsVXn-rbCC}m%jo%S>Pe}U;WA8MlEA3VV?z&SlR$(YQp3{?S<88{bra$=F7 z5`J)csO!<7E{p;p#A*HXK1PPqc9N-rd8nk65U!IEo?nR-P(}Phgy22a9zyIEjRqbx zCIv)tj`M51q-YP51(Fe(O$o`M0F0qL&fu`ySrXpaKIHuVImOfv@yDJ%g!oW+0VHTX zbP_W{;Pj8E3*qIq#Qth^3}WBgR*TymUaLlK#wP>T7c>k4$uDqEJe>uc=LEf;MZX*V zb|b=Ko$y4i$fLwIp29N7N6Wdz`FYJGkC;=82smmDuH=&M+YOC8liA3cNJ#gFjfy}I z|A)d&;W_8b6~fJU6apx&wrMzIt^sM4bQru=sI*{Jh2M(WvdYS6Ts#~ooZHkGqBgad zpf&N3o^A(Dm%=%~hzirublbDyD}(Plt5RFgk&1}=<@r@QmN#Pv#Q(DM)xFJM#u@Jn zED`(LIzkqu?4L;i!gU8{Wb;OY_K&93nnEg66_xw(ks4ZT9w@M}xqC^<)keEWg;99Y zDH>oheX(7{U4KZF56(oRRLaB!VgA$oskdEZy!&sL|U@Ov2s2N6UvhK3X-AQKRND)Z04n~n%b~< za7)&cd@L9@(Fa$%l?3Dw{2`I6%%Qk3f?mG`asn#zaio_{EvDbTaXU|?e*txNDhmnr z{nC&KnG(rwhIPpD1z39Wcy_4eDCI|Vt~q;A z$N|1Y5Z5P1k@B-#*uS#4DGZD}meJWD@%Q#;d<@A^NkTg@Bp?47)=|3VuHX*K1jgM}K z8$T4*5BaE}TQXK^ENwRb|25&NFgVQbup#}D-QPVTdp*{V`@|wm8q%CFB5wAp%S;CnuWW5t2Xf!LX9HN3U*+@ktLv zU7i};{hyw|VDVjSyltoPexAQH%3>l{5N*cTc?AfUAcf|TnxibX;t?Q0Lj{1IR$!2R3tLXSY(_q(6hDG}Os*}F!$5yFC4}#mp@5;zzbRYL_wYwG{riy^j6(kj8svD(nu4%DPRO z2e9Y$q)FvsJJN1BP@eqIpfZEBdiH|cBrd&Qq4${Z>2y05dOs{oZ{8kEZ#LX8p>DNM zuJG?jXOGv`6FMDvw$RZz<=<#|z%uEKm9h5RTzzew%bY9b6+152xE*!yaeMdCSy4TI z4)B+Avz-mj8XHh5V&tBL7A@af1Vg&H&fp@*x+j<-eQeqoZvRU{*H$FS^2dzU#%k7Z z1B-9pmV9-ZCwfjs;a$NaDlWFTR)RqAeP`2?a}m$F4iU|eYS(0!z{HlFBwZR+h7Y=_ z-4Nm-sv*A&q|BW2J@$NDqS8cT#*dp(TIEG{Z9$lO7F2u-6A=RxVYJT@p*P}OxTCo| z#Z+a%k2Fs}x`3;O1;wUt&EFF&DzxU)xG;Osym6cR@7ia6__ z3jG`7QrJ?x8$Z0NX`F5mS^{eljqMwuk|MbL?N6jipL9U7)s}n#(t*Te%M;1FtD;k% zs}r?t=EPK}74|Wk_2G;+k?F+#3-ZQJUzMwp6&qU8Jhm`d%G&v6W#sw1My}WS=F|Gm z!~Gh-q{+Ps6GmmmoXg8i!bielThY+{LC-tUnB~}Z{tMCGY3zsI#l#5W=k*=WkYv`5 z$@KRf%5SH@2lcA~awHWqy(@}ZS6}*8Z*n#A7L7HfwsWg=+e_by#8pE9v#xQH0EYeK zJL3~?+`eR6Q(t>FBw2JJnyQ-X1CF6bb6+Z9PjS0_F7GQg+>*+<;>x*Ux*Ef}RY6y0 zYtbPiJlBnLoS8z%!@!lvAjOw6X_ZMZa3#K&FL4utpL;P{+oxQW|D=W^FANa>~w#9N2q0EwRjxkPZe?A z8bK+FHh-F0qWCU7(~~H?B=P33`{b4hif50|D-GzDdVJuOt)_A>;v_y7@2ZO-d0d`K zA~Nm>*fDoK&9U}^JB8II0T1$$-B_%N9wL#%W-K^c4Ur2vstgy6M;|vO#TF7W<7OOIx>P1S>EHl^~l)f>n)IT78MlD~+qX^cU zwj6%%qDXns#+dW@;1CN^i)-0)-bm-m)^WTvup2QQ_cUdRRh!zWiQP6Ucv2o@#T=L2 zuZVxbMJ>)~c9~HnN-zJRT=P~z@$}&Oo*}SnGf06$HL5eT(`N(TUc}r|i^h2o{dyNB zBJIaTiU$t$eZ^8Y^DOGTkweZMvG`tVW73PkujqZp)_7A~?q=K+OHAiYKnuWtQK1KJ z+x5iPCS|onZq}ILvSN+B;?;KCs9tkZNbE-G*wfK>p+rIq3fW+syH)-?=^% z?b@tUhVe{gv;oGODlv?^s5V{W#sOeG1h3rjR<54)YK35x{AdJH-@kv4zr23P^L9?S zUr8@&N0PhJ(y8hKEIvD1-zDeTr_w$%XBUrU8!fVVGlKt=M3s8#EMQk{TDRd#tm$Ci z)M=%&TK>hpbbvFn30)o6bT9gT9UE!x+ZG*e*h(+XM{UL)GDuT~9G9vzzz{;AuN-;C zuNt{fnNLk!nwLWZ2L~4x<=8TF-W*eTdUV(2oEe6fS!+RK693&on$kPZ-|h7Dn-LNH z?xgPRKu*@5eB4T2O?a1hLuBLInBu|IV5(peaDR=AYnGr!CWy8>RW>WiuA`!xl_nml zHoMQiT2jxN23VZ+7}Ge+oxg-z9O(_-HQpQ-=Bta}8%z~`N2_Yb1BTfS4>!eHjejj; z^>>^M?fo6OD?qoiUVy)psrDoDBzgp{(8)8sXjnQ|GO#8rF0GQ#uF-iq*t$@uIYg^1 zvsTU2VYh4o&pQ+n=&saa&~1XnYtQg9nLVCBh0Vgw)x3_ht+J6Yxi3CcrBCnrbyYOo zm~KU?lV~*MJ=S`q-!XMXx})#BY;6BJMy)LS@W$m-WT~QS39fde29m|VC_|j-LDIZ! z-KAinDcQ#LF5tj0Q1z9ss>9W9`+;{1lgek^p}KPDWYS>H%}9Y=HKZ40RF2R!$}6gb zmr@poh0Pr*%HN7zj<1b) zKJMQL)uS0dh{60C-^X)7PeX#x;f6A(wiu_to-`jpJ8C#-svd|+-2rSzfa5$%!)7BK zxvJ@S)H{zRpduU%&R`sTb)f~r9aE22>4w-9yAht+UQ=gj%n;>$*@2svY+^iZ#P~j9 zeAlk_SkiHe2&Js1or!kD&FvHMzAG$!X=!7?l3o1;!;v!i|o0`+hdykr3ja))^4t_xC5yLC)L3bZg0uIQr8fM5RkJ2-3t-ke z0Ni^Xhb5HfgExRR`vO1CvtKy9%>dcB0clb)lKe%T467};lrpE}C@eT^b}Q4|1wJY5 z$KO|VRrs`na>WI`em!PG=9gV`9DfVOw)O@wIhi>&>JtJZ;tC_Z@1&ad`!_qId~3im zAHHvTi6P4kET054=?dIEm)mVH(;bCz1WsKh;W=`SzBRizutxjxh5)2lQd0gnn!SC- zIvirWi|&K9FviP!eAum(MCGmDb9Oja(6YCQn45#Y`AVmRkU!X8ZS>@|p{_FoIU;oQ z1ihNkkMEf|26-*@XeLR8s#NuD(n^GoEvq<)_=XErx?{az3N`)*scyBwG57b$OX2FD z2%{v-4!imyuv4Q6E>}mQ$4wee@?i|9E_{&AOR;-6%(2rvEu%dj(Ud zi`HkDJ#G@ko;ebb&jfgt*3pI@ollD2F7b9B?K+Wb7QnFm_%&`=6A=bn+u%J|2*2@I zpL}tdE`z}zsh@ct*XE3FngB4->yY@K0tg_VIb5;eR&AQJ&4K3yt9jNC&f>%iB}>oL z$deN$-F$NPfZ;7A#}WI9doO0>WQU#@{P-Yia;rL(+W-<-&i zj84Vc201LgboM_njuhzDUECG6rOT7sPcFMOK}!C zf^A)iOx`BF$dOJKyn_@G9z!052aDRT#)~FpagzkQ^wsRA_>^!|d<`3Rq@E)}TBcn2 ziD}b^=GeA~1>!6(x)Ny=S6iP}M0&~QBy_K_Jkg4nI+IKE8~3>ASR~ap#|RgyfZIE2 zk0VGp;J?pUQWEqU8mLfr86>y!pY}5Z_&2C@6!KG39!V~F=nWKY51E6wj(=RVv_t@s zJNnMpChu$<^;nNGu4w@t0YMSDGnlFtV+3{dtKEHA z&TpHvF`T{KuO2u0O8)AFR{e>6ilGUd+}~gpca^8RrGB?W+8Q=(=zgE%W6*4HsyQLD zs^VZ>#Sq6uDh>O5BL1y|va0F4-Bx@kSx;>J9i^%L1!)X>a=VNhJyw#5l2TT@8&SON zyb)-+~2V@LEl z?TjccO4Ri30D~TUf9+ORUwK-->Jj6rdftnH2Tw_d6mfJU0+9-Pqq1CmigLN;P9)?* zE(=fV>2^9*H`4X4%gab2oh42#(Z)Gevrl{Q4!y{9d+FFrwm=JY?Y}@HaH)fQ-oW-E z5r!l>mz$GUsnDN+wuiydZAP_!t;z6(gu7qE-6gWh1tZSA*njjVPc9g_7yve|iT-j`8ohJ(5n!p)m1KNkzFAG`v>x zM8k&^)qJ=`u9}mqQ<=B=SNi3hYVq*52#tSwf7=IZB&ILgP#L2uGX~Vab#7|+>lPMl zTe?&Z{UH;v8(4ziU)I^@-B|r%5xKFlooAtF(ECVj$iOmrDqJPsrQ`&cG?b=Bd^o3- zIDH%5vin|kOk=GU<6?iGyAbyQjP`o&(+{&G%z;AV*fY53bo6KOsqb+*o&W(d?|khOHvRo3b2 zxV#V)4+%DWlM$sOna%EvQ-m6VwtFFaD@X!io|AT}Rj=)ys>}pwlh~S3DCk7v*R?-c z0k9$y&R-SgSXs3#Ia7~(&^S1|L#74ePoI+npdF;rz0~ad}{dIO#e zPW4%3KKp?nnG8gy@SO7zy1q?7U|#XO`q>ep|6E%2vDJp|VsoznpnApmu*10GRfLU) zT18!Fm9)a6rd(jO>J)FmnO!*mj5t2l`)OZs3zh(;erlG9^I0e1ks}h%@7W5RQ3*M&%OAgEpgKKJ zgdZg=sKX+{>5aXAp56UkPzbtqk!jv|`y3bnU4c@I3bWRYTjhMD*1R?%`+eRo1~to1 zR$~gu^IYc7OEiK2Nu&jwv{^R+4avlysYU`}M}CGunQ=3F&OfD#!O>Nz*3e;(cY#hN z<{(^@CBsI;VVsI`2mlbNSeS80t=V?o{Z^JC71X+_lNu%LNJrf2Q?4Sq=00!~d|BME z;_k9cUrKkMWZrP&4N{dpCg|dDMk5L!V2qcQfvT*sueenG90|ambo#5W^}@ry^Md=h zSU8{vDopc?#g%{^es1bi*dW5Oqmu`4)I_DB{6vDv zf&?81I{uyG9ppYZGzZVE^_f_Y;Q7 z{PlbsApv!Hp3Vf`g`K6_y2F#goU?qlL7mip45sse;Z;=1$;X&XQOJ2&=yG0kjOZUC zWry+bJB$AEtkGOpK_%#Q_9xL3V?b|MD^!g|bM3}A%i54dN*hYf=rhZ-`C1T^2a}c@ zii1(^(k3NR4>cuSbj)n{Ml}RQ;s_h_;vVy;hqF+{ft4N*BCz&DNJBgRWibsdeZ%Mp zwaHjqMWMKEnF$Z0#2AD-qOxAXTtDPCPKLoPId=?fq&lY7*k6u&6Hk;FN5+;i;KhCF zzL5zTVW=38sVsIqJ7KUV>7$<9__fw)w^i9(ZWkr%XhfmW;vAm}C zz}24Fe_RYF1zl9yC|m?o!LheKok+!XgRtc}R|Fov2}^@2GOe)auupRu=Tb!(ol264#EjPM)pQnqBD(vnm4r>+=EYD??MxyUe}!oZ}i zP1SnT360;nVqdYFfRFQqodevc`nw@}L8Bfs zIou;+M{fb@k`=8iAN^G!Dz29!TPt@hS@p`w3Jc34R*Q6^HtdKqKm^+r&h3+lYXfRl z&zG#&KYLHCalCz|hL6%yW;>kC?~5v2w&y&X1R(Jsh2(ELzfJA$La|D6OizW39R6u+ zo_woAQd>#ui^}6+q(q{QI=t$RfPGAjRIgAybMfqx0hmJmgly|{%MQYaiz!lvTaW7a zO}yd#%eQLe)Z@h=A@*q*ns!+=I3N01=sp?#=`p0Y5xAUb%!T__Rd#Or9{;~)6P;!5zt3s39xL{$>?ncch7{}Ne+r>n0u+V!F%DAm?TX?4GTY~*=|W%07YiYHr} zO3L&_w<)P6{Qh*Z^~{Peh_ynDgI_?r>Bt|_4lI=whLL)ClT5z;tRG1Vj)A9)NQ8Crgf>v^B>T*rX z&jy~2F}(t(uu%;~Py#RdF{b9bcn6fJ@|P|};L|9^$-hN!vWBYhKgANe5`RYw8#KEg z0I7Pu76tR0KX2r&>KrPyvR3tWtCfiI5S*G2NMSgZj*O)uVyPq#h4m?+wKq zAIH-`4mxBuRwNNlnAE(rhr#K zw9nE+EE+sY_m%+fgf2z598h<=jy*d6KVkuP>7coE^uZAV@6!8?4I|DTJ-{`@sjFZ5 z8P9H3n}K0q5G8&^9yf(n=LZWstMz8keQS{iqMCMPKi1R69*ElqLUb<+mn=wWOBjNG zFtRPNheTg^##D*F2efcd7%p0JH9uSH=+^!cPUKGc#&viQ^0+BEgVSL(w2ymvvm^)2 zrFGCvz!ej2vNjrF-@(|lFyz_#;anUsA=VeQG9`uY>~;oH19wlJw2ubpA=IplkLb&7 z0@&;P@ig($ba7T~NGrAi#O*FGq3Eox$Py|GuHx2VRLyW@;hdn$YMix@P=yrAZ>Kk>+6 zq25x4kjwG{sTi(cnUSt4Nnry1v2~^4)XPTVW?Kgw{0qNNm??i9i^((bld}a%M)AB}pvsEZ|G^UKo|XANebBrSFZ?JW~{4o`~(f{_&&NznN_0q^Su0@Ih1X!nni z0A+zEh`E*h`Xm7YM%fe!(|~;_Ei zL##)?O1N&(psLJZb{fOSafA%wAG@^yXiCrS0Do8mm+$w!V z>xnR7&Bv3@VIPY!5qDgYCt%0$BotH8zZqsN%;fleRQ*LcS;i3^~+-z)OY+0T*R_CnB4wzJV`i749L% zvPtRwMB2uyK|?fAefm0|rGPPr3{4D?j18%K@H!jo`eGLGY?7ux_HM`sQmJ+QR4LM8 zN#18hZok3SRncV|;mvTeBONw;1-eL|N?I))L*Z=s*y=@I#HZm02&H(}Hm9{G`! z(L(Qw?%A45tTm}g^xdv^6Z{1x%%THzIrk&A9t=4*%DwV@t8Acig;k^MUW0Jsbsk-@ zjOxvOTvZ5jq3<6+K$P65awSf6Dx}=nSSOHz#dvfeLI%mjyA%C<31_7HRuIehykKcj zaavaT<5U8-&7>=8WjMWNtm#WSfhOZOvB8E8t5ushTUF@u`t11HkU~m0vHTfavY*ad zc9g}XU;#ZdcD>ak5D|r_*w#By=IG7VC!F_$bfk_SOfCfDyAncF`W(V3d{ju9 zC=YZ>v2m#BdK+p@)0-8cRW~bm8E80DjF%`<8`-U!u8#5I@w;;Mcd9Dh8`x~!C(3A@ zbpLI$!@facQhFK}=%mE%!HfI9R>V>Y@s;W;$ixU^}~6(=Aoen;1!clE)G;lx12`z4=88o3FY>#GaPLr3Q)_!wn@ z+)$9aU>DEjg0es9! z7SL%2HFT^aa>@cbk(R?NNg-@>BQMJxJ5py?RIffukQon?y6y%GKknt)!v9Pz4LKxK z@RTu9+_~QM6&iD)zEyoQCfJ)}dvRY6J{h|d-DDFZMITTDxestWEvlm6C4k&lwSSd> zWoMIW7lwu}(7EIH0`Z;ehq=u73VOrA&Z1#fO2}LNFl^Ix`sL+eq;@1e{Eumv%1nZZ zUE-;2wmAfH@?(OZU48>kOww<=cK#UM7@}Qn-z*my42)06NRI~+LZS@5ufSBM;S92j zWgkM`;rTEz!YNsk3{iVJ_WV&^n_{d_71KqI-$+sZ`s9x(1weK1A@*M|hyu99+SDoi z3iB19PsivHmeQdB5Dj1+4s!DNsqIJW&!^xd(PmHKkDWGu;ez4&&?|e7MB|PtqX-7h z=PkDvYY+AN=;M@06-VLsQOX$~LlmSZ)w0^~9>;QvcfI@;b=TK&Iz{ovkpIp%FXu}C z*{Q}#d(u+#{L6B-oiF9aJ9z4l0WRhxz(vz;O77o7|2)9Z-v914fS}x1EjlCK_#DP6b-Lh(3U{z~+P4wcA;qN{F)yl)uu697P zTIFLL|E~T8Fmnoe?BLo7@o^}6FYN{NR-jA_u!hTx=)A)sANR}-Vz2@?8?rnEzEU7DLd0@jkPm95{P4>i`MuzQmjyxhUx0Wv?|%XDL^oJV<*}&} z%|>{~G#dtTJFJ5b%|?^>3*yDs1aug3+qR5VVH!%L=L!yrR;P5CF<0$&|?^uAJ(XV!Fp z|Mcz+$UpleK(9U0R=|GPX*f%1li?02X(G?NERLA-u;uifgKj&>G-DGpi8&abxHDGw z-noT;@CeKJ`1lt9qv$lI}w4Z|N{0At7sidQTsTjptCM*Uc6Aar(0lMBOMIk8FzTg z$1i7uw-*8%Nw)0z`#O*P!(kwOU{tOqC3lK2Cfk|DHTmYF?x>-m@u&F4FV@><-9Ii| zEtg8}^VHnFSlpqq)4xRQZpU*9^mxs#M#H2{_Z+JeS?YLa$T_NfpJOB*rbt3?`k)8OllyTils0@C9Wi-yy-dB`i)O&UNC={$2(m)siqE$4 zcyh~k;<&^wXQHdnL_oLw_RELkoXnctuFM*fEeqxb?^=#~bx#%&|5ALTP1ZxaLX~NI zR$`6u_6zN1087kOiTou+_+-K{f;Goivm!J;+?>lm2&?+qkNlSQCcX$N7UG?2apIi| z^J6+2G`?MH@4=_{NYN zDZ|rnxz8QjnA9D<-tj6l(s*~qfq201#_fjwma2|D+bJ^5&8g^#kZ{QKNR$aPeJF!6 zhy=BI>Lw`Pj_gsqT2lA@X{8I;)-WkBpu>~CtTteH%Y0=1vM{ZK*I?Aa8E$&7-9Pv7 z%;r5Vc#d?iekT_-<@Sq$KD6IY_L$>i>w-gi+-sXW>UB4lsDVwp1W*Z;MnJgboU@FM zR?pT^c(+xA{*C*BitEQx?Zp@VzDn}-t`;_nVK061I%MrpmMIz6pu<_ppFqmG4dm?& zE`a0KCEaOIBsi=}15p!OW(8oW z5;|?3rX8mK1dHlj1k&0X^|c!5m*(MAGj+fW5nkS$mGtjm5@u6NVVn2`47 z)ddjB#)n2JulKRaGwe~*WC+)(DOlI5kMx*xk)Lt_Us+kH*2j-UUx8P}Us`nA;z;uR z;89H?n6g?yPB@gg>X?K)vNUd47I5BhM`!~E+xG1!w*uea$0Jef|0tSf_*$uV zvBC!sTHB&2Bx^Li*w|3|`*I^?0)O)$_a1LNsH;6fN^D4>eMhAerY+I4u-~8_yY@Pr z;5B4jBFqdGUQX zb~e{)7}jvyb_gw|CW1`^Qkv0*RN$6iGLkKuyV2&ZP1b)x4n#Y9HNj&9S%}#6bXl^& z#vK{_#s`IO7V;y)UXvUbh5x;Oq?hA-HY!Ka)~2jRu+}{BoxtfZHKFYAGp&_52Q#nq zK>9cDEdQ#;j)-X&#uf5<^m(N__Q*-)8qew#77VV&OBr!T$kDdf6-fjsnXe_bKjH=5 zC$~KJL7VkNcSmz!->$0&vqA!Qz`48CL?*n%5rT*MDS`(Mv7A?*96{{+#>G+%-KA3zH5NTo4I<#e%j%9pdx@GCAad)n@1#bMdq5DcLs zKkNZfqqC;*F>HF1LKR_ci&RX;FRX{Z7NnI6eEpHi&r%jM%VUt~m`T9oJ?lFJl#`?2 z<4oW`)R_tZ>KqmvX6^2)5%0~aqw5_$%5B=y>XD)=y{=#aVse#mY*xlfZ95Ogq@e=} zBfhkUi1U~-t}vT2{)~Q`!JG$f`(6+4=^<789PzP)o;%8UI3+4?)C5lm%gNN?1m7pr z8<=%Ay5Q>W2?$At7%fBYbbXCq9@l8jqT_LiO{}St{73)W?YH=!6Ka4$8`Nx#4=b(9 zHMbEO0bzNw3>y;H&!XjP38DvscV2Zxqq|lW{PITIpa_iZ{5z}Vn)vhdMc{ziOYyzK zRw=Sa+RHV8&Wjg1kBik_9U#lp-UlIB=M?UFnRH2y&ZF+ZEgnkm%$Xj$Kl$b@PI^3l z2-TDwjm?5rLA-Md_>Cl@?MtqbR4`$!GqBdliF_UP?}~1$l#M*Jex@VRxZxg)5@p)J zG@B`Vc7(KUu*w2ikG^`VQG`}g+((&?fc|j1v6K^W5iQzn{>rZ9DBy0BJ4BWv300>J zFt|2y{AJfR_31eZ>V@(bc#4C~7ifN;XoOwLLZpkQg}`UMdiQV>;LeWia;+hBs(^Q2 za7HV+b+=A)Xrd)YjpHWR{pF+u+Wg!qYkRKKoMKYtQ>ZnrK<%r*R2?Nl1bijVEa|Wv z(8bVpAgOlGtq>G&kdyLPwTbxgPw^Fl_uO;i$4o2bNZ4ku+WPx6!my{zUT+0_8pIjY zjq4Q$j&b>VwJWvfiLo$U3vak;_5az(Tmw7(U6G!=Prixdqb3N_$%R9nrd5R}ZU+91 zE-uFcw&0sY$U7MVq;qR|+}twaUb>15Z;(u<$vY{JW2#XP4}p0N=n?EaP1_=-FG75) zlKE=T6#D0&2TR9#2L5^)ogDF=`HLyeI+~Rnr>C{|DAY;4z1y}o@8jJUBJXYF+lSbD zfNUQxO~Aqrzp1$_8-zxRjE+Wr!q3h>9iM!JQG4>~|5W`>ody{mMJ(&M{~84k;-sGF zC5bpp7>6YndA2^NF@{Y1Z~j8P_-8M;zjg}3zfuwYO~S$d?M#KgUQoL*eTJP7SKX~m z%bV(Owm(sA{`nE(Q~Y`(jm!iF&O#6}oZDuYXY2K;XP@EIH~^>r;bwV0*0TBENeJi1 zF`Jc39r?~{=0Y@jbB8pK@AA%om0)8Eh7Aw&2U_m1ing0YbaS|`X1(T7cVCF7Qu{uP z6S6nz>;|HTn>ly#UYUNc%P}FOfZiyXax!Mk;Y?Y?n10!f>V=t}=w=y|s_$TAJVT+N z>J@%r&Uqon=Zh@_Wou+;)z?P0-)_;I;ky%mv|BTRRcIUid(VJb$~uvz8!-oiQzy|? z5x~vJsV;%Q*vR{x2)=WvKNk)W;a%kZVoJ1W%IN2CqltU*{?e0!ICx6ah}&bFQowUaW6= z0-gRL7usUkA-X%0doE`eRGSqhLvyCQd)U(zEnXiznqH50HenTFy>ZV5#Slu#;$ia7 z<9-$m_2lkssdR5TN zSS}Cbo0(K)MXx6+R=%f_?{Ap`hf~ez*RWz?wSbyOI}VsMwEiOjzR{y#jTGp%7fs&e zBKI_qS&=SztQ?HZn0ZOox^{@ zxn+r^Y9_TuV_tdmzHu6W+a3fnGEv(77geBM34LMMCou#(X%Ah2gib1*L(`m+^C^q- zKda1BAOu)j@C<~+8d~s@>q&g5(?S#P%?+e#xqRUGYXhGD8!kJ9%%vK9_h4?DFeqRT zVThJ_`CstgrDGBgA;-2;%#Fh~VPln*sj8Cy9G0D!{jad>Gu0dG^%txlPj2||tryj2FEeYfDk(SQ%F%B>q2{MMW_!Ler zKIfRh$$X7aNtk!zF4f1`t3!y|SuI#I`a2k1v_1^MTMHsT=1)$D0MbixqhTT$wQXa0`cvW6bPX6h} zNR0tfk*lKHgYmRf8$9TKTK;`NAR!ZL-cN1G<)lnv;pHWTJZAAPWR3mOocTXNQVf^W zI@e?_j~G4zXP+lM536`x<3W<_dx8z!3ip9j4@2?Xwg%o1}mg|9>CYA^FgIiVjz)ZDCBj*Kwp!6D$)Oz z%D$4_0)Kej_{2RpK(lB2mXQSyz*U$Fa1BA>tEc!t_0GZo~9E z$oiuyh#V?%Yh`4H_Z?&zu}tV0#7*Yj!K-Hw_st6+Q51)JG9LU7+^jizlqmuay)SMb z=x*pvh)oKedr17JRzc`zlV=+ClTASspZDMaN!O2mi)yWhYB=!5I#YlW^@?svzj7nu zbNu(9M?7Jl7aU(C_vC2689YL_b4byG-)oz^0m}Bz@ zDP${xgoJ+^8Ce`Q`xQB=7W}o@iR?0I<_7&jsf;+)l*7^1IfA>3L87={_jN5l^P=*VoyudvbVx2g>yf)}716X-~zY740 z5I1%^^FPU<$OuY*1v<^$iqfEd^w%ghQo1J?>#li|M zEu{?m+Uo+BXO34;P;j zhzTZ9Gr!@;we&w=ZLVzTA3M)(y?9NJiprxof(y)Nrlj}JZhDgtF>q+}cX=E}ot>S9 zg@Ng|XvjO|E-lSF^+4Az^VR)mdG3PEyi`Nv8=8p9dM83b5&ZcR4;qQ!3-4Dg5VN?K zfW?&br0uSF9+Ih!5DN)nY;$0u(8?Iv!fIy76Q;v=S~ z<*8|CR;x5Ya$x4oyFh@XtSvsr3Mi~UC2rj)wrpLjMmT2>oe!i79Hn zjR*)&FEr20q7BP|HNCSdJ;ej%z-!y8KPa+3^h6bI1XvzR9bB!mZLzs_V_+P9%^yQu z6q=FO$}6OXGea`%aF1b?nOngq^@x@cIopHDcoF&jH)NvLv6qA>?Tb@;fH`+-Wv+Rv z<)`vX!>~fmOb&$xdYr7_c;eO_kNkjx1N~!4*@8I?rva|zX(xGS zL~S6g;6;FGhuT2}2l-gk`e9iSzl+rycSBUd8>Os2@3^E9C!RN4UsTgP=44l5uR z0x+ARbiDT96)4+g5+>D(F?~A-2Fm_b4tho>L1cjzbeP%|2=r}8L5!t?6?_Y!riJ}Kf)O<&8M{0 zjGBOuyoy~6+gQgq14>C7IjgBJ!1FZ%Kzk29a`GgBC^DE9+-FSo^2v#Wh|P010P2^53| za`$5hg5=<+Iqx_PDXq_Wr|-N-pHSDe1^F&2b=GOOh(-6*@?eO#>E=~Os&8`~Y#TvB zcIU*$2SJ`zd#>&aG5^oj(16{L8>^*jrP}z@|0f+2;_U8+Z(P5XdXG$ZJ3^`}jh?XT znpWrzXT5n)w0aM~;c&DNu!ccauORESzw=5)b;AdJ!g`ZBWDFB7p2*NBW48&7t}7Uf zU^E-hH4TG)l+Rv%nZuVq$Ac3M7+R}KrHbwUdE703U2|@=HO>-Rv(a{<`G#zv_=Z22bI09?XcwE1=JFUI%+Ei6q zAbb!HOi99DcTiSzlrO*8#$!i^^TcF-(j7Hj7&z+P9UWbBoSOH`x!KQocSPe+5WR`w zDWI!PF{^ixHO;l;*uJ7QUs7~G-B>SZ21TQ~tQz7jXVz~9;%Bd;ByTTU*MGu)zWJJQ zx8KiCL)ww;io^R%pLRVSz6SK5R#+kdib}UCpnS;!euPHaS2~6J4(cM>^=GN zlYG+s%2{`=;%o9<5RzRdyZC9-DNd%Kv}z*D-ZzO47k3f@L^#CG!>3tuu!Cd08K8){ zOIPqn^!J$9L)%lJhfE-W)EiIBd4qTNpbXa|mX3!u!ZEa9C+cerW@fCQqRl z#nkDuxNgafZ28x(^5Z9d!nAMP&w^4LA$vIZ@-wXa&AXgRK*`v7eDEVHSu!n#37GV- zYu%4o|ITsRdeeZQbo~3cdF4uOoDjjLlqnM@Vbv6YO8H`bYVE`P?OMm?=?{FL2d3wR zM_v0SPMk@N1cxQ=JHG|`qaD4np7TkiTeA83dm zREoB3&+z2)Z*i3ppexQU|_kM%V&5K|T zVbAsB!%(G=j#D8J*Aj<@E8rxcFBxtD#8tX)b{NMN6`uLqfm zLvIIWsYwKjJ`qL93u0D|_P1yGn3&<7!rKhO0ku zA1lYh@z>X~?z`Wi|B*+zbu1W0KdpNY(LMf7?pr#UqSR^L{?%HZ`+kTq-&n=WXpH#} zJjz_lB9X}co~mzpko#|_A%q}W9YbZ}1C9Y4`!dodlYydWDPc0CEP;{`UKf0IQzkGscz6Uj5U&WmG7XE$ByHtJne*U4c64}#6U;Su=Ob%^Bx`WdfI9}68 z((-l_ZFMX7!oAZdlSyb8g^(Sb4A?WTvX`dyS$k$iNl8~m^2*zX=rXHWRb@f9$Vs zzQrqYF0+fy5+}_3hB~IEk7C4%5Sf$M(n)DoKv6{<P5EVTAPA_AxyOS@> zvY=a8vWO){kxt#ftvqVsE{xB*wyggUS-xn@u!Qw1Ik&^~O zD3oEiltGJwAk)+Q<6WdYEzV zS6SXzgtTpLyXOwxe)t*QJoOjMiFDCNF>`0kU`#ET^lxZz5s zPpKgc2$4qhy7t`jk1TJDVp|rI0`|<9Ja{sWpXI7OG>xXPh?n#dKwL3%LXghGx!`2L zdkADUs={ku32&DtxA56@+3jZKI9A<#6W8<}CL{Z4wH4hPp5(6li#8P|Qa_ay9%V zzQg3clBpb~fbPb(mIb6!T|SlZwaPkXbQvW|Z-(UHj;gGpG=*Nq15X=%`iR`v)7RlkPMU4*rlw9t`|e>gMzDhwfo^B!xP6gwvKq&wqT8`|{hS zJB_*EW|mHShiCuk5n8TZ%=OnVV$Rs8BVI$;5biuw(D4F9x?FpH^rb=Vv89240TZf& z2|PN>QKKn9(Uj|*38hddlvD^LV7u;u%Iko$C9w+5w(!DbRkQipvPqO=+FASDo9wB) zoCWF_bhjbOKoR2V+m^GkK5&@|K~YHw^2lCRto%4v9X-VJ+jjB2moiLVa06ehIY|k& z-yJ%0?A(ur-R>&g=WkcZ^I!_Vf=C2ZfA-*%?Y~bL!`mbF7no4sCya`0)}y;$;n&ji z8q09KX}40yMPxY!!;RjUO;FSfGdDRQC^~lc0Zyc0^yJZm+}jytS^j%6nT-3B@V+Da z!;o&`imjZ=CsGacJfu**U=CI8NqNUVZUujL?_6T37B+nEXY8wePyv~c8Hu2NPH!)$^!+d^m6%k`_8@zfgBRyXK`Jna) zBBRQX{pT?Z!*7p#QM;5ZN4;XT<~^-wUfRC5JPAsoY&UG@CLbv2dT+Kn`PzFfRbdbB z!jD$bV0AOW2=O-`oke-etE_H`(k~UEqH@M!apat!;_N|cy+_*tMjd_&nM#sw{vEa9 zFrT~YPQE_3h$Br$Xeq5h*@Bn>siedXd~dk8lJO$No>ocP-A35t-6Kgt)%Dc$Cvrl0 zL7OjR&&bb%Gj{2F!_qtNu16)M8}?Psn3;6v3c4X%$Ic69IjXz`BlA5rUsLlYUz0h< z@1EO2duTd0HI@?|J(V%$dG_t=BIBi>%PyMs^O_j;rv%~RVu}L~Gu?}A+jMm& zDV=gHs~&ocuPiR(`2YNd(}ah#!K^Cmc-0{G#9}emo*1D_Jf~oBej8=O!9oj~Ml)gu zL1iaZ`=Lkg0+TqMtg@Y{X`ZMsz8VP68&c0Nxx958;N@lmY58J5VvN0wd zuRY7Q-?wmR@7wG?EwS_7=Y{pGOon7Kg=kpDU)@~AvGq@|t;--2ox$?=SJ1v`HBWAS zo92TDIneYLTX&o$Ar+zcKDPaCANyO5vUm4R4zwm9T29OmL)wrk^mwHlV9(w|hd8k3 zEw=7BLqcZ5ir(MB+Deb1X*2~Ol~cLhn?LR6>boIGyka3j`lD!mC{l^SMbz7ydl6fw zk8#;m*YKgeFSBm9$)ee3nY-i`9*Vxn(|dODcuIj$#KbEaSXf&^QMivc_w3^*aT^en z*No>=cU(=w`CZuQB-bpvo?XvuWzB0Rz$m71@d6gwJD7Iu2l@NZ4xV~xjn z?4#FlyL}j}jCbh%1ap5psl9Djdt#}P&YR200?C#a^R@})k620xhM~M57|Oo5(pQ5C zS-$rqm7ush22H=_i63}jx^YaMwVeCzznSTyB*{dA3^4hQFLQs<8lHRMKiQFlSp8gX zdvFzt>nzeq2}ai28{lCvFng~*UBtpqt)lt+PxGrMc7s{TtdGoQMqL!Oh9A#T5X}cjU+wI(yo6wl;n7m2Ag<_Od61ifL)2TJRj!HNw z??!PskvZ=N1lFlTSf^SDkDrE7S%-*3QC1q&*F)ySe$1+|n3c7NqGHE;N%ms39zu4X zbM{qQL1@wy7_l;xZ6VKhVjXQpDe3I9svZ%FpptQ{(?_t|TLCbu#uC2lN~dGmu^HT? z5a-3vkoI`TFw!whucVdmW?H+|ScJ$fEh7vAgn?m(FiaC8R?3>@Q>=XSpUGs>L$>Wx zKmR$m-g+y^WD+SQmSqj_229hWyu92my9Cbss7xk9GMV&0&ZiA0WV-tqSJ^%0Fmi9{m4XxO$*Utb^Tbb44DJo`s- zyhEKUr4*KB5s%0Hu`_S{%rs5^5sgN9{`u$mY|9*LhGWeG-fJb!W1ZMH^moL&NbmXW zpsx+JPXN246}zK#@SWP3VLw}lgXaAsRbcT{_xvhP)B+E4ROo`Qx3#qmY{N{3vuDrdY#Yk9 zOeQnzc^b}!ksfdG{CS@ZE)nCsK3F>iYdh+Yqee4Q2SJb>w{bgG-}e%3o|jv}!Vxuv z;f2M7x1zG9AUzYx_s~SvT?Q5lrB4m;3S7svE9tr5tuVW~jss%_X*N-kN9m zt5y$n^Wb@pPB>Bvnnp9?n3tcn?{}DvcsU+|8y3k~$0_J!XhFNg)1Pyz-$pyH=g9<*3n&>`oGe zz`(X_r=t|Yop7bVFx@Fo*{b^j;Z~{;*&2kJ0`KCpeU@<7@ywQU6oIN(-dIbv>b_;$ z2#jIJF}>G4m@Y1us9HT=T~jvf%mltFyRuHVYl2)`F&aFDn`qb@jBR`l*lL zmR6DoBb1$&gqb(N*PR3m=q|5tj66@x_r6>~3#?h~itsl0vCAj9pw@QTP43u~C{J=?aKFmWOZ!OopK>FVmbqzSv4KX%(1 zR904U?V?3Ym^fkBw$*~B(F}o=$t~1(P%-_Xfzs)MhluoqtR$ITF^8ajYgxNBCyXf&EXYyKDa&pchklBtUT0000D6m$)mmNs{ZvhuoQ&vK7%UhN5Rk9pV&4@&KtPAypKm~Ye*Z7!Oq%ol0P3h9 zDhN_FfphTw; z_zVGKo>d3}LI5KET|mhVaGdGtrlkBh$mgmNCw^8SgvEMI1O_9a7>=th?<)MFuCMCq zoY;5*K+~qAI%-1$M*}SlN1+UWDwz!e5#R)mi&>2~zk7X65oe-QR4B=syc&y79nN%| zbf5H`yzAP_^3Nm*Gw>!v(_p8x?0yc^Ld8)~?>_Y*ukd`Cye z`Sta8Lk5hJii(1=vhd$C2QWS3uH1h@+7khGs9l95irTwzYb>4ag#itAuIap?Ka zXvg-!s^YDEsEZvA{svT#fwDnHOsO?$G-8;Tm`X}Ya&Da3t@>l&_B1fyVE*guqfM;3 z`q!|DUS3`?wRNymxgTL^(EC`F%4#0SFZpRSX+V zdO0kXb8$_`-_EnScr}AbTjmd52H;R#)yu)u)hMav-d+pBM199c3X`?t(l>rT6hSL- z5xnk!+E2o9Qqi61CxH;@hKDXom%o`{9s@QNWAe5_rgwl9JkR4j-hHqzwB(nMj#!`! z?Fz>P??n;g0!6L#z~e&k3fsU639#c!u^O_>oU-m8gVzJUPyE8C6gw1>a|)@ zlYhcWG=bz*eN5CTDG|%(@Cjn{49G+*66F)NaH9MnG$jG~??K<=y`A7mIc1*(iGuqf z-anw-iEvDKo}9BCB%_aij5`L$S%Wf;a+wEM7*QY%aq=#qasmPtmgsJ7<~?ldCvhb9 zkiWewLlnCs8oFGT0*jGH-80}w2Bl&pofDBLhwTgc97y7yXV;YjMPHdl&`Cbh3Omaw z3#N=U;>dgf9f7EV{%-JJji>@x%+ZKBbNU=t)G0r66y%lU`xn}$Tk~~Q4Fti4sA!D) zs{$hrfIs;&!RsPP_rP`RDHDwGgrHHsxO|L^T_aRM`T_whDyi8lQqrbY46Rt)cP%pn z*JY-(#G`pfZ$T8k>@kDm^Nof(hTH^n&HR}-ZkD=8E%oV&qs)(?MbJV;EHGju9EPdO zMIuSO@h~t4mG|)de0wr}$K|^b0_q*6tg25**_2ccVuEa;$QoXNCVPzd(fc`)m{Vcr zI*EwVHUv!QF|s38Q4)s<H$&2FnNH3*gG)d>QT7|O0} zg6!rV0j2OUb5vvb+uXI~&`|`$_1Orsc!vrh2*mffZo&` zy81|XWxD4R@zJLigjIjPKTs%%pZi$F{u9-M`remM*sU;&l>`9JXfdUd5p46EBCO6kAuA9{gA$|l zSf@S-x0rglsaC-~z!|?|=xxQ9?@qccd(iYOx1kZ2B-z304v)#<>kxYV8FtfxTZa22 zZ(o8ebBROKS_n}4MC$*04zJz%;Q)g*97M8Xs|D#2^4e_>lbwb&~&nI85{(j?D*x=s^FwZxTUr^#2Bw#s;B;5)2aG$_uTaz$#vY{7&%L|6O4z}dyCf^vJj&q z_&=r4R~Q58%gx@VA-R{9dYh`Lrq{AZfP=Q1mA)@gx12eL1ohdEVq9CGr%2 zTllP3rO^cVY+{=|sZ|XJKQQ8)FS$oQAl9n3{Wh@s&qBW6%IIF5nIRU(9F^DB zXS=6uJ_gPypv}NK(zT%j=~I%|h$UOMb#Bx zIkH{8r?VZp`lh!Vc+nVWm;Z80Q_-Et^=eH?<~)D*m;K^2ogj=M(|5gYxlhs3`Xfl&PREqo-$|qwR z%ASbzS4tgwPE+nvyn=W1RseyA4;xrGVj8dp*nNIGRq1lqCp~i6V>TlI#N~N!U@ui2@Auy6d`S3z`gk zG~>mdQj*sTIseTG?=(-;qO`hISru|Hu-yAmOtpyLhDV{Nn?18g(uo22Gl_yuWsJIB z&WPMk7-;dh7?PNn5*`3b37bG^UW{fQL4M9%%#SY@#g0lK2dNO;mk*#>SW{Wpae;K% zA|Wm$6QAHRY5J60;&!kd!`>%Abaa^Dmjb8o9=k)~F7>Q|#l5F3RiG#mFD_(!&SMZR zq$CC-4V3Z?=52QT4{rv%$vUM4<5pjJuo((G^02JWl4h%tLK236PZE zjQ4UCL}0&uFXR3dWrzllJ&d$fr*dpc`m-~&&~o?4Pmg_D=GwAG1NU)N|U!zEXapeWD4QrAXN$f4ke3L{ZNMElL`D!`)f(S7s8 zOP4=w`bHpJ^nuJz*=?|=m0y{?m9LA`q;R84-F1gYPGnAaezsq{r72gAT(q(A;3bCX z_MVPUosFRjhKZO>wo^C&1- zeNls_C4x6$h&e028@Pd-2zfs|ht?NlQtl3?bLFUL7g2XKabi10$C$(A=t`Kas8_IM zBux0w$i5_UEBZbkiy$lOx!RnTY;NJh%X@7hc-2jR(+@Y0LgzDb9kCEWRR&$bz_8v< zU)f{0wHcgRaqnC8A#ZC0ij6ZOR*RE&Ql#*D3r^{6{-z&I>2@F&t&1p8Iheu{NVjrn zIh4aj5GBB-sIXcA^HgNE-j8Jn0dk({PaRDRGAiN>4obK^@lcO7ozw_D`MnsaZt++vU}IWSn4TTeNyLmQEHf$tb-q&j+WQM@-zM7U0LYtJZQQOgCrIxzPn?Li9w6h+ddeltd~>M@nQWq zB{f4qXz|hryvk(!BSA4?(EihEE94Q0z~J7!5vbcaCL+=(-6-RWY1L5old1_fGy0QE z>Y@%<8Eirl-l3gYnXR6Q?9<-%ywv*C*-cQAq9R2k-XD0suqYhqnUo~;7)Nb5>?T1^ z?j5csGiVPdCdT+5-+Vw;OUoA%vPKcc=^Vfw?X-j76nB|c-F<1x^x+wAV!^?N47QFr zo;NGJ8nF^9tLZ4)Fa};ugdU5mjZY43Q?4!-Dq3Gqby~SVZ(6G}n}sgPcZy_6Uh9Le z^Rn)3r3VvO!m|9SD3s*R^VX1OQvL|2PVVCQcij}D(!X1pMo{p#hu1gWSjV}dB5KPK zC;h>u5?{xov>g#oAd=^s3XPgvzWrX%a+q(KR--)n`gwDf%*ag#hP6xe=;6Q_+9RO< zIyK2oezwm_{{HE*H^n$i=cM=kMhml*bZ#g-l7?E%2va?&c8CeB@U;5l2^vjZ|D#T6 zxAeHJk-C725nY0k$MDxMt$Q|qvo=5~Tqyn~1TyJ@$cRv14f~<%_oH9g!FWAclmffJ!Di9_nW}QQ0l3_zxX#%%`afCEtXipzD_<3|#A(3bv)p zl|_M2qm=9gY&?Gl6n znqI4tJ}VZ2QI%xHQr412&IV2%Jl@xmSx!wBb#(EOa4GY~;7CVfr!Z*!vkRJ4UEc&# zn-e#C@Y-Y8P`iZZ z2N@1-_L+wEDC|6y^SN-MfWc*<0-3+78wX{T zdxA$ye$G2ZPS=gE@!k z(*(=JK8f+-WPaqt*U@bQ@%qeInNG_IyWfv1^vT`x#&b+zrGH#oa7tyzzKbReJA{<2 zP4`IQ)-c|%Mwgx}5_WH{x|mrgtLKM}{yvp2X*<9MTh-bD1-!K`zx=WM8vG!4y+^hn zGdjn%!1B#bU6mbh)THZTW}<|+n11ncJ*LH-PVaQbz#u_nx(1)|iF2dNx6LA7v}FJyZaNz)UpgJpGX;r;{N4Bl-8AtXikY6S1cs{LdXcawx%ZFrU=j z3vqZeC!%#M;X;6i8N6dEBTsU|*gRZu6nXPyddjC|N0IKBUusXZ( z6uR~2fop1zKYK7ZZ(9OQvoNLC(jXzkvPfjT!uGiLE_ce7I+URwOIDX}o{elIovs-` zX&H$J<2!C0qXwc(?YOK@mU55kocdNCXrfiUe#h-N-uJ_rbwHc1{RHnOBZFkwfW=Gg zQFWBWVEHye6_Wdcfz=)qoRp4%W}TVzr+;OF86NFwxXfK@&8YJ==L(vbh2zE1kzud7|Wqd51RH{mA zZCTzuz$Ii|+Ns$H%%xgy9;ng|Np@{IEg9cZ7#QmLvey@_skLB&UvJ}db4mIo5iuXQ zn=~CKK@9JG%^cX?R9rAED9}3PVm)>HyA459-iW4fNvex9m~aKy-tnL-kJ5C^)!*?o zbn5eW5QTgQZWx$fU7TJ#%E#PZY3{N*(bdUGpW{;2MEQU6bu* zOd0M;fR~(dhVep~Z7TvxqyVEJPBke&il9EC?EXNEjr~??voBbpea<*snFtkH7))Hg z#naBK@*CLmQ+qtlH$_2did1E-{*9}`<8N`3x&!1JrS$^?;*7tR*$6_a;S)5Ip%=o9 zv{~HAx&wmF`MYF!2KtVGGju&iBMlvt>C*U}1MKQlU~!>W_gAjd0yvtg`uhZr7wn;0 z!V}eeSL3p#6eV?jBcVeH8{9A3;BnkR?p34!tMHrrub4(g%7{o9{3breos`PMF4e?M zK#o=45-w2Q`Tn6o)Xzm;P56mz=9PHUQ`y74@fLi0$x4^U&w&&aa-P^?-m#I;Q}L>5 z-u89n9Zp6RpAy%7 zR`I~^&8&g!KAB@wWzF<_w$UEObEmzhj_<>867a0ndHK*|jyxJb-!}tt^vF&A zcNI_-&$=$0mAN_S_T*)Vnw6MZqEnNT1W2U<4KdsnIroSUK~hR4Qs>b*MVEVD44i3wU2no~cOb;*eJnwm(iudu5m^b{WkGeOY zuM+VcO#qOGHp4Ags8B`f`(1GV+=4g=*BbB3Sy8K_$`xqnCmcKQ0Sp;2Q|!Dw4SGL; zl(3|@-yQYhj8gU&h4N=o2)>Nr=jbs}mnd_Fk5U5%6p{?!Dz%65&RiVphG5+gFi>T? zJ+n4{`GA&ak^Yn(bEbE?PrK+Ykn*UM{ zoScLFCNJj?@u9)4W1)!U5B~@VS~93LMy(l1Hj2OzC_|P+DaV`dXtuyz?z+c`RuQ~3s1t3GFEAuW3av$x8Uw54WT`_Jc-{PvLWvr zV9To`^VkZr?E^}Sw~R|_+nFG)O?oC1d3-inrJc^9F_oCr6pE&T_m<_2DzI$l2qwL{ zYFsX4KgRQH?uC@KBdUJ)z=VeLb30^>r-!*V3+3b?d@{+qXOoWEy&>P5l5FDbob_p& z?%75RT;l_E1z5@xB&N||t0dNm{Ad!J^3hOMNYDW7C)11b4l&Zaz8|_jEm1<^5LWK! zAW7_)KGe7YUf{UVRy61V-=thk-c@JD{izj z!X~w4{dWIKMCJ@3izEt1<_08V!=oz}<bjnyygo*YjxrLY zJ0`JKCJD5`6ALGgDIxTJa${Wm*chU8-^>A zL}>L{(kt_nJV%3<%^0P}H?bpDBo@+GR9LB1^Ph8U2hCu~zR=Sy4F+#Yw4@>Ss?i;T_4WSD~fJ>2pXa;$5A62dIi=mAj$D4bvqhHaN-Q+-4+P)KsVfId1g})0{S=-y@Z}QeE%|dR5eW;f z2aNqPzc!2fhf|<&Nct>)w^{-sQCYb!Wy`%2d*DdV~*N7j$x*gk@nd7T{TNi*U;1c(+lw8%QamGAyEsk%p zqy|PM<$rtZYQ?pbJoIq6uEiLbLd2}*pr^qSe3V}ZT?B5DjyaIUErO$#7IP)vYa;K$U&x`+Fm&}}P)WH^sBGzBwmT|?I9G5q+F6Ae-X+I_v>&FpgoB-QPoV1_yxBB*}XsY1L_ z9{jt4+3RWG6CE;BGt`zm@5>h75C%u)f$MjB){0&faqV|d)x!gz(XW$;YiaZa(}dgE zKtu@mWmLDaDlh{NSd&xvdrgoZQE=rtf2Zq)R@4ThGZve zvY?N76C;v+DU6lLxcnPZ`1nk*Ao4&R`du( zS3ZHt9pl64y&PB0C}^bgmiUO@dwS|{j~>LiZ|A>hxAK%<7T@*0<=plD9)35=dL2wb z9tAh64~T1b8%Sd)yGG*Yz$F9n7}kxvOn$)=;o&3Bd*-XKHp|?*uV?*dMb!m8O6`GU z;B}`<<>7hjrSgVlRXKGnDT4!%LZ#jvnIBOU_;@5UKoDcxgqbWJ8ebN7Qo6;zZn@q} zsm{4<&Ojt-T#d%$$TI>nqF>>uYnRnVZ_i`r(aoJ9Pu3v+uoZI=|!7TPU!jPc|+%T6k#pYoWPHZcsB+iFjOM{*~ z?Y;NR$|6nBY`MnZ4@^rGh1+*HTqvuQsQ#GGDxn$0;+*zw89wUQt_V@i>3nKrRUyU; zr~QcJB4}djXn+oU^E@X-yPZM58^YKx0RiI~!+fFhd^qu7XiG_}WzhZ=O)2i?zf{a( zR(fOksr*Dpb3w~4>&)?Y$G_acfokF^Q6)CgvBfGKcYWjz`1hcqOVc`Oe63#Li|oP` zEE(bXX;tx^n3AHd^_8{HgFYhg?xtDUh#5;dNLZ%OB~ypjdbQPCRINHKc0_6x4%{9*}- zTqy~O`hb@F4=akj(u+@+%auG9@2XpYU}0UC#i8<5*KYk^&p=lu@b`$&LlG{$Yi)89 zH!zz7_aGH!^6k}WD$Ew#+6X+(6)n82fhkvFcGl1(ARXpRq@q;uuTLqD{i&Q%K8iWd z;}0nk)hBxvCQ&I;sgSQy{tm7itKUcL;Uho>`$dW!%1QW1cJ0R`r>L zS`Iyx=4^?|0=i)Nw=((C0>GpJMES?ZpiAYShsqbpudSqL)Tn|kUSZg2P7!h zNg1Ui4GzL@#4>*3@S%%tK;GkUqe`!D6;61+WXcpvAl)Bz{;)qE+<(ik`e||CqJLR+U{2)Hm6zsU|m4O z*3q@1NMc?4NIK!STY{Lzd$ROlg-0$y>`&7aI@XmA%V&;#e+QAm2Sop+Oc*0AoOHVw zVW4<+;tP}`I1yI-n5zNhDg@fX!GC$XR@e{hPk*WYe`W0J7_AAtM`(3!rgSFyUj;M` zC-#aT>hJH0j_03}3sV|wyN&u^4QS9ez75^mFiQH4IBHEcS&i;|d)2V)j+lDgz4b>B z6CnQIq`h*qCc*B!-TB$A1LwhEPTKC|u|(_rn&UY%#M&^{efVHO*S=6;Ja_-iwx$DiZmNs zL+tplP-pgPZ_A_;mF1{MN8~)Gh33;7eU-S5JC{BcPv)o@?dS2Cult?@Ps_@C?Lij* z%7M?8VW-~nK?}`Vinv%K*mfDjCi@vugxq6h_7p2|YUZ)a3@BA(MVB{5vw=L5Y#)zr zVpRu^WKy>Y2$EPVz2mQ?L|T4tdcY!|=)S z+kLOh^kkC3EmZMfi>TXW)5Luli0aF>3@~GUjt9tc8Hjf);@FFR+@`>2QoA)eseaju z2os3~w#Au4_sP1_n)%_d75yRijxXgwkDIeFToJo_Jsy>dL%Yb2E{GRiW-Ge)_n(%7 zLDJGI_nTzJ49cdQF9*M+k;$3u^|+j(qAnu5pIOU)-k3MNEH}v457J389$2E)n622z zB#-3GBO|SZrQ@alKCuUg2y>nW?mk2#3{m4y8j$#6q4pgyn_Q|tYjQ8~)m-2-DvVF{ zS6@wVVz{j-;Y9{B^U-XMx~}$|-?6vS*H#S*{U2}_LV^_Y%`-CesRVW0Qt(2MPM8J zd_CvYbo_}|GHu-P<=FxfRCFf*{bGSMXEk0zoW zu)+HMG`stgCi4q9_pdV~Z${L2A1wn_ng9~1I-IV{hv%K?A1=Cez^Wgsw+>C9x!fjD ze@piX`n~U&^5~0u&Z4#6Gf+t5wS|Ie+c6OY$GPybCI8Ny&9{Tr`V&OCHpx|U`yTU? z>N#A`Df$`j&WkU^-IDN)SN2BL>{#NkeeOUe`#cmH_NaL^Z$Ts4$F`@U@ci1Gt!GqQ zOUfhGEVUl|xw`b$qIYoapTE9#YER~b$ufTv5%L*8OUkarUdOgj-fbSsY7ULzD!#Nh zBiPQv8ToDb+2Zb5jqPE2D~db?fyVK6u#o2ATsrb~#=Rw?t9D&Gd`osAgRN=8=M+$) zZkYUT1y$Sg+vd+6YY)E5GmIb{uH?F2O@YM0WM+Z{xOW1~&!SM_zrbcn99dl!uIX8s8>h!`@RL+qn77*Afl&sIQ>ztmP92rVH_ zHQM~&_^WC@7AwuC_?u|gP#>)Yay;BWjNd{#>0gFqQ$;+SF8T3+5wErLCrDdf9Cuq^ ztYjwpXD6#~$J*puor|IGop7WA4v}4OX!QGP2$beb7ky=jZhyIPr%(AbU)Rzk79KhN z=^xCFX7JSxJkP7cG zRVW9{^Zf2?<7|+Ig!IvKT0_5fA+GrkraW?VJXnf9J!JRi&OsP-$8DzEl0A;gjnG-F zq}kT>7#HS=dCt!;{m&4jB^JTeF-f@6#t&Szh zJ6UMIg+0YX)zisOD`ir`H5mOJC7xEQ2|o7{^uidfp-ox5WvNRly>cl8-#t3|$VtWjBvshGiOm zy>6thKJ6a2iC`m$;%8g5+5n5jcyzhYU&$rjPWQ-nT;e;$ckwy#>QNIcl?RoDp7jZO z=$V?P0)}_bH;&H+w6Tq{+1v+|t&Z*dFSP6V=Rypl*E;jAX8*>NgVzi^UliVyza#tP zj`rM88cI9PTP?{a5=_z1zk_8^*AcMD`NX;)avG_f)rx79_PjsG6^91l_VuYp`VA4x zoi#VYU^f1){w)|{Oq~n#tcglh{$I?qLeay;G~k_iHrxkE6p91~5ZkaPy2`2ZK-vYi{)Sb{;M6^wy*~}?H5NJZ8B)=%` z`XrmNh+)*urtnYaC zXI4ua-(b~K8Gi37V;`%PPN$`)?%jqdMT^WAz_yyL5%CwaSu-UC%aGQ#4`-l5-eikT z%2I#7W4~B)CG)%?f?HaFDF1pS)=-op1bJm)qS=!m=^;Xywr?cZIR8toI{47Ru=6Rf zfl&Orm~sX$IU*LSu+j;29D;XXFc5CUE|`!y&*sQe&9{XbZC?OKSuZ_hN=ua`Q zhJfX3hDnEXHm6A8O;piW##74-G>A{E?};4y>zf7K|8MFj!9HSLbEr7&YIIzqS5$c) zMB_-&tc`AynPgx7vT=QaKM_9X_~7Ks%HH>sx1C|Z^cn}|;kfsQU{#AP^KQoz1HgzN zElh|S`*LtpMoXJxb|;}C0!PO2ePj8yS}h58NIG8eJdq#9Zi>&ELwstasj;mp>X|@C zHUGA%?;P;T7&Wi^p^EPzkK3YiCrD|PyW=8h*{{){7YrKhj zaB&_rSe+YS=4-V2(gG;Wd^2D1q2*Z3B)9wdUejg<<^hw1Khw;*%MDdwj>qqPJWS}a z#?jk6F)&DD>(3x3Kr?Y>d(H8`VN1TRN+(#DzrRK=kHY(^%ektMyT@@~kY-(Fj3$?x zT&a-m=X*FVT*bH2PW4hT{S&9#rcm&Cqw>AYo}3&EwDE7hl|Z3}MI z2CE8&>B=?9tu{tpzRTzxf0OoOf;@5?$`;-E%6z>+!$2g8-2G$^=O^yux{JmgFgmJ* zD|_eSJ@BaWg6mEJ{mD*v(jL3Mpr;@-J#%wceTm-fPP2NhyQ-P%C;IIZ-r;Y*Uvz-! zI7(D&%u?#zbLX%~x&r3>ET5FMxeB+0j?6n*O&B9BYT!Jejq^GX>a#3Pe^oR)ldq7k z2X{iyL@YhakGMFpt}&MGU>c1#h_gzzPa0mm@t6oFE89v*h4&xg-V^L-#`d3!)NYrzx_sQd-MJbPkLB|`L@*J^YcB;dHg$L zj4xHZ0~JTxEpyX>=*1xjBLR#qLf1L4M{NF98b_fqUpofAEWG|$0e7kAa_)%&K?DuTzXJeXC%~lW+GIXzRQ9!14LS+?wCEE2h}SLlt^LjCG~J0W zdU92$lnegNET!YdfZVY&rO8I^Zgi@8p@SE#-t|II1s?+b26g%@IU=b+oJ0g2%ze(D z5jjgI4!lL=U#ZDpm^{W<)tyW~iwDWs+YTPmnr~Pas#SA%(F!kLpubY~rXA=m7$|J~ zJ>K<8ZTOAEriHAV1>O4jhQTxBYi#YOxT<4MX!^oRVIp8tR#vXvn~IEC`$clpxEDoV z<0AU+?)Qnb8@pz_DW5znWiIer(KQah#_Vo>g-o;MgQVUs)rcs;_Lj+K)#QU}f9F)R zh8R3BPBJ~w{!1NGxuBabu{nCJPxI{&_r#fhPQZlkMwU)0qyLClNG@Nl;RK)ir8J4M z{&eq{uSi=-b0*El+In-NwJqOf?EwOQ$G6a}&g`x1Xs322(~nrjyhV)r@O_YzNVuI-Q5F`D zw+qK*&JU?BY>>r`yg&2)(zT5c{<8nvE5}Y8)*z&nv>~qb23O)cyl&Jg^+bR=upF4d zz<=N`RVMll$yxUlndS4&NT)P6kA<69X-^l*=E+a3lg8-UMmV~TaLVBF#m*ML1A43g+IWi2iF#F}>#=9#F#j-)E-{OVmAr^hZqwi2+E@yx?#H&70FM|zOX zt>PUI8C&v5&jp{zWMD?1umkOaQ~$?D!SuPHD7lt}KGk`~T3+IgQ~Ff9ST`!3gi9L1 z#z9XA84kEj@z5Ndf6-$JGWqK2hjAIq&jz^{Cb}YS0;mfrme#VVkqrj|whNPnrAkHpHxh-#f@Muk-XCuc3u|gQ)qJ{8YATn}0)owV6+(Hded(Z>Ze;@8sIF-=BB@f%JUE;LD9 z^N_{nxY}`I|Cc;Li-~p|ByI9~7b8d0;m#8olME7Zm*z;58G`o@gE1S--;~PTCh>3A zinMlUTHvL$If_qa3oGLYbFC(^h0ERZbMb0@Fr7eiHZ?UNc=6=}Ih$3sl9)99VS>&9 z>fJ&o=(@AmHtenaIbC;zWD$-b<2ebn_=)KxUw$9XcQ7ybZF|xYG@9=DRr)Bbki!)n zIB{@rqX*_eZY|zgid^<)Mc7$F{;D~{NGhFYngipSWYs2Na^jZOYwvL8@l8Cg!l5}b z$*I=+($?QoD3`$>8?q{*FaMN;+1mcMnyJU1jO{{NsdE6Dc)*H8o)*{JY>vyg*e(nf z;HEpvrQdU@#+Z5VhUWkiPp}zOUu&@|@vJ$EJm-zTzzKb6J__K#Xmv{Q;NoaygWMvS z2oBVbiGPM%^|S;V_5p3^KGo65c!9?6c%sAixhBddYVb?_(rvZZ;c6Q~=Ei|)`F5Ir zP|7n9V$F3=H!ip^)d|%$l%H9@z526!(J5}*BynnNf0_5eHJ!{04eS9pkmhzxVyS9F zc(N}plgX(_e_!ZGO6SGcyr0C)*e3;?#y&l z!}4;P3?=P79)oG3GkiI9ns%`^22MF7o5r(-xn8Ms4^~t+)!nTV!X2-Uw4FsOZtU`_ z#ee6tJb>lZsZS4tbiFtkJgem<&yaTo#!)Q1L!{v8b>`CqP&0t`;8%I!W3||jsx^Kh zXDq=dII`yx3T|9FO#9u<}WLvH*C{>UW!WFUR@e3x_Z6DU-CRBFz>c9G&OPN z!Do2SP3!Qu3YLl&JrB7OI0SXT-_XIx^skG}8WWX0>GC(S6_b_h`6kks0CpM96i zit_#1IRPvs>6XMtD5uRDqK5;O)UF zb*`6N5W0`tSh7M9R1~wS2=5qpMe2S&Q7vS3y6=PlU5GG~Lc8{eTf8ow3BY<) zFkyaqR`jylR#Rm402DU5Y8fz#-!2STtE#MC>>DJTpz(=9_uU_%uE#5k4?X82kD`q8 zZ3ZRMzf_jRCZk7vcCq$mCE;Z=sWmj^_3^eX2t*M5MJo6%TS#gCdp9ac6>HX8Y&OjE z0bc>n??#AZ7{>m;97W*M_uobz$O8)J|L4-HcRl%^tG52jW`rS2Bu8Gp@$CL?c4I@d z`427sJp%#TfpXC0jF5Q2?|9-?f)$(M`ApvkK03DyHyjZ&Bt|53Qxd#V%`j`mnsXsXtUYB618yBE zlEQD-pYyL`rpTH;R5z*<>6+%KWrVXPF85Z9_xA`ARMT#6YI~h;;zZr~MEUYge?2Q= zWBORFxt&9sDo{gK%!%B_!wP2W<&M2X z2(_5a=NCD(i$j|fs5X>0Ud8}^Xs~+bfVwxzNBs<+BAG7F9TDI4Dpp0e?Z7T_da29HcOm%WkFxAussAEiZs%}F>pJy83C`<$Bsc-eo_^}g!; zEsfe9yLWZ>)B?xq@zSTA${-ycsT{%Yye?; zNY~Ln6!gt{S*O3gp|Crk9>=Ey+ecWyQ*23YgmpbW9r^rq6y>9?4=Z12;%fioGPV0X4fu?@!pIZ`p4s&547vle4>qjuo zbi3h-#%xo0Y~cxAWp?IP1%`w<5`q_CPbZFMD*s&AW+nkkR_1WDpE=Je0{!o#cYdjT zyXqzC^4j|f>+2i;gv7&NwY~f+A4PbrceeJz4YO{s-T^UUHBEEG^yaegzeGoWRAU(@!>aEaT5H-@*W1pplHMyA{ZUxb%waHk>fdnJ)p#Wp)w>#l=%Tv@Iu{^`KymRX z4eppF7ai)-bZ{$y?tit!DWhU4V{@7(y3jxNwhT8_xBDQi4B3gtW_55O;b0>dMXC!n zB(CRzhcW9e-fd>MZz?VdHd~y<|9748&`@E2g%}T)(g|*y_@?mWIl;U@lpNkPpZ9T5 z=Q_I4MEqVwrY^FfHlQbVrCqdb%9Y3p<=qkuX#c6d>E-^aL`^7q*UzMVt`Bh!=6lZm zu}Z=cWj~L%?Fjd6UcL3_kyntEBgl(_;MBZV=~wc?di+sEU((6hYl8BxKZs+#qNucK za2ozYO@_@}nUd>a=K3t$#1Sb(0YgQ8_?r#i_u-#`7vFGas^7m+0L%8{djV=Qdw1PV zk5Ge-r&SM&m>cbzuckG78CW%_Dh1II&xY7`rUcnKAMS7PA>B3Q2jB_=D6fe)ELuUThSl_3x)?_Ri+44SdXq z@DP73Se}KR^KFXJnMHo9JV=Qnn_`xO2(I$#KgHHYn6ekJULa#Xq5E*a2D~Ls21}v1 zA2Do>j~U?qTF4%n!i++uW~^ay4a-fNMFsb@J&6(Ld~U z=&rC|w@>EI7$u$2*db5~l72M*gQWFig-S+Q&vxK$hS~8wf#%OjZx2OS zhBu!b-2Uu$T<%NP`U8-@K8P*zku5nB2semLT7Q)F4&DhL%L&KlZV{{_U_`rU&;?)` z)2kwL=+C#{8BO$$K#NiKy01BLp~h(=ET|@`k-B-EuY|{^42(_*5PkVSMX$Vy+c&u5 ztnIediR1M;9l!0F)TxDs^T%n3b><)DD^^pv?+l~aQB$^7XQT`HeQA9Sk&`RwJTHVc zJnxe~esm+gV!tjP6cR6ZepP-w=F2Wj-@9C0K$Cky;yU+vTub@U%<1P7k8dz^988nd zh|eNWASGs?S0}qdK>jdwS8LAA;)_>~KDqv6K}%@AAtqKrQYw#2(@*~3zT>fro(l5S z$KE@YWruCk31n5~DBu24Gr!(J`e**1?J)X_j6JO`E!OmADgpet^!BXmG3zkA$}U!Z z^#72fJPJSLs2^!S!hcR{=R*~XI>y_ndp7}fYX!RBeskZBcjvHJ{HxaZa$yVuy26CYTpGSy3MktrX_t5H2>xOC z+^?0tX+}r>F(}s5D->sDXCp*L2_w+`1uQd557-k&OEvI%$z%S-sd$l_XF>3nr(|8;mW;e zQD^ywX}a$keUOvxdKmECqNw1M@{?gYo}rp&3twr6eY-_)ogNbO^@*5FRn`5${{HkA zIX~7~)f~aQ$0AIY^a}#M38IEy%dLe350)0B zmjeVfpBOe+HRf+&#BF2pCeub}AL-wtH4b^e)FV8Z$5;{P{T?bR?yl_68)8|doJaBITRX`f;!#KyVM{_>{Vp0Z1# zgH&5JScg4PXr=hl!Lkbg<7bKc#PnDmlr{_ZGh@6u+s`gMW(V+~J*F=0v<-~pywJXp zkOlK8kd{MSFAoBNm~Rgdm6ViZo6aVh$5JvkXRfcWPfY6P_xD|Kyq`ay7__K@x^3TE zoc!76UY{te(W677+KkxtV|EqNkaiWMXmJpOJp zc15-LLj{8NRrzTZ9`rsG_`VwF@&EB!`*5wbZC0peI=c}@HvPr1&?uxx%SCHi@HcLv zq92Pr2M$6UiyRvE*PsUl8HwkPWMfJ0#tPlECcX-4eMId3FQ)24CUGr=-qJUw%_6*{ zTpA*{a7~oZ7=Bf*S@LM?q{mikfXy3o89Y#yZ1YGlwPJI~W9Kdby4+Y^yKaqTpJ=un z8YQ`8uPjGW61q=4V!w>?xR1%O%?<1e&s4so%lnq+H z8kI#cLFG$inE}e|c&V!z0b6XL>`x3dTS6|c^E z$D1_-*dt@s$q2)0K5;(e!0*wbp0e{HnW~QtRcuy!#aou2R9-D>ZbB3(l{bYscZ+yj#mqsC@2CG@x_qSWBZ;yP z21w2oS~_;#|4<4!?z#3QPOwQIyP!4h`Z@BKgYvm0RW@Jfu^gbBAVsq5@)k4Sd`;5f zF8k$IS0zimBTwv$mQ=3=k_7A{RYyB9jEDa7G}Y>Rq4>7k%Vlt;M0yKtGkzThb{|NkLW? z7@Bw03s(r<^?cKA^%|P3p+?jNUY}VJj-(eG&Y2o`qW6Mge+izMl14>Gv37+BgTCWm!)4VQz~S4 z5Tm87(+Al#LABn$fEvsR95`jb%95Py@tUB8?$)E+kipSy)w_J1c8H0N#GJg6m{&*` za_xG2H6zGu-qNN*dlU30mJYTl?ueEcVjh>pg#?(wjPN#^7>#vDLtFd_`PH0~2mFYh z|LMOwXO(Wh!zu_w;Ua0o+24mccLpUY{RoQs#_%ONWsHsYUH2yroY0SCO1@X|nMdcJ zjX_&#SdlrYf`&~NIJB_Q-s~@zhm=)Z$K5A3xOhCIDoiMbw+m+Ax z*~h7Y+VeGg5^L?=Y-D2-W^?vJ<&?rj{1WRFu1LAu7Og(h{5#bfpQFJU-BsdXW?{j2 zaKB1&K`9|(d2&D^+6jG7;N|oEOK>{0|Fou2+=_7Je}caNKXuMN!p`dA?Ya@Hrj_;y^iK#?dJy6*h5 z&e`9;2GhQllh(9KnG~w6z(vTnUGY;mRMnAVT{zVQAv2mEofv*4YB^sQ7TDk~ewdtH zZ%-{9aLvF_ardSogU;f*O(k^2HwroaOqUu+B^me^X;OAbt4+UeHIeIc81jbG;PRqU z5VEWSU&kD8VX}`H^#z1WuEa;Q*gaK|_SUUjvVh^Et!BkHpjwNF8LZWlAJQ*Ltw+vB za{P1XGf_xe?<3xW@VU4VpQVHuz#wy~hJfe+yH~LYaw4^RO(z`r=;A3jEoaJswUop} z%IIUR@CMh+zI#!cczlj7gjD#H&-t*hDThV9eSfni9|~N#lH%RsFWjRuDnvD>cly8yoyG&3OvudgLI3IR4f%yD^wtIqL(nQ&t~6Be4R7+x_cub% zJI+|Yy#fCTD_qHaZM#yMWyAWKbw<$d(yy$|2J7$#s|ZMFu0dT%3D4NrI0gD(C@MCe zn}Lmi_nCtaMqH`zF&+;q z%%8t7fv7kSWxA1^&M?e4qX%Z_xay;%U7!HzJ5LK^^%osy_|aUImfOJfVmkQH5wDS) z`UI|tBY#MPvD-a3)*%aJ&b|pvms;DBT8wWbNzRf%mHeGtii;zr z=^NaxAgRMpl>6wGek9Ch<&5Xr3C=9icp9g5u`y4kvH+l#V|&64a6IhgQQAtTW}R8; zZuJ&_6J0&2M7ihn7_51l&IN_EF5^oG^}z=IcwMSU{1`oLPtwL6J$IC+HlWMr`Gss6 zeWA zW=8X5o(_jkv#PnUJB8;{Pia|x@j+6diIlCdBfmGtn#a7hqnR^R$S}R@t^UE{cOFk> zxdE@TRcnKmI6oXOra3LGXjF1O{rXv1Ae#TPt|tXby~g*?bh+nvdSrb7_+Xy0Dex_M z9oj6@8M-lOx_Y@7fQavzq#?Yd#>Z!sQlTkj!k3qicb9b$7rNILVYndIl<;BlNGF1p zgkt^uI;UQ7vV!cINO)xnY_sx3?@C9_k3uQIOfEIS#>)8!VJL&Cp^kd`lNZNxL~Z+H zyW24$He=-j{zuNslD3?O1?71qw)|Z0A6N%7{}dnnUSr{z74SOp+Tii&GGD?=frwVl zwCSDp%8}n?r}WcDM$PLI$CN`B#4X^U=RE9R^^067RJHojW6Jk5WDSjh=B@xsCkRwc zBIC>@;|@4aU(~L^GT4+9T(^DDR3`w$VkmQZ=i?(Psj3YLU=9)vBBw2H$p{KuD{S+; z|GHUVvY~{LjJ-V93*6rEUvrQyJ?IE09%%ozY{ekR>m+lt@v;G`$R3J-rS_7xYtOD)ML?uj_sqAeoZ6ne#>W5nd zKS|nqpm-ofVaQK|nXaM+uh0=yK*-otI92|P$kF9Mf+qXMye3djAE0i=$VbVp@51dm zKKanvFXokFjH!q6>AQnudT(^@Wb-I+Pk-j-^5xrJ;=olH1&agAboTeTn*5BHj8PQ0 zas?R$JQ<+_8U?z3uT%tVeuHW|>}O;@e^F$b&lup3mql&D_)pHxrWS}SZG|X;*8I-A zA8y;62?kH_O2;0qGO&EhX(1CiCqV!#h-n3$9Le9FBNwQI#nW&5#T8z+8{|_K={U|! z=X^;wQ5G}cW?l*#F3uB-qx{aTFH82>1*X=ZEW`TS;h~-*s3u2^M?|V$L(xJ!`ogI14ccPAiL(W#H(!`faVFHI zQokBCrm(cXi#4OqJ&9qmXFkBRGM?JD=*q>F>UdK?KJg zp2YBDf0a~@KxB`qOVD+|ivp=J!(3;Qj_OD@Qr()ZRKYKKt&{p9PWzA{HTJm^(rSrS z9agLECWb9l;IB~G&S8e8)qe+%=w57RTsB+B@ z0sUJ4>9`uNH6HXxXeu_zW7hRx4do9+ z{Z1lNX@DajF^15RA-IM#p12ky^56L{L}~jN;Vy9cK)?~w7RU90A6ywClI*lK{n%2s zf?Li0Sy+UR-+@OLccS8Wz5ayP9=9M zY>ytc6&CPce9Y^#^&1Dk4Y2fa7XdoIsi_)WN%b? zs*|?ICaQ$45w}!YuvFOK+hJrfJq&7*kBoT+d!HVsP4$gR1}?aGFND4Pat8$55jqu} z=FG&o_ti`orev0$nQnf*zFV7}xD6Gh(BkuF9d&&>9Hu8y9E!`es~8e93hI?*eSMLB z`kl)UvmfrebL+!IWs9(e+m}U>9T6hJk6%TA{UTPRPe4lW2ihY$;~O=VCf)NdInux4 z82P-!>pVw?EVd31LzOJ3)#$*Z=}H0wl)RVNNxYSEnT>G{32tEfskIa8#-q(OJijAS zQje8dlF-N^@c^9HC>U#O$IGQ8olv=KtXXA}i`~mP`A(tCw{5!qgt7p0gM+rdgAc8d zQMSL=pSJMDL{G+i@80p1uy3OV&y(l^y>u3yg^wswmXyi%D`vC!C3_MkZ1pYQVYS?3 zK|B~C!;-8Ml>MF*@CA8?-L(A{b*2|KEUO4ywVbF8h~pzhGFBZy94?cvktmBjs)8&0 z?WF^Ae~Iu9J&|ez;+yYOD@)>Z=F6)Rt%GZ-5Y4>(&TPQ+-<(SS5wPH~XxVX3g+D^ma z@~)Mw1^jf;IyyQJyRzlO`3A_M`oHvB-0OmO?-m}QfZ0VwU);oCGpU{u8N(hpLlYBh zbkP(M3IcN03nCE;pR5E3WbP>k4h~L=6%7KuJXbf2>T z*Md^_oR}eDL?7%E*K#w#>TtAuQZ(*ydXqv5h~Uz^hv=wj`eLI!)WIv}ZNbF)y%|c07N{ z;gg(oqs3*$K@{C{Bw)<*Hxh4ay~D55X&UQH2xMTSG}ACGD+}5}+@Jzcb3U5t|Cv!p1WnjqdN5 zLr4f6e;Ki^G~=PjZb+6%pCAeCe#u5-v-#!p0Gw#=#5;eW-B3SYGU1qq=CI%-CVqFX zVpG@qO{w%Mx6IAE9h{vW_IEi|Mx#Wd>yEw*#FpY7{zJwFj}%zC?LDsQUNu;d_abJ5 z3#7)(!NarpceOV$De2T*x;a1|8QG&uP|M&b6G!iGnn`rKgg~g;+izEOmi?nHI$*1| zNRHQq)#gi?e0tB)_07n2%r9{?HD%R5l2675NP{2YQIgP;f~?OLYx%6F2Lq#LNNUHE zhq)>{24Fxzc3$2Is}fv6{ScBJ1^FsQFs<}o(7M^I3oN_7KB=I9bv#3wu{`{Ztjaw` zRAg_d`4+kFZQ~fulO}qI#0y{A1osRR c :call SyntasticCheckCoffeescript() """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" let g:gitgutter_enabled=0 nnoremap d :GitGutterToggle + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Vim-Session +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +let g:session_directory="~/tmp" +let g:session_autoload="no" +