Commits

Stefan Göbel  committed 0a8c9a2

Version 0.5

* rewrite of most of the plugin's code and documentation
* added multiple new options:
* g:vimyaSocket
* g:vimyaTimeout
* g:vimyaForceRefresh
* g:vimyaRefreshWait
* g:vimyaSplitBelow
* added support for Unix domain sockets
* renamed sendBufferToMaya() to vimyaRun()
* added multiple new functions:
* vimyaSend()
* vimyaOpenLog()
* vimyaRefreshLog()
* vimyaResetLog()
* added docstrings to all Python functions
* added multiple Ex commands:
* :VimyaRun
* :VimyaBuffer
* :VimyaCommand
* :VimyaSend
* added proper escaping of all file names
* added testsrv script for basic testing without Maya

  • Participants
  • Parent commits 921691c

Comments (0)

Files changed (4)

 PLUGIN  = vimya
-VERSION = 0.4
+VERSION = 0.5
 
 SOURCE  = plugin/${PLUGIN}.vim
 SOURCE += doc/${PLUGIN}.txt
 	mv ${PLUGIN}.vba ${PLUGIN}-${VERSION}.vba
 
 ${PLUGIN}-${VERSION}.zip: ${SOURCE} ${EXTRA}
-	7z a -tzip ${PLUGIN}-${VERSION}.zip ../${PLUGIN} -mx=9 \
-		-xr'!*.vba' -xr'!*.zip' -xr'!Makefile' -xr'!.*'
+	mkdir ${PLUGIN}-${VERSION}
+	cp --parents ${SOURCE} ${EXTRA} ${PLUGIN}-${VERSION}
+	7z a -tzip ${PLUGIN}-${VERSION}.zip ${PLUGIN}-${VERSION} -mx=9
+	rm -rf ${PLUGIN}-${VERSION}
 
 clean:
 	rm ${PLUGIN}-${VERSION}.vba

File doc/vimya.txt

-*vimya.txt*               Vimya - Send buffer contents to Autodesk Maya
+*vimya.txt*           Vimya 0.5 - Send buffer contents to Autodesk Maya
 
 =======================================================================
 
-Contents                                                        *vimya*
+0. Contents                                                     *vimya*
 
-        1. Overview                     |vimya-overview|
-        2. Requirements                 |vimya-requirements|
-        3. Installation                 |vimya-installation|
-        4. Configuration                |vimya-configuration|
-        5. Usage                        |vimya-usage|
-        6. Additional Information       |vimya-info|
-        7. Changelog                    |vimya-changelog|
-        8. License                      |vimya-license|
+    1. Overview                                   |vimya-overview|
+    2. Requirements                               |vimya-requirements|
+    3. Installation                               |vimya-installation|
+    4. Preparing Maya                             |vimya-maya|
+    5. Configuration Options                      |vimya-configuration|
+    6. Functions                                  |vimya-functions|
+    7. Key Mappings                               |vimya-mappings|
+    8. Ex Commands                                |vimya-commands|
+    9. Additional Information                     |vimya-info|
+   10. Changelog                                  |vimya-changelog|
+   11. License                                    |vimya-license|
 
 =======================================================================
 
 1. Overview                                            *vimya-overview*
 
-   Vimya can be used to execute the contents of a Vim buffer, the
-   current visual selection, or a single command in Autodesk Maya. The
-   plugin will save the command(s) to be executed in a temporary file
-   and tell Maya via the command port to source this file. Both MEL and
-   Python scripts are supported, Maya's log can optionally be opened in
-   a separate preview window or tab in Vim.
+   Vimya is plugin for the Vim editor that may be used to execute the
+   contents of a Vim buffer, the current |visual-mode| selection, or a
+   single command in Autodesk Maya.
+
+   The plugin will save the command(s) to be executed in a temporary
+   file and tell Maya via the command port to source this file. Both
+   MEL and Python scripts are supported, Maya's log can optionally be
+   opened in a separate preview window or tab in Vim.
 
 =======================================================================
 
 
    Python support is required for this plugin to run, check with
 >
-        vim --version
+     vim --version
+<
+   or from within Vim with
+>
+     :echo has ('python')
 <
    Additionally, you may install the 'Tail Bundle' plugin, download it
    from
 >
-        http://www.vim.org/scripts/script.php?script_id=1714
+     http://www.vim.org/scripts/script.php?script_id=1714
 <
    and install it before using Vimya to view the output of Maya (i.e.
    the stuff printed in the script editor) in Vim. You do not need to
 
 3. Installation                                    *vimya-installation*
 
-   When using the vimball (recommended, but requires the 'Vimball'
-   plugin), all you need to do is open the file and source it:
+   Using the Vimball archive is recommended. It requires the 'Vimball'
+   plugin, get it at:
+>
+     http://www.vim.org/scripts/script.php?script_id=1502
+<
+   All you need to do is open the file in Vim:
+>
+     $ vim vimya-0.5.vba
+<
+   and source it:
 >
-        vim vimya-0.4.vba
-        :so %
+     :so %
 <
-   When using the archive: Extract the contents and copy the files in
-   the 'doc' and 'plugin' subfolders to the appropriate folders in your
-   runtime path. Usually this is '~/.vim/' (see |'runtime-path'| and
-   |add-global-plugin| for details). You may need to create the folders
-   'doc' and 'plugin' if they do not exist.
+   When using the Zip archive: Extract the contents and copy the files
+   in the 'doc' and 'plugin' subfolders to the appropriate folders in
+   your runtime path. Usually this is '~/.vim/' (see |'runtimepath'|
+   and |add-global-plugin| for details). You may need to create the
+   folders 'doc' and 'plugin' if they do not exist.
+
+   You may also install Vimya directly from the Git repository if you
+   use 'Pathogen', which you can get here:
+>
+     http://www.vim.org/scripts/script.php?script_id=2332
+<
+   With 'Pathogen' installed, you just need to clone the Vimya Git
+   repository to the bundle directory in your runtime path:
+>
+     git clone https://bitbucket.org/goeb/vimya.git ~/.vim/bundle/vimya
+<
+   This also allows you to update Vimya by pulling the latest version
+   with Git.
 
    When all files are in place, start Vim and run the |:helptags|
-   command to update the tags index.
+   command to update the tags index (this is not necessary if you use
+   the Vimball method).
+
+   See |vimya-configuration|, |vimya-functions|, |vimya-mappings| and
+   |vimya-commands| for details on how to setup and use this plugin.
+
+=======================================================================
+
+4. Preparing Maya                                          *vimya-maya*
 
-   See |vimya-configuration| and |vimya-usage| for details on how to
-   setup and use this plugin.
+   You need to open a command port in Maya that will be used by Vimya
+   to send the required commands. To open port 12345 (Vimya's default
+   port) you may copy the following command to your userSetup.mel file:
+>
+     if (! `commandPort -q ":12345"`) commandPort -nr -n ":12345";
+<
+   Refer to the Maya documentation for more details. Note that Vimya
+   does not read anything from the socket, usage of the -noreturn (-nr)
+   option is recommended (it should work without it, though).
 
-   You also need to open a command port in Maya. To open port 12345
-   you may copy the following command to your userSetup.mel file:
+   On systems that support Unix domain sockets, these may be used for
+   communication:
 >
-        if (! `commandPort -q ":12345"`) commandPort -n ":12345";
+     if (! `commandPort -q "socket"`) commandPort -nr -n "socket";
 <
-   Refer to the Maya documentation for more details.
+   Again, please see the Maya documentation for details.
 
-   Note that only INET sockets are supported at the moment, this may be
-   A SECURITY RISK!
+   Do not set the -sourceType (-stp) option to 'python', even if you
+   want to send Python commands! Vimya will send the appropriate MEL
+   commands to run Python code if required.
+
+   Note that there is no authentication, opening a command port may be
+   A SECURITY RISK! This is especially true when INET sockets are used
+   instead of Unix domain sockets.
 
 =======================================================================
 
-4. Configuration                                  *vimya-configuration*
+5. Configuration Options                          *vimya-configuration*
 
    This plugin uses the following configuration variables, they can be
    set in your |.vimrc| file:
 
-   g:vimyaHost - string (default '127.0.0.1')
-        Specifies the address of the host to connect to.
-
-   g:vimyaPort - number (default 12345)
-        The port number Maya is listening on for connections. See the
-        short note above on |vimya-installation| and the Maya manual
-        for details.
-
-   g:vimyaDefaultFiletype - string (default 'python')
-        Vimya needs to know if the code that should be executed by Maya
-        is MEL or Python code. Usually this is determined by the
-        current filetype. If the filetype is not set, e.g. when a new
-        file is created, this default value is used. It must be set to
-        either 'mel' or 'python'.
-
-   g:vimyaShowLog - number (default 1)
-        If you have the 'Tail Bundle' plugin installed and you do not
-        want the Maya script editor log to be opened, set this variable
-        to 0.
-
-   g:vimyaTailCommand - string (default 'TabTail')
-        The Tail Bundle command used to open the log (if enabled, see
-        above). The default is 'TabTail' to open the log in a new tab.
-        Set it to 'Tail' if a non-tabbed preview window should be used. 
-
-   g:vimyaTempDir - string (default '')
-        You may set this to a directory name to change the location of
-        the temporary files. If it is an empty string (the default),
-        the system's default temporary path will be used, as determined
-        by Python's 'tempfile' library. See there for details.
+   *g:vimyaHost*                                            *vimyaHost*
+
+     Default: '127.0.0.1'
+
+     String that specifies the address of the host to connect to when
+     using an INET socket for communication.
+
+   *g:vimyaPort*                                            *vimyaPort*
+
+     Default: 12345
+
+     The port number Maya is listening on for connections when using an
+     INET socket. See |vimya-maya| and the Maya manual for details.
+
+   *g:vimyaSocket*                                        *vimyaSocket*
+
+     Default: ''
+
+     Path to the Unix domain socket to connect to. If this is set to an
+     empty string (the default) an INET connection will be used (as
+     sepcified by |g:vimyaHost| and |g:vimyaPort|). If this is set to a
+     non-empty string, the host and port settings will be ignored and a
+     connection to the specified Unix domain socket will be used. If
+     set, it must be the full (absolute) path name of the socket.
+
+   *g:vimyaTimeout*                                      *vimyaTimeout*
+
+     Default: 5.0
+
+     The timeout that will be used for the connection. If this is a
+     float value, it will be used as is, if it is set to an empty
+     string, timeout will be set to None. See the documentation of
+     Python's socket library for details on socket.settimeout().
+
+   *g:vimyaDefaultFiletype*                      *vimyaDefaultFiletype*
+
+     Default: 'python'
+
+     Vimya needs to know if the code that should be executed by Maya
+     is MEL or Python code. Usually this is determined by the current
+     buffer's |'filetype'|. If the file type is not set, e.g. when a
+     new file is created, this default value is used instead. It must
+     be set to either 'mel' or 'python'.
+
+   *g:vimyaTempDir*                                      *vimyaTempDir*
+
+     Default: ''
+
+     You may set this to a directory name to change the location of
+     the temporary files. If it is an empty string (the default), the
+     system's default temporary path will be used, as determined by
+     Python's tempfile library. See there for more details.
+
+   *g:vimyaShowLog*                                      *vimyaShowLog*
+
+     Default: 1
+
+     If you have the 'Tail Bundle' plugin installed and you do not want
+     the Maya script editor log to be opened, set this option to 0.
+
+   *g:vimyaTailCommand*                              *vimyaTailCommand*
+
+     Default: 'TabTail'
+
+     The 'Tail Bundle' command used to open the log (if enabled, see
+     above). The default is 'TabTail' to open the log in a new tab.
+     Set it to 'Tail' (or 'STail') if a non-tabbed preview window
+     should be used instead. Values other than 'TabTail', 'Tail' and
+     'STail' are invalid.
+
+   *g:vimyaSplitBelow*                                *vimyaSplitBelow*
+
+     Default: &splitbelow
+
+     If 'Tail' or 'STail' are used as |g:vimyaTailCommand|, this option
+     may be used to override the global |'splitbelow'| setting. The
+     default is the same as the global value. After opening the log
+     file the original setting will be restored.
+
+   *g:vimyaForceRefresh*                            *vimyaForceRefresh*
+
+     Default: 0
+
+     Setting this option to 1 will cause |vimyaRefreshLog()| to be
+     called at the end of the |vimyaRun()| (or |sendBufferToMaya()|)
+     function after all required commands have been sent to Maya. See
+     also |g:vimyaRefreshWait| below.
+
+   *g:vimyaRefreshWait*                              *vimyaRefreshWait*
+
+     Default: 2.0
+
+     If |g:vimyaForceRefresh| is enabled, wait this many seconds before
+     calling |vimyaRefreshLog()| after the commands have been sent.
 
    Example setting in your |.vimrc| file:
 >
-        let vimyaPort=54321
+     let g:vimyaPort=54321
 <
-   The plugin will create the following mappings unless you configure
-   your own mappings:
-
-        nnoremap <leader>sm :py sendBufferToMaya ()<cr>
-        vnoremap <leader>sm :py sendBufferToMaya ()<cr>
-        nnoremap <leader>sb :py sendBufferToMaya (True)<cr>
-        vnoremap <leader>sb :py sendBufferToMaya (True)<cr>
-
-   See |vimya-usage| below for details on these function.
+   Note that every option is (re)evaluated whenever it is required, so
+   changing an option during a session is supported.
 
 =======================================================================
 
-5. Usage                                                  *vimya-usage*
+6. Functions                                          *vimya-functions*
 
-   The Vimya plugin defines the following Python function for public
+   The Vimya plugin defines the following Python functions for public
    use:
+
+     |vimyaRun()|                                     |vimyaRun|
+     |vimyaSend()|                                    |vimyaSend|
+     |vimyaOpenLog()|                                 |vimyaOpenLog|
+     |vimyaRefreshLog()|                              |vimyaRefreshLog|
+     |vimyaResetLog()|                                |vimyaResetLog|
+
+   *sendBufferToMaya* (...)                        *sendBufferToMaya()*
+
+     Since Vimya version 0.5, the function sendBufferToMaya() is an
+     alias for the |vimyaRun()| function (see below), for backwards
+     compatibility. Its parameters and behaviour are exactly the same
+     as for |vimyaRun()|.
+
+   *vimyaRun* (forceBuffer = False, userCmd = None)        *vimyaRun()*
+
+     If you call this function without any parameters:
+>
+       :py vimyaRun ()
+<
+     the complete current buffer will be executed by Maya. The content
+     will be saved to a temporary file, and Vimya will send commands to
+     Maya's command port to source this file.
+
+     The current buffer's |'filetype'| must be set to either 'python'
+     or 'mel', or not set at all ('none'). If it is not set, the option
+     |g:vimyaDefaultFiletype| is used to determine the correct commands
+     to send. Other file types will cause an error message, no further
+     action will be performed in that case.
+
+     In visual mode, only the selected lines will be executed, unless
+     you set the forceBuffer parameter to True (it defaults to False):
+>
+       :py vimyaRun (forceBuffer = True)
+<
+     In that case the complete buffer will be executed.
+
+     Note: If a selection starts or ends in the middle of a line, the
+     complete line will be included!
+
+     If you explicitely specify a command with the userCmd parameter:
+>
+       :py vimyaRun (userCmd = "<some command>")
+<
+     the buffer content (and visual selection) is ignored, and only
+     this command is executed instead. Obviously, the forceBuffer
+     parameter is also ignored in this case. Note that the comamnd will
+     still be written to a temporary file first, and then this file
+     will be sourced. The current |'filetype'| also determines the type
+     of the command, as described above.
+
+     If the 'Tail Bundle' plugin is installed, the output of Maya will
+     be written to a temporary log file and this file will be opened in
+     a new preview tab (or window, see the |g:vimyaTailCommand| option)
+     in Vim, unless this behaviour is disabled by setting the variable
+     |g:vimyaShowLog| to 0. See |:TabTail| or |:Tail| if installed. See
+     |vimyaResetLog()| and |vimyaOpenLog()| for more details. Also, if
+     enabled, after sending the commands to Maya the log buffer will be
+     refreshed automatically, see the options |g:vimyaForceRefresh| and
+     |g:vimyaRefreshWait| and the |vimyaRefreshLog()| function for more
+     details.
+
+     All temporary files will be deleted automatically. The files
+     sourced by Maya will be deleted by Maya itself: after the command
+     to source the file the
 >
-        sendBufferToMaya (forceBuffer = False, userCmd = None)
+       sysFile -delete <temporary file>
 <
-   If you call this function with
+     MEL command is sent. The temporary logfiles will be deleted when
+     Vim is closed, do not delete any of them manually before you close
+     Vim. The location of the temporary files depends on your system,
+     unless the option |g:vimyaTempDir| is set to override the default.
+     See the Python documentation on tempfile.mkstemp() for details.
+
+     Note: Since version 0.2 the plugin keeps track of all temporary
+     files and tries to delete them when leaving Vim, since deleting
+     with Maya's own commands did not always work reliably.
+
+     The function |vimyaSend()| is used to send all required commands,
+     please see there for details on the connection settings.
+
+   *vimyaSend* (commands)                                 *vimyaSend()*
+
+     This function will open a connection to Maya's command port and
+     send the specified commands. The commands parameter must be a list
+     of one or more strings. A newline will be appended to all commands
+     before they are sent. Commands will be sent in the order they
+     appear in the list.
+
+     The options |g:vimyaHost|, |g:vimyaPort|, |g:vimyaSocket| and
+     |g:vimyaTimeout| specify the parameters of the connection. Please
+     see their respective documentation for details.
+
+     An error message will be displayed if something goes wrong. After
+     an error, no attempt will be made to send any more commands from
+     the list.
+
+     Note: This function sends all specified commands as they are
+     (with the exception of the added newline). The |'filetype'| is
+     ignored, no temporary files are created, and this function will
+     not open any log file.
+
+   *vimyaOpenLog* ()                                   *vimyaOpenLog()*
+
+     This function will open the currently used log file, using the
+     configured 'Tail Bundle' command, unless this is disabled.
+
+     The options |g:vimyaShowLog|, |g:vimyaTailCommand| and
+     |g:vimyaSplitBelow| may be used to change the behaviour.
+
+     If no log file is set, or the file is already opened in a window,
+     this function does nothing. If |g:vimyaTailCommand| is not set to
+     'TabTail', any preview window currently opened in the active tab
+     will be closed.
+
+   *vimyaRefreshLog* ()                             *vimyaRefreshLog()*
+
+     This function will update the log file if it is currently opened
+     in a preview window. If the window of the log file is not located
+     in the current tab, it will switch to the window's tab.
+
+     If the log file's window is a regular window, no attempt to
+     refresh it will be made (the tab will be switched if required,
+     though). Does nothing if no log file is currently set. If a log
+     file is set, but not opened in any window, an error message will
+     be printed.
+
+   *vimyaResetLog* ()                                 *vimyaResetLog()*
+
+     This function will create a new temporary file and instruct Maya
+     to use it as its log file.
+
+     If a log file is already set, the command to close all (!) log
+     files:
 >
-        :py sendBufferToMaya ()
+       cmdFileOutput -ca
 <
-   the code to be executed by Maya will be saved to a temporary file,
-   and Vimya will send the appropriate commands to Maya to source this
-   file.
-
-   The current filetype - |ft| - must be set to either 'mel' or
-   'python', or not set at all ('none'). If it is not set, the variable
-   'g:vimyaDefaultFileType' is used to determine the correct commands
-   to send to Maya. Other filetypes will cause an error message and no
-   further actions to be performed.
-
-   In visual mode, only the selected lines will be used unless you use
-   the
+     will be sent to Maya first, then the new file is set.
+
+     The log file will be opened in Vim if enabled, see
+     |vimyaOpenLog()| for details.
+
+     If |g:vimyaShowLog| is not enabled (or the 'Tail Bundle' plugin is
+     not available), no new log file will be created (if a log file is
+     set, it will still be closed, though).
+
+   Note that help for all these functions can also be accessed the
+   Python way by running:
 >
-        :py sendBufferToMaya (True)
+     :py help (<function>)
 <
-   command, in that case the complete current buffer will be used. The
-   complete buffer is also used when not in visual mode. Important: If
-   a selection starts or ends in the middle of a line, this complete
-   line will be executed!
+   It is suggested that you map the functions you need to keyboard
+   shortcuts, the default |vimya-mappings| are described below. There
+   are also some Ex commands available to call some of the functions,
+   see |vimya-commands|.
+
+=======================================================================
 
-   If you explicitely specify a command, i.e.
+7. Key Mappings                                        *vimya-mappings*
+
+   The Vimya plugin will create the following mappings unless you
+   configure your own mappings:
 >
-        :py sendBufferToMaya (userCmd = "<some command>")
+     nnoremap <leader>sm :py vimyaRun ()<cr>
+     vnoremap <leader>sm :py vimyaRun ()<cr>
+     nnoremap <leader>sb :py vimyaRun (forceBuffer = True)<cr>
+     vnoremap <leader>sb :py vimyaRun (forceBuffer = True)<cr>
 <
-   the buffer content (and visual selection) is ignored, and this
-   command is used instead. Obviously, the forceBuffer parameter is
-   also ignored in this case. Note that the comamnd will still be
-   written to the temporary file first, and then this file will be
-   sourced.
-
-   It is suggested to map the commands you need to keyboard shortcuts,
-   the default mappings are shown above. If you set up your own
-   mappings, no default mappings will be created. See |key-mapping| for
-   details. (Note: If you create one mapping for this function, you
-   need to create the other mappings even if you want them to be the
-   defaults, else they will not be available!)
-
-   If the 'Tail Bundle' plugin is installed, the output of Maya will be
-   written to a temporary log file and this file will be opened in a
-   new preview tab (or window, see the 'g:vimyaTailCommand' option) in
-   Vim, unless this behaviour is disabled by setting the variable
-   'g:vimyaShowLog' to 0. See |:TabTail| or |:Tail| if installed.
-
-   All temporary files are deleted automatically. The files sourced by
-   Maya will be deleted by Maya itself: after the command to source the
-   file the
+   See |vimya-functions| above for details on these function. The
+   mappings are available in normal and visual mode.
+
+   Note that if you create any custom mapping that contains either the
 >
-        sysFile -delete [temporary file]
+     :py vimyaRun
 <
-   MEL command is sent. The temporary logfile will be deleted when Vim
-   is closed, do not delete it manually before you close Vim. The
-   location of the temporary files depends on your system, unless the
-   option 'g:vimyaTempDir' is set to override the default. See the
-   Python documentation on 'tempfile.mkstemp' for details.
-
-   Note: Since version 0.2 the plugin keeps track of all temporary
-   files and tries to delete them when leaving Vim, since deleting
-   with Maya's own commands did not always work. Additionally, when
-   leaving Vim the command
+   or the
 >
-        cmdFileOutput -closeAll
+     :py sendBufferToMaya
 <
-   is sent to Maya, which will close all open log files, before the
-   plugin tries to delete the log file.
+   command the default mappings shown above will not be created!
 
-   The timeout for the communication with Maya is set to 5 seconds,
-   which should be enough for connections to the localhost or to
-   machines in the LAN, and there is currently no option to change
-   this. If you need a higher value, modify the plugin's source code.
-   You may file a bug report in this case, maybe I will add an option.
+   See |key-mapping| for details on creating custom key mappings.
 
 =======================================================================
 
-6. Additional Information                                  *vimya-info*
+8. Ex Commands                                         *vimya-commands*
 
-   See Vimya's page in the scripts section of the official Vim homepage
-   for more information, including links to bug tracker etc.:
+   The following commands are defined by Vimya:
+
+     :VimyaRun                                          |:VimyaRun|
+     :VimyaBuffer                                       |:VimyaBuffer|
+     :VimyaCommand                                      |:VimyaCommand|
+     :VimyaSend                                         |:VimyaSend|
+
+   *:VimyaRun*
+
+     Calls the |vimyaRun()| function without any parameters. The
+     command itself does not expect any parameters.
+
+   *:VimyaBuffer*
+
+     Calls the |vimyaRun()| function with the forceBuffer parameter set
+     to True. The command itself does not expect any parameters.
+
+   *:VimyaCommand* <parameters>
+
+     Calls the |vimyaRun()| function with the userCmd parameter set to
+     the parameters of the command.
+
+     Parameters must not be quoted as a whole, Vim will do that.
+     However, individual parameters of the command to be sent must be
+     quoted as required by MEL or Python! All parameters will be
+     concatenated to one single string.
+
+     For example (assuming Python is used for commands):
+>
+       :VimyaCommand print "a" + "b"
+<
+     will result in the function call
+>
+       vimyaRun (userCmd = "print \"a\" + \"b\"")
+<
+     and this will eventually print the string "ab" in Maya's script
+     output. Also see |vimyaRun()| for more details.
+
+   *:VimyaSend* <parameters>
+
+     Works like |:VimyaCommand|, but instead of using |vimyaRun()| the
+     command will be sent using the |vimyaSend()| function.
+
+     Please see the notes on parameter quoting and the example for
+     |:VimyaCommand|. These notes also apply to :VimyaSend.
+
+     The string built from the command's parameters will be the one
+     (and only) element of |vimyaSend|'s commands parameter.
+
+     For example (again, assuming Python is used for commands):
+>
+       :VimyaSend print "a" + "b"
+<
+     will result in the function call
 >
-        http://www.vim.org/scripts/script.php?script_id=2626
+       vimyaSend (["print \"a\" + \"b\""])
 <
-   Feel free to contact the author for any questions regarding this
-   plugin, for bug reports, suggestions etc.
+   Commands for the other available functions are not defined, but you
+   can easily do this in you |.vimrc| file if required.
 
 =======================================================================
 
-7. Changelog                                          *vimya-changelog*
+9. Additional Information                                  *vimya-info*
+
+   See Vimya's page in the scripts section of the official Vim homepage
+   for more information, including links to the bug tracker etc.:
+>
+     http://www.vim.org/scripts/script.php?script_id=2626
+<
+   The Git repository is hosted at Bitbucket:
+>
+     https://bitbucket.org/goeb/vimya/
+<
+   Feel free to contact the author for any questions, suggestions etc.
+   regarding this plugin by mail:
+>
+     vimya /at/ subtype /dot/ de
+<
+
+=======================================================================
 
+10. Changelog                                         *vimya-changelog*
+
+   2014/05/22   * rewrite of most of the plugin's code and most of the
+                  documentation
+                * added options g:vimyaSocket, g:vimyaTimeout,
+                  g:vimyaForceRefresh, g:vimyaRefreshWait and
+                  g:vimyaSplitBelow
+                * added support for Unix domain sockets
+                * renamed sendBufferToMaya() to vimyaRun() (the former
+                  is still available for backwards compatibility)
+                * added public functions vimyaSend(), vimyaOpenLog(),
+                  vimyaRefreshLog() and vimyaResetLog()
+                * added docstrings to all Python functions
+                * added Ex commands :VimyaRun, :VimyaBuffer, :VimyaSend
+                  and :VimyaCommand
+                * fixed some issues that could probably cause the log
+                  features not to work properly for certain file names
+                * changed version number to 0.5
+                * thanks to Talha Ahmed for suggestions and testing
    2014/02/11   * added the vimyaTempDir and vimyaTailCommand options,
                   thanks to Claude Ronin
                 * minor updates to the documentation
 
 =======================================================================
 
-8. License                                              *vimya-license*
+11. License                                             *vimya-license*
 
 Copyright 2009, 2013-2014 Stefan Goebel.
 

File plugin/vimya.vim

 """
 "
-" Coypright 2009, 2013-2014 Stefan Goebel.
+" Coypright 2009, 2013-2014 Stefan Goebel - <vimya /at/ subtype /dot/ de>.
 "
-" This program is free software: you can redistribute it and/or modify it under
-" the terms of the GNU General Public License as published by the Free Software
-" Foundation, either version 3 of the License, or (at your option) any later
-" version.
+" This program is free software: you can redistribute it and/or modify it under the terms of the
+" GNU General Public License as published by the Free Software Foundation, either version 3 of the
+" License, or (at your option) any later version.
 "
-" This program is distributed in the hope that it will be useful, but WITHOUT
-" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-" FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
-" details.
+" This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+" even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+" General Public License for more details.
 "
-" You should have received a copy of the GNU General Public License along with
-" this program. If not, see <http://www.gnu.org/licenses/>.
+" You should have received a copy of the GNU General Public License along with this program. If
+" not, see <http://www.gnu.org/licenses/>.
 "
 """
 
 """
 "
-" Vimya 0.4 - Execute buffer contents as MEL or Python scripts in Autodesk Maya
+" Vimya 0.5 - Execute buffer contents as MEL or Python scripts in Autodesk Maya.
 "
-" Help is available in doc/vimya.txt or from within Vim with :help vimya.
+" Help is available in doc/vimya.txt or from within Vim:
+"
+"   :help vimya
+"
+" Help for all the Python functions can also be accessed in Vim the Python way:
+"
+"   :py help (<function>)
 "
 """
 
-if exists ('g:loadedVimya') || &cp || ! has ('python')
+if exists ('g:vimyaLoaded') || &compatible || ! has ('python')
     finish
 endif
-let g:loadedVimya = '0.4'
+let g:vimyaLoaded = '0.5'
 
 """
 " Configuration variables:
 """
 
-if ! exists ('g:vimyaPort')
-    let g:vimyaPort = 12345
-endif
-
-if ! exists ('g:vimyaHost')
-    let g:vimyaHost = '127.0.0.1'
-endif
-
-if ! exists ('g:vimyaDefaultFiletype')
-    let g:vimyaDefaultFiletype = 'python'
-endif
-
-if ! exists ('g:vimyaShowLog')
-    let g:vimyaShowLog = 1
-endif
+function VimyaSetConfig (name, default)
+    if ! exists ('g:vimya' . a:name)
+        let {'g:vimya' . a:name} = a:default
+    endif
+endfunction
+
+call VimyaSetConfig ( 'DefaultFiletype',  'python'    )
+call VimyaSetConfig ( 'ForceRefresh',     0           )
+call VimyaSetConfig ( 'Host',             '127.0.0.1' )
+call VimyaSetConfig ( 'Port',             12345       )
+call VimyaSetConfig ( 'RefreshWait',      2.0         )
+call VimyaSetConfig ( 'ShowLog',          1           )
+call VimyaSetConfig ( 'Socket',           ''          )
+call VimyaSetConfig ( 'SplitBelow',       &splitbelow )
+call VimyaSetConfig ( 'TailCommand',      'TabTail'   )
+call VimyaSetConfig ( 'TempDir',          ''          )
+call VimyaSetConfig ( 'Timeout',          5.0         )
 
-if ! exists ('g:vimyaTempDir')
-    let g:vimyaTempDir = ''
-endif
+"""
+" Mappings:
+"""
 
-if ! exists ('g:vimyaTailCommand')
-    let g:vimyaTailCommand = 'TabTail'
+if ! hasmapto (':py sendBufferToMaya') && ! hasmapto (':py vimyaRun')
+    nnoremap <leader>sm :py vimyaRun ()<cr>
+    vnoremap <leader>sm :py vimyaRun ()<cr>
+    nnoremap <leader>sb :py vimyaRun (forceBuffer = True)<cr>
+    vnoremap <leader>sb :py vimyaRun (forceBuffer = True)<cr>
 endif
 
 """
-" Mappings:
+" Commands:
 """
 
-if ! hasmapto ('sendBufferToMaya')
-    nnoremap <leader>sm :py sendBufferToMaya ()<cr>
-    vnoremap <leader>sm :py sendBufferToMaya ()<cr>
-    nnoremap <leader>sb :py sendBufferToMaya (True)<cr>
-    vnoremap <leader>sb :py sendBufferToMaya (True)<cr>
-endif
+command -nargs=0 VimyaRun     :py vimyaRun  ()
+command -nargs=0 VimyaBuffer  :py vimyaRun  (forceBuffer = True    )
+command -nargs=1 VimyaCommand :py vimyaRun  (userCmd     = <q-args>)
+command -nargs=1 VimyaSend    :py vimyaSend ([<q-args>]            )
 
 """
 " Main stuff (most of it is Python):
 """
 
-let g:vimyaUseTail = 0
+let g:vimyaTailAvailable = 0
 if exists ('g:Tail_Loaded')
-    let vimyaUseTail = 1
+    let g:vimyaTailAvailable = 1
 endif
 
-autocmd VimLeavePre * py __vimyaRemoveLog ()
+autocmd VimLeavePre * py __vimyaRemoveTempFiles ()
 
 python << EOP
 
 import os
+import platform
 import socket
 import tempfile
+import time
 import vim
 
-logPath   = ''
-setLog    = 0
-tempFiles = []
-
-# __vimyaRemoveLog ():
+# Global variables:
 #
-# If a logfile was written, delete it. Automatically executed when leaving Vim.
-# Also, if some of the temporary file are left on disk, we delete them.
+#   __vimyaLogPath   - If not empty, path of the log file currently used by Maya.
+#   __vimyaTempFiles - Contains all the temporary files created (log files, MEL/Python files).
 
-def __vimyaRemoveLog ():
-    global logPath
-    if logPath != '':
-        __vimyaCloseLog ()
-        try:
-            os.unlink (logPath)
-        except:
-            pass
-    for file in tempFiles:
-        try:
-            os.unlink (file)
-        except:
-            pass
+__vimyaLogPath   = ''
+__vimyaTempFiles = []
 
-# __vimyaCloseLog ():
-#
-# Issues a `cmdFileOutput -closeAll` command to close the log file.
+def __vimyaRemoveTempFiles ():
 
-def __vimyaCloseLog ():
-    host = vim.eval ('g:vimyaHost')
-    port = int (vim.eval ('g:vimyaPort'))
-    try:
-        connection = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
-        connection.settimeout (5)
-        connection.connect ((host, port))
-        connection.send ("cmdFileOutput -ca;\n")
-        connection.close ()
-    except:
-        return __vimyaErrorMsg ('Could not close the log file.')
-    return True
+    """Remove all temporary files.
 
-# errorMsg (message = <string>):
-#
-# Print the error message given by <string> with the appropriate highlighting.
-# Returns always False.
+    __vimyaRemoveTempFiles () : None
 
-def __vimyaErrorMsg (message):
-    vim.command ('echohl ErrorMsg')
-    vim.command ("echo \"%s\"" % message )
-    vim.command ('echohl None')
-    return False
+    This function will be called automatically when leaving Vim. It will try to delete all the
+    temporary files created during the session. There is no error handling, if deleting a file
+    fails, the file will be left on disk.
 
-# sendBufferToMaya (forceBuffer = False, userCmd = None):
-#
-# If userCmd is not specified, saves the buffer (or a part of it) to a temp
-# file and instructs Maya to source this file. In visual mode only the selected
-# lines are used, else the complete buffer. In visual mode, forceBuffer may be
-# set to True to force executing the complete buffer. If selection starts (or
-# ends) in the middle of a line, the complete line is included! If userCmd is
-# specified, this command will be written to the file sourced by Maya, and the
-# buffer content will be ignored. Returns False if an error occured, else True.
+    If a log file is set this function will try to close it first, see __vimyaStopLogging().
 
-def sendBufferToMaya (forceBuffer = False, userCmd = None):
+    This function does not return anything.
+    """
 
-    global logPath, setLog, tempFiles
+    global __vimyaLogPath, __vimyaTempFiles
 
-    type        = vim.eval ('&g:ft')
-    defaultType = vim.eval ('g:vimyaDefaultFiletype')
-    host        = vim.eval ('g:vimyaHost')
-    tempDir     = vim.eval ('g:vimyaTempDir')
-    tailCommand = vim.eval ('g:vimyaTailCommand')
-    port        = int (vim.eval ('g:vimyaPort'))
-    tail        = int (vim.eval ('g:vimyaUseTail'))
-    showLog     = int (vim.eval ('g:vimyaShowLog'))
-
-    if tempDir:
-        tempfile.tempdir = tempDir
+    if __vimyaLogPath != '':
+        __vimyaStopLogging ()
+
+    for tempFile in __vimyaTempFiles:
+        if os.path.isfile (tempFile):
+            try:
+                os.unlink (tempFile)
+            except:
+                pass
+
+def __vimyaStopLogging ():
+
+    """Tell Maya to stop logging and close all open log files.
+
+    __vimyaStopLogging () : bool
+
+    If a log file is currently set, this function will send the `cmdFileOutput -closeAll` command
+    to Maya, causing all (!) open log files to be closed. The __vimyaLogPath variable will be set
+    to an empty string if the log file could be closed successfully, its original value will be
+    added to the __vimyaTempFiles list for clean up on exit.
+
+    If the connection fails, an error message will be shown and the return value will be False,
+    else this function returns True. If no log file has been set, this function does nothing and
+    returns True.
+    """
+
+    global __vimyaLogPath, __vimyaTempFiles
+
+    if __vimyaLogPath == '':
+        return True
+
+    if vimyaSend (['cmdFileOutput -ca;']) == 1:
+        __vimyaTempFiles.append (__vimyaLogPath)
+        __vimyaLogPath = ''
+        return True
     else:
-        tempfile.tempdir = None
+        return __vimyaError ('Could not close the log file.')
 
-    if type != '' and type != 'python' and type != 'mel':
-        return __vimyaErrorMsg (
-                "Error: Supported filetypes: 'python', 'mel', None."
-            )
+def __vimyaError (message):
 
-    if logPath == '' and tail == 1 and showLog == 1:
-        (logHandle, logPath) = tempfile.mkstemp (
-                suffix = '.log', prefix = 'vimya.', text = 1
-            )
-        setLog = 1
+    """Print an error message.
 
-    (tmpHandle, tmpPath) = tempfile.mkstemp (
-            suffix = '.py', prefix = 'vimya.', text = 1
-        )
-    tempFiles.append (tmpPath)
+    __vimyaError (message) : False
 
-    if userCmd:
-        os.write (tmpHandle, "%s\n" % userCmd)
+    This function will print the error message in Vim's message area, using the appropriate
+    error highlighting.
+
+    It will always return False.
+    """
+
+    vim.command ('echohl ErrorMsg | echo "%s" | echohl None' % __vimyaEscape (message, '\\"'))
+
+    return False
+
+def __vimyaEscape (string, characters):
+
+    """Escape specified characters in a string with backslash.
+
+    __vimyaEscape (string, characters) : str
+
+    Works like Vim's escape() function. Every occurrence of one of the characters in the characters
+    parameter inside the string will be replaced by '\' + character. The backslash itself has to be
+    included as the first character in the characters parameter if it also should be escaped!
+
+    Returns the resulting string.
+    """
+
+    for character in characters:
+        string = string.replace (character, '\\%s' % character)
+
+    return string
+
+def __vimyaFilenameEscape (filename):
+
+    """Apply Vim's fnameescape() function to a string.
+
+    __vimyaFilenameEscape (string) : str
+
+    This function may be used to apply Vim's fnameescape() function to the supplied parameter.
+
+    Returns the escaped string.
+    """
+
+    return vim.eval ('fnameescape ("%s")' % __vimyaEscape (filename, '\\"'))
+
+def __vimyaFixPath (filename):
+
+    """Replace all backslashes in the file name with slashes on Windows platforms.
+
+    __vimyaFixPath (filename) : str
+
+    Replaces all backslashes in the file name with slashes on Windows platforms.
+
+    Returns the resulting string.
+    """
+
+    if platform.system () == 'Windows':
+        return filename.replace ('\\', '/')
     else:
-        vStart = vim.current.buffer.mark ('<')
-        if (vStart is None) or (forceBuffer):
-            for line in vim.current.buffer:
-                os.write (tmpHandle, "%s\n" % line)
+        return filename
+
+def __vimyaFindLog ():
+
+    """Find the buffer and tab that contains the Maya log.
+
+    __vimyaFindLog () : (int, int)
+
+    If a Maya log file is currently set, this function will return the number of the tab page and
+    the buffer number in which this log file is opened. Note: Searching will stop on first match!
+    There is no convenient way to check if a window is a preview window without switching tabs, so
+    this is not checked, the buffer found may be a regular window!
+
+    Returns a tuple: (tabNumber, bufferNumber). If the log file is not set or not opened in any
+    buffer, this function returns the tuple (0, 0). If there is a buffer for the log file, but it
+    is not opened in any window (and thus in no tab), the return value will be (0, bufferNumber).
+    """
+
+    global __vimyaLogPath
+
+    if __vimyaLogPath != '':
+        bufferIndex  = int (vim.eval ('bufnr     ("%s")' % __vimyaEscape (__vimyaLogPath, '\\"')))
+        bufferExists = int (vim.eval ('bufexists ( %d )' % int           (bufferIndex          )))
+        if bufferExists:
+            tabNum = int (vim.eval ('tabpagenr ("$")'))
+            for tabIndex in range (1, tabNum + 1):
+                tabBuffers = vim.eval ('tabpagebuflist (%d)' % tabIndex)
+                if str (bufferIndex) in tabBuffers:
+                    return (tabIndex, bufferIndex)
+        return (0, bufferIndex)
+
+    return (0, 0)
+
+def vimyaRefreshLog ():
+
+    """Update the log file in the preview window.
+
+    vimyaRefreshLog () : bool
+
+    This function will update the log file if it is currently opened in a preview window. If the
+    window of the log file is not located in the current tab, it will switch to the window's tab.
+    If the log file's window is a regular window, no attempt to refresh it will be made (the tab
+    will be switched, though). Does nothing if no log file is currently set.
+
+    If no log file is set, returns True. Same if a log file is set and opened in a preview window
+    (or a regular window). If a log file is set, but not opened in any window, returns False (and
+    prints an error message).
+    """
+
+    global __vimyaLogPath
+
+    if __vimyaLogPath != '':
+
+        (tabIndex, bufferIndex) = __vimyaFindLog ()
+
+        if not tabIndex:
+            return __vimyaError ('No log file window found.')
         else:
-            vEnd = vim.current.buffer.mark ('>')
-            for line in vim.current.buffer [vStart [0] - 1 : vEnd [0]]:
-                os.write (tmpHandle, "%s\n" % line)
-    os.close (tmpHandle)
+            vim.command ('tabnext %d' % tabIndex)
+            winIndex = int (vim.eval ('bufwinnr (%d)' % bufferIndex))
+            if winIndex > 0 and int (vim.eval ('getwinvar (%d, "&previewwindow")' % winIndex)):
+                vim.command ('call tail#Refresh ()')
+
+    return True
+
+def vimyaOpenLog ():
+
+    """Open the log file using the Tail Bundle plugin.
+
+    vimyaOpenLog () : bool
+
+    This function will open the currently used log file using the configured Tail Bundle command,
+    unless this is disabled. The options g:vimyaShowLog, g:vimyaTailCommand and g:vimyaSplitBelow
+    may be used to change the behaviour. If no log file is set, or the file is already opened in a
+    window, this function does nothing. If g:vimyaTailCommand is not 'TabTail', any preview window
+    currently opened will be closed.
+
+    Returns False in case of an error, True in all other cases.
+    """
+
+    global __vimyaLogPath
+
+    (tabIndex, bufferIndex) = __vimyaFindLog ()
+
+    if __vimyaLogPath != '' and tabIndex == 0:
+
+        splitBelowGlobal = int (vim.eval ('&splitbelow'       ))
+        splitBelowVimya  = int (vim.eval ('g:vimyaSplitBelow' ))
+        tailCommand      =      vim.eval ('g:vimyaTailCommand')
+
+        if tailCommand not in ('Tail', 'STail', 'TabTail'):
+            return __vimyaError ('Invalid value for g:vimyaTailCommand.')
+
+        success = False
+
+        try:
+            if tailCommand != 'TabTail':
+                vim.command ('pclose')
+            if splitBelowVimya:
+                vim.command ('set splitbelow')
+            else:
+                vim.command ('set nosplitbelow')
+            vim.command ('%s %s' % (tailCommand, __vimyaFilenameEscape (__vimyaLogPath)))
+            if tailCommand != 'TabTail':
+                vim.command ('wincmd p')
+            success = True
+        finally:
+            if splitBelowGlobal:
+                vim.command ('set splitbelow')
+            else:
+                vim.command ('set nosplitbelow')
+
+        return success
+
+    return True
+
+def vimyaResetLog ():
+
+    """(Re)set Maya's log file.
+
+    vimyaResetLog () : bool
+
+    This function will create a temporary file and instruct Maya to use it as its log file. If a
+    log file is already set, the command to close all (!) log files will be sent to Maya first,
+    then the new file is set. The log file will be opened in Vim if enabled, see vimyaOpenLog()
+    for details. If g:vimyaShowLog is not enabled (or the Tail Bundle plugin is not available), no
+    new log file will be created (if a log file should be set, it will still be closed, though).
+
+    Returns True on success, False in case of failure.
+    """
+
+    global __vimyaLogPath
+
+    if __vimyaLogPath != '':
+        if not __vimyaStopLogging ():
+            return False
+
+    tailAvailable = int (vim.eval ('g:vimyaTailAvailable'))
+    showLog       = int (vim.eval ('g:vimyaShowLog'      ))
+
+    if tailAvailable and showLog:
+
+        tempDir = vim.eval ('g:vimyaTempDir')
+        if tempDir != '':
+            tempfile.tempdir = tempDir
+        else:
+            tempfile.tempdir = None
+
+        (logHandle, logPath) = tempfile.mkstemp (suffix = '.log', prefix = 'vimya.', text = 1)
+        __vimyaLogPath = vim.eval ('expand ("%s")' % __vimyaEscape (logPath, '\\"'))
+
+        escapedLogPath = __vimyaEscape (__vimyaFixPath (__vimyaLogPath), '\\"')
+        if vimyaSend (['cmdFileOutput -o "%s";' % escapedLogPath]) != 1:
+            return False
+
+        return vimyaOpenLog ()
+
+    return True
+
+def vimyaSend (commands):
+
+    """Send commands to Maya's command port.
+
+    vimyaSend (commands) : int
+
+    This function will open a connection to Maya's command port (as configured), and send the
+    commands - which must be a list of one or more strings - to Maya. A newline will be appended
+    to every command automatically. Commands will be sent in the order they appear in the list.
+
+    Socket exceptions will be caught and an appropriate error message will be displayed. After an
+    exception, no attempt will be made to send any more commands from the list.
+
+    Returns the number of commands successfully sent to Maya.
+    """
+
+    socketPath =      vim.eval ('g:vimyaSocket' )
+    timeout    =      vim.eval ('g:vimyaTimeout')
+    host       =      vim.eval ('g:vimyaHost'   )
+    port       = int (vim.eval ('g:vimyaPort'   ))
 
     try:
-        connection = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
-        connection.settimeout (5)
-    except:
-        return __vimyaErrorMsg ('Could not create socket.')
-    try:
-        connection.connect ((host, port))
-    except:
-        return __vimyaErrorMsg ('Could not connect to the command port.')
+        if socketPath != '':
+            connection = socket.socket (socket.AF_UNIX, socket.SOCK_STREAM)
+        else:
+            connection = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
+        if timeout == '':
+            connection.settimeout (None)
+        else:
+            connection.settimeout (float (timeout))
+    except socket.error as e:
+        __vimyaError ('Could not initialize the socket: %s' % str (e))
+        return 0
 
     try:
+        if socketPath != '':
+            connection.connect (socketPath)
+        else:
+            connection.connect ((host, port))
+    except socket.error as e:
+        __vimyaError ('Could not connect to command port: %s' % str (e))
+        return 0
 
-        if setLog == 1:
-            connection.send (
-                    "cmdFileOutput -o \"%s\";\n" % logPath.replace ('\\', '/')
-                )
-            vim.command ("%s %s" % (tailCommand, logPath))
-            setLog = 0
-
-        connection.send ("commandEcho -state on -lineNumbers on;\n")
-        if type == 'python' or (type == '' and defaultType == 'python'):
-            connection.send (
-                    "python (\"execfile ('%s')\");\n" % \
-                        tmpPath.replace ('\\', '/')
-                )
-        elif (type == 'mel' or (type == '' and defaultType == 'mel')):
-            connection.send ("source \"%s\";\n" % tmpPath.replace ('\\', '/'))
-
-        connection.send ("commandEcho -state off -lineNumbers off;\n")
-        connection.send (
-                "sysFile -delete \"%s\";\n" % tmpPath.replace ('\\', '/')
-            )
-
-    except:
-        return __vimyaErrorMsg ('Could not send the commands to Maya.')
+    sent = 0
 
     try:
+        try:
+            for command in commands:
+                connection.send ('%s\n' % command)
+                sent = sent + 1
+        except socket.error as e:
+            __vimyaError ('Sending a command failed: %s' % str (e))
+    finally:
+        connection.shutdown (socket.SHUT_WR)
         connection.close ()
-    except:
-        return __vimyaErrorMsg ('Could not close socket.')
+
+    return sent
+
+def vimyaRun (forceBuffer = False, userCmd = None):
+
+    """Sent (partial) buffer contents or a single command to Maya's command port.
+
+    vimyaRun (forcedBuffer = False, userCmd = None) : bool
+
+    If userCmd is not specified, saves the current buffer to a temporary file and instructs Maya to
+    source this file. In visual mode only the selected lines are used (for partially selected lines
+    the complete line will be included). In visual mode, forceBuffer may be set to True to force
+    execution of the complete buffer.
+
+    If userCmd is specified, this command will be written to the file executed by Maya, and the
+    buffer content will be ignored.
+
+    In both cases, the current buffer's file type determines how the file is executed by Maya,
+    either as MEL or Python script. The file type must be either 'mel' or 'python', or not set at
+    all, in which case the 'g:vimyaDefaultFiletype' will be used.
+
+    If Maya's log is not yet set, it will be set and opened (if configured), depending on the
+    'g:vimyaShowLog' setting. See vimyaResetLog() for details. If 'g:vimyaForceRefresh' is set,
+    vimyaRefreshLog() will be called after waiting for 'g:vimyaRefreshWait' seconds after all
+    commands have been sent to Maya. Note that if a log file has been set and you close the log
+    window, it will not be opened automatically, you may use vimyaOpenLog() to open it again.
+
+    For backwards compatibility, this function is also available as sendBufferToMaya(). The usage
+    is exactly the same as for vimyaRun().
+
+    Returns False if an error occured, else True.
+    """
+
+    global __vimyaLogPath, __vimyaTempFiles
+
+    filetype = vim.eval ('&g:filetype')
+    if filetype not in ['', 'mel', 'python']:
+        return __vimyaError ('Error: Supported filetypes: "python", "mel", None.')
+
+    if __vimyaLogPath == '':
+        if not vimyaResetLog ():
+            return False
+
+    tempDir = vim.eval ('g:vimyaTempDir')
+    if tempDir != '':
+        tempfile.tempdir = tempDir
+    else:
+        tempfile.tempdir = None
+
+    (tmpHandle, tmpPath) = tempfile.mkstemp (suffix = '.tmp', prefix = 'vimya.', text = 1)
+    __vimyaTempFiles.append (tmpPath)
+
+    try:
+        if userCmd:
+            os.write (tmpHandle, '%s\n' % userCmd)
+        else:
+            vStart = vim.current.buffer.mark ('<')
+            if (vStart is None) or (forceBuffer):
+                for line in vim.current.buffer:
+                    os.write (tmpHandle, '%s\n' % line)
+            else:
+                vEnd = vim.current.buffer.mark ('>')
+                for line in vim.current.buffer [vStart [0] - 1 : vEnd [0]]:
+                    os.write (tmpHandle, '%s\n' % line)
+    finally:
+        os.close (tmpHandle)
+
+    commands = ['commandEcho -state on -lineNumbers on;']
+
+    defaultType = vim.eval ('g:vimyaDefaultFiletype')
+    escapedPath = __vimyaEscape (__vimyaFixPath (tmpPath), '\\"')
+
+    if filetype == 'python' or (filetype == '' and defaultType == 'python'):
+        commands.append ('python ("execfile (\\"%s\\")");' % escapedPath)
+    elif filetype == 'mel' or (filetype == '' and defaultType == 'mel'):
+        commands.append ('source "%s";' % escapedPath)
+
+    commands.append ('commandEcho -state off -lineNumbers off;')
+    commands.append ('sysFile -delete "%s";' % escapedPath)
+
+    sent = vimyaSend (commands)
+    if sent != len (commands):
+        return __vimyaError ('%d commands out of %d sent successfully.' % (sent, len (commands)))
+
+    refresh = int   (vim.eval ('g:vimyaForceRefresh'))
+    wait    = float (vim.eval ('g:vimyaRefreshWait' ))
+    if __vimyaLogPath != '' and refresh:
+        time.sleep (wait)
+        return vimyaRefreshLog ()
 
     return True
 
+# For backwards comapatibility, sendBufferToMaya() will be an alias for vimyaRun():
+
+sendBufferToMaya = vimyaRun
+
 EOP
 
-" vim: set et si nofoldenable ft=python sts=4 sw=4 tw=79 ts=4 fenc=utf8 :
+" vim: set et si nofoldenable ft=python sts=4 sw=4 tw=99 ts=4 fenc=utf8 :

File tools/testsrv

+#!/bin/bash
+
+# Usage: testsrv [<host> [<port>]]
+#    or: testsrv -s <socket>
+#
+# WARNING: Do not use this script unless you know what you're doing!
+#
+# The following MEL commands will be handled (only if useed exactly as shown!):
+#
+#  cmdFileOutput -o "<file>";    - set the current output file
+#  sysFile -delete "<file>";     - delete the file
+#  cmdFileOutput -ca;            - stop logging to the output file
+
+file=''
+host=${1:-127.0.0.1}
+port=${2:-12345}
+
+if [[ "$host" == "-s" ]] ; then
+   echo "Listening on $port..."
+   ncmd="ncat_UNIX"
+else
+   echo "Listening on $host:$port..."
+   ncmd="ncat_INET"
+fi
+
+ncat_INET() {
+   ncat -k -l "$host" "$port"
+}
+
+ncat_UNIX() {
+   ncat -k -l -U "$port"
+}
+
+$ncmd | while read command ; do
+
+   echo "$command"
+
+   case $command in
+      "cmdFileOutput -o "*)
+         file=$( sed 's/cmdFileOutput -o "\(.*\)";/\1/' <<<"$command" )
+         echo "# DEBUG: logging to file $file" >&2
+         ;;
+      "cmdFileOutput -ca;")
+         echo "# DEBUG: stop logging to file $file" >&2
+         file=''
+         ;;
+      "sysFile -delete "*)
+         temp=$( sed 's/sysFile -delete "\(.*\)";/\1/' <<<"$command" )
+         echo "# DEBUG: deleting file $temp" >&2
+         rm -f "$temp"
+         if [[ "$temp" == "$file" ]] ; then
+            echo "# DEBUG: stop logging to deleted file $file" >&2
+            file=''
+         fi
+         ;;
+   esac
+
+   if [[ -n "$file" ]] ; then
+      echo "$command" >>"$file"
+   fi
+
+done