├── .gitignore ├── CHANGES.md ├── LICENSE.md ├── Makefile ├── README.md ├── dev └── README.md ├── test ├── mockcat ├── mockvim ├── setup ├── test └── test_vimer ├── vimer └── vimer.cmd /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw? 2 | /coverage/ 3 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | 0.2.0 (2016-04-08) 5 | ------------------ 6 | 7 | - NEW: Open files in a specific GVim server with `-s` option. 8 | 9 | 10 | 0.1.0 (2016-01-05) 11 | ------------------ 12 | 13 | - NEW: Open files in new buffers in the same instance of GVim or MacVim. 14 | - NEW: Open files in new tab pages with `-t` option. 15 | - NEW: Read text from standard input with `-` argument. 16 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright (c) 2010-2016 Susam Pal 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: .FORCE 2 | sh test/test 3 | 4 | test_unix: 5 | bash test/test 6 | ksh test/test 7 | zsh test/test 8 | 9 | test_posix: 10 | dash test/test 11 | posh test/test 12 | yash test/test 13 | 14 | test_all: test_unix test_posix 15 | 16 | coverage: .FORCE 17 | rm -rf coverage 18 | kcov --exclude-path=test/test coverage test/test 19 | 20 | coveralls: 21 | rm -rf coverage 22 | kcov --coveralls-id=$$TRAVIS_JOB_ID --exclude-path=test/test coverage test/test 23 | 24 | clean: 25 | rm -rf coverage 26 | 27 | .FORCE: 28 | 29 | # vim: noet 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Vimer 2 | ===== 3 | 4 | Vimer is a convenience wrapper script to open files in an existing 5 | instance of GVim or MacVim. 6 | 7 | [![Download][SHIELD_WIN]][DOWNLOAD_WIN] 8 | [![Download][SHIELD_LIN]][DOWNLOAD_LIN] 9 | [![Build Status][BUILD_IMG]][BUILD_URL] 10 | [![Coverage Status][COVERAGE_IMG]][COVERAGE_URL] 11 | 12 | The Windows script has been tested on Windows 7 only. However, it 13 | should work fine on other recent versions of Windows too. 14 | 15 | The Linux/Mac script has been tested with [bash][], [ksh][] and 16 | [zsh][] on Debian and Mac as well as with [dash][], [posh][] and 17 | [yash][yash] on Debian. It should work fine on any POSIX compliant 18 | system with a POSIX compliant shell. 19 | 20 | [SHIELD_WIN]: https://img.shields.io/badge/download-vimer%2ecmd%20for%20Windows-brightgreen.svg 21 | [SHIELD_LIN]: https://img.shields.io/badge/download-vimer%20for%20Linux%2fMac-brightgreen.svg 22 | [DOWNLOAD_WIN]: https://github.com/susam/vimer/releases/download/0.2.0/vimer.cmd 23 | [DOWNLOAD_LIN]: https://github.com/susam/vimer/releases/download/0.2.0/vimer 24 | 25 | [BUILD_IMG]: https://travis-ci.org/susam/vimer.svg?branch=master 26 | [BUILD_URL]: https://travis-ci.org/susam/vimer 27 | [COVERAGE_IMG]: https://coveralls.io/repos/github/susam/vimer/badge.svg?branch=master 28 | [COVERAGE_URL]: https://coveralls.io/github/susam/vimer?branch=master 29 | 30 | [bash]: https://packages.debian.org/stable/bash 31 | [ksh]: https://packages.debian.org/stable/ksh 32 | [zsh]: https://packages.debian.org/stable/zsh 33 | [dash]: https://packages.debian.org/stable/dash 34 | [posh]: https://packages.debian.org/stable/posh 35 | [yash]: https://packages.debian.org/stable/yash 36 | 37 | 38 | Contents 39 | -------- 40 | 41 | * [Necessity](#necessity) 42 | * [Current Development Status](#current-development-status) 43 | * [Getting Started](#getting-started) 44 | * [Troubleshooting](#troubleshooting) 45 | * [Context Menu](#context-menu) 46 | * [Windows](#windows) 47 | * [Xfce on Linux](#xfce-on-linux) 48 | * [GNOME on Linux](#gnome-on-linux) 49 | * [Mac](#mac) 50 | * [License](#license) 51 | * [Support](#support) 52 | 53 | 54 | Necessity 55 | --------- 56 | 57 | This project was written to address the following needs. 58 | 59 | 1. Running `gvim foo.txt` on Windows or Linux, or `mvim foo.txt` on 60 | Mac, opens the file in a new GVim or MacVim window. Launching 61 | GVim or MacVim from the shell in this manner again and again can 62 | easily clutter the desktop with too many windows. Moreover, if 63 | the file being opened is already open in another instance of GVim 64 | or MacVim, the editor warns about an existing swap file and 65 | requires the user to take action for it. This can be distracting 66 | sometimes. 67 | 68 | Of course, one can open and edit all files from within a single 69 | GVim or MacVim instance with the editor commands such as `:e` or 70 | `:tabe` to avoid these problems, but it is still useful to be able 71 | to edit files from the shell, especially while navigating 72 | directories in the shell. 73 | 74 | Vimer offers a way to edit files from the shell such that every 75 | file being edited opens in a new buffer in the same instance of 76 | GVim or MacVim. If a file being opened is already open in GVim or 77 | MacVim, no warning occurs; instead the editor silently displays 78 | the specified file. 79 | 80 | 2. The problems discussed in the previous point can also be solved 81 | using a simple wrapper script on Windows, say, myvim.cmd. 82 | 83 | ```bat 84 | @echo off 85 | gvim --remote-silent %* 86 | ``` 87 | 88 | Or using alias on Linux. 89 | 90 | ```sh 91 | alias myvim="gvim --remote-silent" 92 | ``` 93 | 94 | Here is a similar alias for Mac. 95 | 96 | ```sh 97 | alias myvim="mvim --remote-silent" 98 | ``` 99 | 100 | But this solution is not without flaws. Of course, it takes care 101 | that a command like `myvim foo.txt bar.txt` opens both files in 102 | two buffers in the same instance of GVim or MacVim. However the 103 | following annoying behaviour occurs. 104 | 105 | - Running `myvim` without arguments leads to an error: `Argument 106 | missing after: "--remote-silent"`. 107 | 108 | - Trying to pipe standard output of one command into the 109 | standard input of GVim or MacVim with a command like `ls | 110 | myvim -` results in an empty buffer for a file named `-`. The 111 | reason for this is documented in the editor's documentation. 112 | Enter `:help remote` in the editor to read it. 113 | 114 | Vimer offers a litle more elaborate wrapper script that handles 115 | these special cases better. 116 | 117 | - `vimer foo.txt bar.txt` opens both files in the same instance 118 | of GVim or MacVim. 119 | 120 | - `vimer` launches a new instance of GVim or MacVim. 121 | 122 | - `ls | vimer -` shows the output of `ls` in an existing 123 | instance of GVim or MacVim if it exists. 124 | 125 | 3. Vim provides a context menu option called *Edit with Vim* that 126 | opens a file in a new buffer in an *existing* tab page in an 127 | existing instance of GVim. However, it doesn't provide a context 128 | menu option that opens a file in a *new* tab page in an existing 129 | instance of GVim. Vimer fills this gap by creating a context menu 130 | option for files called *Edit with GVim tab* that opens a file in 131 | a new tab page in an existing instance of GVim. This feature is 132 | available only for Windows. 133 | 134 | 135 | Current Development Status 136 | -------------------------- 137 | 138 | You might notice that this project has not received a new release for 139 | many years now. This is due to the following three reasons: 140 | 141 | - This project worked well for me as long as I used Vim actively. 142 | 143 | - I use Emacs as my primary computing environment these days. As a 144 | result I use this project only occassionally these days. When I 145 | do use Vim, this project works well for me. 146 | 147 | - In the initial few releases of this, I took great care to run the 148 | test suite in the [test/](test/) directory with various shells. I 149 | do not have the time and resources to perform such testing 150 | anymore. As a result, I am reluctant to make any changes to this 151 | project anymore. 152 | 153 | Due to the points mentioned above, I do not accept pull requests to 154 | this project. If this project works for you, that's great! However, 155 | if it does not, I hope you will be able to dive into the Vimer script 156 | that you use and update the script to suit your needs. 157 | 158 | Alternatively, you could also use Konfekt's fork of Vimer available at 159 | [github.com/konfekt/vimer](https://github.com/konfekt/vimer) which 160 | provides certain enhancements pertaining to locating the Vim 161 | executable more flexibly. 162 | 163 | 164 | Getting Started 165 | --------------- 166 | 167 | Vimer is a single-file executable script. 168 | 169 | Download [`vimer.cmd`][DOWNLOAD_WIN] for Windows, or 170 | [`vimer`][DOWNLOAD_LIN] for Linux or Mac. 171 | 172 | Copy it to a directory specified in the PATH environment variable. On 173 | Linux or Mac, make the script executable: `chmod u+x vimer`. 174 | 175 | The following list describes some of the ways Vimer may be used. 176 | 177 | 1. Launch a new instance of GVim or MacVim. 178 | 179 | ```sh 180 | vimer 181 | ``` 182 | 183 | 2. Edit files. 184 | 185 | ```sh 186 | vimer foo.txt bar.txt baz.txt 187 | ``` 188 | 189 | If an instance of GVim or MacVim is already running, this command 190 | opens the files in separate buffers in the same instance of the 191 | editor. Otherwise, they are opened in separate buffers in a new 192 | instance of the editor. 193 | 194 | 3. If the `-t` option is specified, then files are opened in separate 195 | tab pages in an existing instance of GVim or MacVim if it exists. 196 | If no instance of GVim or MacVim already exists, the files are 197 | opened in separate tabs in a new instance of the editor. 198 | 199 | ```sh 200 | vimer -t foo.txt bar.txt baz.txt 201 | ``` 202 | 203 | 4. Pipe the standard output of a command into the standard input of 204 | GVim or MacVim. Use the `-t` option to open it in a separate tab. 205 | 206 | ```sh 207 | ls -l | vimer - 208 | ls -l | vimer -t - 209 | ``` 210 | 211 | 5. Launch a new instance of GVim or MacVim with a specific server 212 | name. 213 | 214 | ```sh 215 | vimer -s FOO 216 | ``` 217 | 218 | If the specified server name is already being used by another 219 | instance of the editor, a number postfix is applied (e.g. `FOO1`, 220 | `FOO2`, etc.) until a free name is encountered. 221 | 222 | 6. Edit files in GVim or MacVim with a specific server name. 223 | 224 | ```sh 225 | vimer -s FOO foo.txt bar.txt baz.txt 226 | ``` 227 | 228 | If an instance of GVim or MacVim with the specified server name is 229 | already running, this command opens the files in that instance of 230 | the editor. If such an instance of the editor does not exist, 231 | then the first server with the number postfix will be used. 232 | 233 | If there is no existing instance of the editor with a matching 234 | server name or a server name with number postfix, the files are 235 | opened in separate buffers in a new instance of the editor with 236 | the specified server name, or a server name with number postfix. 237 | 238 | 7. Enable a context menu option called *Edit with GVim* for files on 239 | Windows. 240 | 241 | ```bat 242 | vimer --enable 243 | ``` 244 | 245 | After executing the above command, on right clicking a file, an 246 | option called *Edit with GVim* should appear in the context menu. 247 | Selecting this option opens the file in an existing instance of 248 | GVim if it exists. If no existing instance of GVim already 249 | exists, then the file is opened in a new instance of GVim. 250 | 251 | A similar context menu option called *Edit with existing Vim* is 252 | already provided by the GVim installer for Windows. But this 253 | option is provided in Vimer anyway because combining this option 254 | with `-t` creates a context menu option to open files in separate 255 | tab pages, as explained in the next point. Such a context menu 256 | option is not provided by the GVim installer for Windows. 257 | 258 | 8. Enable a context menu option called *Edit with GVim tab* for files 259 | on Windows. 260 | 261 | ```bat 262 | vimer -t --enable 263 | ``` 264 | 265 | 9. Disable context menu options on Windows. 266 | 267 | ```bat 268 | vimer --disable 269 | vimer -t --disable 270 | ``` 271 | 272 | The `--enable` and `--disable` options are not supported for Linux 273 | and Mac. See the [Context Menu](#context-menu) section below to 274 | read how to create such context menu option in other desktop 275 | environments. 276 | 277 | 10. For more details on how to use Vimer, execute the following 278 | command. 279 | 280 | ```sh 281 | vimer --help 282 | ``` 283 | 284 | Users who are very used to typing `vi`, `vim`, `gvim` or `mvim` to run 285 | the editor and find it difficult to type `vimer` might want to rename 286 | this script. For example, a user very used to typing `vi`, might want 287 | to rename this script from `vimer.cmd` to `vi.cmd` on Windows, or to 288 | `vi` on Linux or Mac. 289 | 290 | 291 | Troubleshooting 292 | --------------- 293 | 294 | 1. When the script is executed from a 32 bit [Console2][C2] window 295 | running on a 64 bit Windows operating system, the script fails 296 | with the following error. 297 | 298 | ``` 299 | ERROR: The system was unable to find the specified registry key or value. 300 | ``` 301 | 302 | To work around the issue, execute the script in the native Windows 303 | Command Prompt, or install the 64 bit Console2 application and 304 | execute the script from a 64 bit Console2 window. 305 | 306 | 2. After the script is renamed to `gvim` on Linux or `mvim` on Mac, 307 | running `gvim` or `mvim` with a filename as argument may still 308 | open the file in a new instance of the editor, not in an existing 309 | instance of the editor, even if such an instance already exists. 310 | 311 | If this happens, it is very likely that the `gvim` or `mvim` 312 | command is still running GVim or MacVim, respectively, not Vimer. 313 | 314 | To confirm, execute the following command on Linux. 315 | 316 | ```sh 317 | gvim --version 318 | ``` 319 | 320 | Or the following command on Mac. 321 | 322 | ```sh 323 | mvim --version 324 | ``` 325 | 326 | If the string "VIM" appears in the first line of the output, it is 327 | GVim or MacVim. 328 | 329 | If it is confirmed that running `gvim` on Linux, or `mvim` on Mac 330 | executes GVim or MacVim, respectively, ensure that the path where 331 | this script is located appears before the path where GVim or 332 | MacVim is located in the PATH environment variable. 333 | 334 | Further, on Linux or Mac, set the `VIM_CMD` environment variable 335 | to the absolute path of GVim or MacVim. For more details about 336 | this, see the next point. 337 | 338 | 3. When the script is renamed to `gvim` on Linux or `mvim` on Mac, 339 | and `gvim` or `mvim` is run, the shell may hang. If the `VIM_CMD` 340 | environment variable is not set, internally, the script invokes 341 | the `gvim` command on Linux or the `mvim` command on Mac to edit 342 | files. But when this script itself is named as `gvim` on Linux or 343 | `mvim` on Mac, invoking `gvim` or `mvim`, respectively, ends up 344 | invoking itself thereby resulting in an infinite recursion. 345 | 346 | To resolve the issue, set the `VIM_CMD` environment variable to 347 | the absolute path of GVim. Here is an example for Linux. 348 | 349 | ```sh 350 | export VIM_CMD=/usr/bin/gvim 351 | ``` 352 | 353 | Here is an example for Mac. 354 | 355 | ```sh 356 | export VIM_CMD=/usr/local/bin/mvim 357 | ``` 358 | 359 | Consider adding this to the shell's initialization file (e.g. 360 | ~/.bashrc) so that this environment variable is persistent and 361 | available across shell sessions. 362 | 363 | As a workaround, consider renaming the script to something other 364 | than `gvim` or `mvim`, perhaps `vi` which is short and sweet and 365 | has the additional advantage that no matter what system it is, one 366 | only has to remember to type `vi` to edit files. 367 | 368 | [C2]: http://sourceforge.net/projects/console/ 369 | 370 | 371 | Context Menu 372 | ------------ 373 | 374 | This section descibes how to add context menu option for files that 375 | opens files in an existing instance of GVim or MacVim in various 376 | desktop environments. This section does not require the use of Vimer. 377 | 378 | The steps provided in the sections below create a context menu option 379 | to edit files in new buffers. To edit files in new tabs instead, use 380 | the `--remote-tab-silent` option instead of the `--remote-silent` 381 | option in the sections below. 382 | 383 | 384 | ### Windows ### 385 | 386 | The following steps have been found to work fine on Windows XP and 387 | Windows 7. These steps probably work fine on other versions of 388 | Windows too. 389 | 390 | 1. Run the following command. 391 | 392 | ```bat 393 | regedit 394 | ``` 395 | 396 | 2. Go to `HKEY_CLASSES_ROOT\*\shell`. Right click on the node named 397 | `shell`, select *New* > *Key*. Name the new key as `Edit with 398 | GVim`. 399 | 400 | 3. Then right click on the new node, select *New* > *Key* and name 401 | the new node as `command`. 402 | 403 | 4. Now `HKEY_CLASSES_ROOT\*\shell\Edit with GVim\command` should be 404 | the current node. On the right-hand pane, double click on 405 | *(Default)* and enter the command to edit a file in existing GVim. 406 | Here is an example. 407 | 408 | ```bat 409 | "C:\Program Files (x86)\Vim\vim74\gvim.exe" --remote-silent "%1" 410 | ``` 411 | 412 | 4. Click *OK*. 413 | 414 | To remove this context menu option, run `regedit`, go to 415 | `HKEY_CLASSES_ROOT\*\shell`, right click on the node for this context 416 | menu, select *Delete* and click *Yes*. 417 | 418 | Alternatively, run `vimer --enable` to automatically find the path to 419 | `gvim.exe` and create the registry value described above. To remove 420 | this registry value, run `vimer --disable`. To enable or disable 421 | similar registry value that creates a context menu option to edit 422 | files with existing GVim in a new tab page, run `vimer --tab --enable` 423 | or `vim --tab -disable`, respectively. 424 | 425 | 426 | ### Xfce on Linux ### 427 | 428 | The following steps have been found to work fine on Xfce 4.10 on 429 | Debian 8.0. These steps probably work fine on Xfce 4 on any Linux 430 | distribution. 431 | 432 | 1. Run *Thunar*, i.e. *Applications Menu* > *File Manager*. 433 | 434 | 2. From the menu, go to *Edit* > *Configure custom actions*. 435 | 436 | 2. Click the plus icon to add a new custom action.. 437 | 438 | 3. Enter the following details. 439 | - Name: `Edit with GVim` 440 | - Command: `gvim --remote-silent %F` 441 | - Icon: vim 442 | 443 | 4. Go to *Apperance Conditions* tab and select *Directories*, *Text 444 | Files* and *Other Files*. 445 | 446 | 5. Click *OK*. Click *Close*. 447 | 448 | To remove this context menu option, follow step 1 again, select the 449 | context menu option, click the bin icon to delete the currently 450 | selected action and click *Delete*. 451 | 452 | 453 | ### GNOME on Linux ### 454 | 455 | The following steps have been found to work fine on GNOME 2.28.2 on 456 | CentOS 6.5 and GNOME 3.4.1 on Debian 8.2 (Jessie). These steps 457 | probably work fine on GNOME 2 and GNOME 3 on any Linux distribution. 458 | The steps below need to be performed in a shell. 459 | 460 | 1. On GNOME 2, go to the ~/.gnome2/nautilus-scripts/ directory. 461 | 462 | ```sh 463 | cd ~/.gnome2/nautilus-scripts/ 464 | ``` 465 | 466 | On GNOME 3, go to ~/.local/share/nautilus/scripts/ instead. 467 | 468 | ```sh 469 | cd ~/.local/share/nautilus/scripts/ 470 | ``` 471 | 472 | 2. Now create an executable script that contains the shell command to 473 | edit files in an existing instance of GVim if it exists. 474 | 475 | ```sh 476 | echo 'gvim --remote-silent "$@"' > "Edit with GVim" 477 | chmod u+x "Edit with GVim" 478 | ``` 479 | 480 | After following these steps, open Nautilus (File Browser on GNOME 2, 481 | or Files on GNOME 3), right click on a file, select Scripts > Edit 482 | with GVim. 483 | 484 | To remove this context menu option, delete the script for the context 485 | menu option from ~/.gnome2/nautilus-scripts (GNOME 2) or 486 | ~/.local/share/nautilus/scripts (GNOME 3). 487 | 488 | 489 | ### Mac ### 490 | 491 | The following steps have been found to work fine on Mac 10.9.5 492 | (Mavericks). 493 | 494 | 1. Go to *Launchpad*, search for *Automator*, then click on it to 495 | launch it. It should display a dialog box to choose a type for 496 | the new document. If this is not displayed, click *New Document* 497 | to display it. 498 | 499 | 2. Select *Service* and click *Choose*. 500 | 501 | 3. In the *Service receives selected* drop-down list, select *files 502 | or folders*. 503 | 504 | 4. Under *Library*, select *Utilities* and double click *Run Shell 505 | Script*. 506 | 507 | 5. In the new pane that appears, go to the *Pass Input* drop-down 508 | list and select *as arguments*. 509 | 510 | 6. Erase all the code in the text box and enter the shell command to 511 | edit files in an existing instance of MacVim if it exists. Note 512 | that the absolute path to MacVim should be used in the command. 513 | 514 | ```sh 515 | /usr/local/bin/mvim --remote-silent "$@" 516 | ``` 517 | 518 | 7. From the menu, select *File* > *Save*. Enter `Edit with MacVim` 519 | as the service name and click *Save*. 520 | 521 | 8. From the menu, select *Automator* > *Quit Automator*. 522 | 523 | To remove this context menu option, launch Finder, select *Go* > *Go 524 | to Folder*, enter `~/Library/Services`, right click on the workflow 525 | for this context menu option and select *Move to Trash*. 526 | 527 | 528 | License 529 | ------- 530 | 531 | This is free and open source software. You can use, copy, modify, 532 | merge, publish, distribute, sublicense, and/or sell copies of it, 533 | under the terms of the MIT License. See [LICENSE.md][L] for details. 534 | 535 | This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, 536 | express or implied. See [LICENSE.md][L] for details. 537 | 538 | [L]: LICENSE.md 539 | 540 | 541 | Support 542 | ------- 543 | 544 | To report bugs, suggest improvements, or ask questions, please create 545 | a new issue at . 546 | -------------------------------------------------------------------------------- /dev/README.md: -------------------------------------------------------------------------------- 1 | Vimer Developer Notes 2 | ===================== 3 | 4 | Tests 5 | ----- 6 | All discussion about tests in this section assume that the tests are 7 | being run on a Debian or Debian based system. On other systems, the 8 | commands mentioned below may need to be modified appropriately. The 9 | Linux/Mac *vimer* script, however, can run on any POSIX conformant 10 | Unix or Linux system with any POSIX conformant shell without any changes 11 | to the script. 12 | 13 | The Windows vimer.cmd script is not discussed here. There are no tests 14 | for it. 15 | 16 | ### Setup Test Environment ### 17 | Enter the following commands as root to install kcov. It is used to 18 | measure code coverage of the tests. 19 | 20 | apt-get update 21 | apt-get install g++ pkg-config libcurl4-gnutls-dev libelf-dev libdw-dev zlib1g-dev 22 | git clone https://github.com/SimonKagstrom/kcov.git 23 | mkdir kcov/build 24 | cd kcov/build 25 | cmake .. 26 | make 27 | make install 28 | 29 | Enter the following command to install the shells required for testing 30 | cross-shell compatibility. 31 | 32 | apt-get install bash ksh dash posh 33 | 34 | ### Run Tests ### 35 | Change current directory to the top level directory of this project and 36 | enter the following command to run a quick test with sh. 37 | 38 | make test 39 | 40 | Now enter the following command to run a complete test with sh, bash, 41 | ksh and dash. 42 | 43 | make alltest 44 | 45 | Finally enter the following command to measure code coverage. 46 | 47 | make coverage 48 | 49 | Open coverage/index.html with a web browser to see the code coverage 50 | results. 51 | 52 | ### About the Tests ### 53 | All tests for this project are present in the *test* directory relative 54 | to the top level directory of this project. 55 | 56 | This project does not use an external testing tool or library to run the 57 | tests. This project comes with its own very basic and minimal test 58 | runner which can be found at *test/test*. It is a shell script that may 59 | be run with any POSIX conformant shell. 60 | 61 | For example, to run the tests with bash, enter the following command. 62 | 63 | bash test/test 64 | 65 | As another example, to run the tests with ksh, enter the following 66 | command. 67 | 68 | ksh test/test 69 | 70 | See *Makefile* for more details on how the tests are run. 71 | 72 | The test runner script at *test/test* follows very simple rules to 73 | discover and run tests. 74 | 75 | 1. It looks for files that match the wildcard pattern `test/test_*` 76 | relative to the current directory. These are considered to be test 77 | scripts. Therefore, the test runner must be run from the top level 78 | directory of the project. 79 | 2. Each test script is executed in the same shell that invoked the 80 | test runner *test/test*. Thus, all functions defined in each test 81 | script become available in the shell that runs the test runner. 82 | 3. Each test script is searched for functions with alphanumeric names 83 | that begin with `test_`. These are considered to be test functions. 84 | 4. After all test functions have been discovered, each test function is 85 | executed. 86 | 5. If a test function returns with an exit status of 0, the test is 87 | considered to have passed, otherwise it is considered to 88 | have failed. 89 | 6. Before executing each test function, an empty directory is created 90 | at "$TWORK". The TWORK environment variable is set to test/work. 91 | 7. After executing each test function, the "$TWORK" directory is 92 | removed automatically. Therefore, any temporary working files 93 | required during testing may be written to "$TWORK" by the test 94 | functions. 95 | 96 | It is an error if two test functions have the same name, even if the two 97 | functions are in different test scripts. Each test function defined 98 | within the *test* directory must have a distinct name. 99 | 100 | If all tests pass, the test runner prints the number of tests that 101 | passed and exits with an exit status of 0. If one or more tests fail, 102 | then the test runner prints the number of tests that passed followed by 103 | the number of tests that failed and exits with an exit status of 1. 104 | 105 | See the test runner *test/test* for more details. 106 | 107 | 108 | Release 109 | ------- 110 | The following tasks need to be performed for every release of a new 111 | version. These tasks should be performed with the project's top-level 112 | directory as the current directory. 113 | 114 | - Update copyright notice in LICENSE.md. 115 | - Update copyright notice in vimer.cmd. 116 | - Update copyright notice in vimer. 117 | - Update copyright notice in tests. 118 | - Update `COPYRIGHT` in vimer.cmd. 119 | - Update `COPYRIGHT` in vimer. 120 | - Update `VERSION` in vimer.cmd. 121 | - Update `VERSION` in vimer. 122 | - Update version in download URLs in README.md at two places. 123 | - Update CHANGES.md. 124 | - Run tests. 125 | 126 | make test 127 | make alltest 128 | make coverage 129 | firefox coverage/index.html & 130 | 131 | - Confirm that code coverage looks good. 132 | - Tag the release. 133 | 134 | git tag -a -m "Todo " 135 | git push origin 136 | 137 | - Upload vimer.cmd and vimer to GitHub release page. 138 | -------------------------------------------------------------------------------- /test/mockcat: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Mock cat. 4 | 5 | # The MIT License (MIT) 6 | # 7 | # Copyright (c) 2016 Susam Pal 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining 10 | # a copy of this software and associated documentation files (the 11 | # "Software"), to deal in the Software without restriction, including 12 | # without limitation the rights to use, copy, modify, merge, publish, 13 | # distribute, sublicense, and/or sell copies of the Software, and to 14 | # permit persons to whom the Software is furnished to do so, subject to 15 | # the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be 18 | # included in all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | 29 | # This script considers the last argument to be a file path and prints 30 | # its content. This script is used as VIM_CMD for some tests where the 31 | # content read by Vim needs to be verified. 32 | 33 | 34 | # Ignore all command line arguments except the last one. 35 | while [ $# -gt 1 ] 36 | do 37 | shift 38 | done 39 | 40 | # The last argument is a file path. Print the content of that file. 41 | cat "$1" 42 | -------------------------------------------------------------------------------- /test/mockvim: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Mock cat. 4 | 5 | # The MIT License (MIT) 6 | # 7 | # Copyright (c) 2016 Susam Pal 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining 10 | # a copy of this software and associated documentation files (the 11 | # "Software"), to deal in the Software without restriction, including 12 | # without limitation the rights to use, copy, modify, merge, publish, 13 | # distribute, sublicense, and/or sell copies of the Software, and to 14 | # permit persons to whom the Software is furnished to do so, subject to 15 | # the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be 18 | # included in all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | 29 | # This script prints a single line of output that contains each 30 | # command-line argument surrounded in double-quotes. This script is used 31 | # as VIM_CMD for many tests where the command-line arguments Vim is 32 | # invoked with needs to be verified. 33 | 34 | 35 | # Begin creating a result string with the first argument in double-quotes. 36 | [ $# -gt 0 ] && args="\"$1\"" && shift 37 | 38 | # Append each remaining argument within double-quotes to the result string. 39 | while [ $# -gt 0 ] 40 | do 41 | args="$args \"$1\"" && shift 42 | done 43 | 44 | # Finally print the result string. 45 | printf "%s\n" "$args" 46 | -------------------------------------------------------------------------------- /test/setup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Test Setup. 4 | 5 | # The MIT License (MIT) 6 | # 7 | # Copyright (c) 2016 Susam Pal 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining 10 | # a copy of this software and associated documentation files (the 11 | # "Software"), to deal in the Software without restriction, including 12 | # without limitation the rights to use, copy, modify, merge, publish, 13 | # distribute, sublicense, and/or sell copies of the Software, and to 14 | # permit persons to whom the Software is furnished to do so, subject to 15 | # the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be 18 | # included in all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | import=true . ./vimer 29 | -------------------------------------------------------------------------------- /test/test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Test Runner. 4 | 5 | # The MIT License (MIT) 6 | # 7 | # Copyright (c) 2016 Susam Pal 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining 10 | # a copy of this software and associated documentation files (the 11 | # "Software"), to deal in the Software without restriction, including 12 | # without limitation the rights to use, copy, modify, merge, publish, 13 | # distribute, sublicense, and/or sell copies of the Software, and to 14 | # permit persons to whom the Software is furnished to do so, subject to 15 | # the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be 18 | # included in all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | 29 | # Location of test script files. 30 | TMAIN=test 31 | 32 | # Temporary working directory that may be used by any tests. 33 | TWORK=test/work 34 | 35 | # Temporary file containing the list of all discovered tests. 36 | TLIST=test/list 37 | 38 | # Location of test data files. 39 | TDATA=test/data 40 | 41 | # Start afresh with a clean test list. 42 | rm -f "$TLIST" "$TWORK" 43 | trap "rm -rf \"$TWORK\" \"$TLIST\"" EXIT 44 | 45 | # Discover test scripts. 46 | for test_file in test/test_* 47 | do 48 | # Load the test script. 49 | . "$test_file" 50 | 51 | # Add test functions in the test script to test list. 52 | grep -E "^test_[[:alnum:]]*()" "$test_file" | while read -r test_func 53 | do 54 | test_file=${test_file#"$TMAIN"/test_} 55 | test_func=${test_func#test_} 56 | test_func=${test_func%"()"} 57 | printf "%s:%s\n" "$test_file" "$test_func" >> "$TLIST" 58 | done 59 | done 60 | 61 | # It is an error if two test functions have the same name. 62 | duplicate=$(cut -d : -f 2 "$TLIST" | sort | uniq -d | head -n 1) 63 | if [ -n "$duplicate" ] 64 | then 65 | echo Error: Duplicate test function names! 66 | grep ":$duplicate$" "$TLIST" 67 | return 1 68 | fi 69 | 70 | 71 | # Number of tests that passed. 72 | pass=0 73 | 74 | # Number of tests that failed. 75 | fail=0 76 | 77 | [ -f "test/setup" ] && . test/setup 78 | 79 | # Execute each test. 80 | while read -r test_spec 81 | do 82 | test_file="${test_spec%:*}" 83 | test_func="${test_spec#*:}" 84 | printf "%s: %s: " "${test_file}" "${test_func}" 85 | mkdir -p "$TWORK" 86 | if ("test_$test_func") 87 | then 88 | pass=$(( $pass + 1 )) 89 | printf "pass\n" 90 | else 91 | fail=$(( $fail + 1 )) 92 | printf "FAIL\n" 93 | fi 94 | rm -r "$TWORK" 95 | done < "$TLIST" 96 | rm "$TLIST" 97 | 98 | echo PASS: $pass 99 | [ $fail -gt 0 ] && echo FAIL: $fail && exit 1 || exit 0 100 | -------------------------------------------------------------------------------- /test/test_vimer: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Tests for list actions. 4 | 5 | # The MIT License (MIT) 6 | # 7 | # Copyright (c) 2016 Susam Pal 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining 10 | # a copy of this software and associated documentation files (the 11 | # "Software"), to deal in the Software without restriction, including 12 | # without limitation the rights to use, copy, modify, merge, publish, 13 | # distribute, sublicense, and/or sell copies of the Software, and to 14 | # permit persons to whom the Software is furnished to do so, subject to 15 | # the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be 18 | # included in all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | 29 | # When no arguments are specified to Vimer, a new Vim window is 30 | # launched. 31 | test_no_args() 32 | { 33 | VIM_CMD="$TMAIN/mockvim" 34 | [ -z "$(main)" ] || return 1 35 | [ -z "$(main -t)" ] || return 1 36 | unset VIM_CMD 37 | } 38 | 39 | 40 | # When a file argument is specified, Vim tries to connect to a Vim 41 | # server and edit the file. 42 | test_one_file_arg() 43 | { 44 | VIM_CMD="$TMAIN/mockvim" 45 | [ "$(main foo.txt)" = '"--remote-silent" "foo.txt"' ] 46 | unset VIM_CMD 47 | } 48 | 49 | 50 | # When multiple file arguments are specified, Vim tries to connect to a 51 | # Vim server and edit the files. 52 | test_two_file_args() 53 | { 54 | VIM_CMD="$TMAIN/mockvim" 55 | [ "$(main foo.txt bar.txt)" = '"--remote-silent" "foo.txt" "bar.txt"' ] 56 | unset VIM_CMD 57 | } 58 | 59 | 60 | # Filenames with whitespace are passed correctly to Vim with the 61 | # whitespace intact. 62 | test_file_args_with_whitespace() 63 | { 64 | VIM_CMD="$TMAIN/mockvim" 65 | [ "$(main "foo bar.txt" "baz qux.txt")" = \ 66 | '"--remote-silent" "foo bar.txt" "baz qux.txt"' ] 67 | unset VIM_CMD 68 | } 69 | 70 | 71 | # With the -t/--tab option, each file should be opened in a new tab. 72 | test_tab_option() 73 | { 74 | VIM_CMD="$TMAIN/mockvim" 75 | for opt in -t --tab 76 | do 77 | [ "$(main $opt foo.txt)" = \ 78 | '"--remote-tab-silent" "foo.txt"' ] || return 1 79 | done 80 | unset VIM_CMD 81 | } 82 | 83 | 84 | # With -s/--server option alone, i.e. without file arguments, Vim 85 | # launches a new server with the specified server name. 86 | test_server_option() 87 | { 88 | VIM_CMD="$TMAIN/mockvim" 89 | for opt in -s --server 90 | do 91 | [ "$(main $opt name)" = '"--servername" "name"' ] || return 1 92 | done 93 | unset VIM_CMD 94 | } 95 | 96 | 97 | # With the -s/--server option and a file argument, Vim tries to connect 98 | # to a Vim server with the specified servername and edit the file. 99 | test_server_option_file_arg() 100 | { 101 | VIM_CMD="$TMAIN/mockvim" 102 | for opt in -s --server 103 | do 104 | [ "$(main $opt name foo.txt)" = \ 105 | '"--servername" "name" "--remote-silent" "foo.txt"' ] || return 1 106 | done 107 | unset VIM_CMD 108 | } 109 | 110 | 111 | # Server option must be followed by a server name. 112 | test_no_server_name() 113 | { 114 | main -s 2>&1 | grep -q '^.*: Argument missing after: "-s".$' 115 | } 116 | 117 | 118 | # Server name must be a non-empty string. 119 | test_empty_server_name() 120 | { 121 | main -s "" 2>&1 | grep -q '^.*: Non-empty string must follow "-s".$' 122 | } 123 | 124 | 125 | 126 | 127 | # With the -t and -s options only, i.e. without file arguments, Vim 128 | # launcches a new server with the specified server name. 129 | test_tab_server_options() 130 | { 131 | VIM_CMD="$TMAIN/mockvim" 132 | [ "$(main -t -s name)" = '"--servername" "name"' ] || return 1 133 | [ "$(main -s name -t)" = '"--servername" "name"' ] || return 1 134 | unset VIM_CMD 135 | } 136 | 137 | 138 | # With the -t and -s options and a file argument, Vim tries to connect 139 | # to a Vim server with the specified servername and edit the file. 140 | test_tab_server_options_file_arg() 141 | { 142 | VIM_CMD="$TMAIN/mockvim" 143 | [ "$(main -t -s name foo.txt)" = \ 144 | '"--servername" "name" "--remote-tab-silent" "foo.txt"' ] || return 1 145 | [ "$(main -s name -t foo.txt)" = \ 146 | '"--servername" "name" "--remote-tab-silent" "foo.txt"' ] || return 1 147 | unset VIM_CMD 148 | } 149 | 150 | 151 | # With the -n/--name option, the value of VIM_CMD is displayed. 152 | test_name_option() 153 | { 154 | VIM_CMD=foo 155 | for opt in -n --name 156 | do 157 | [ "$(main $opt)" = foo ] || return 1 158 | done 159 | unset VIM_CMD 160 | } 161 | 162 | 163 | # With the hyphen argument, i.e. '-', the text read via standard input 164 | # is first written to a file and that file is edited. 165 | test_hyphen_arg() 166 | { 167 | VIM_CMD="$TMAIN/mockvim" 168 | 169 | echo hi | main - | 170 | grep -q '^"--remote-silent" "/tmp/vimer/_STDIN_' || return 1 171 | 172 | echo hi | main -t - | 173 | grep -q '^"--remote-tab-silent" "/tmp/vimer/_STDIN_' || return 1 174 | 175 | regex='^"--servername" "name" "--remote-silent" "/tmp/vimer/_STDIN_' 176 | echo hi | main -s name - | grep -q "$regex" || return 1 177 | 178 | rm -rf "$TMP_DIR" 179 | unset VIM_CMD 180 | } 181 | 182 | 183 | # With the hyphen argument, i.e. '-', the text read via standard input 184 | # is edited. 185 | test_stdin_read() 186 | { 187 | VIM_CMD="$TMAIN/mockcat" 188 | echo hello world | main - | grep -q "^hello world$" || return 1 189 | echo hello world | main -t - | grep -q "^hello world$" || return 1 190 | echo hello world | main -s name - | grep -q "^hello world$" || return 1 191 | rm -rf "$TMP_DIR" 192 | unset VIM_CMD 193 | } 194 | 195 | 196 | # While editing standard input, hyphen, i.e. '-', must be the only 197 | # argument. 198 | test_too_many_args_with_hyphen() 199 | { 200 | main - foo 2>&1 | grep -q '^.*: Too many edit arguments: "foo".$' 201 | } 202 | 203 | 204 | # If the temporary directory cannot be created, an error occurs. 205 | test_tmp_dir_failure() 206 | { 207 | # Create a filename with the same name as $TMP_DIR. This would cause 208 | # the a directory creation with the same name to fail. 209 | rm -rf "$TMP_DIR" 210 | touch "$TMP_DIR" 211 | 212 | main - 2>&1 | grep -q "^.*: Cannot create temporary directory: $TMP_DIR\.$" 213 | rm "$TMP_DIR" 214 | } 215 | 216 | 217 | # Vimer ignores non-existent editors and uses an editor that exists. 218 | test_find_vim() 219 | { 220 | EDITORS=junk:$TMAIN/mockvim 221 | main -n | grep -q '/mockvim$' 222 | } 223 | 224 | 225 | # When Vimer cannot find an editor, an error occurs. 226 | test_find_vim_failure() 227 | { 228 | EDITORS=junk:junk 229 | main 2>&1 | grep -q '^.*: Cannot find GVim or MacVim\.$' 230 | } 231 | 232 | 233 | # Help output contains usage line. 234 | test_help() 235 | { 236 | for opt in -h --help 237 | do 238 | main $opt | head -n 1 | grep -q "^Usage:" || return 1 239 | done 240 | } 241 | 242 | 243 | # Version output contains version. 244 | test_version() 245 | { 246 | for opt in -v --version 247 | do 248 | main $opt | head -n 1 | grep -q "Vimer $VERSION" || return 1 249 | done 250 | } 251 | -------------------------------------------------------------------------------- /vimer: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Vimer - A convenience wrapper for gvim/mvim --remote(-tab)-silent. 4 | 5 | # The MIT License (MIT) 6 | # 7 | # Copyright (c) 2010-2016 Susam Pal 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining 10 | # a copy of this software and associated documentation files (the 11 | # "Software"), to deal in the Software without restriction, including 12 | # without limitation the rights to use, copy, modify, merge, publish, 13 | # distribute, sublicense, and/or sell copies of the Software, and to 14 | # permit persons to whom the Software is furnished to do so, subject to 15 | # the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be 18 | # included in all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | 29 | VERSION=0.2.1-DEV 30 | AUTHOR="Susam Pal" 31 | COPYRIGHT="Copyright (c) 2010-2016 $AUTHOR" 32 | 33 | LICENSE_URL="http://susam.in/licenses/mit/" 34 | SUPPORT_URL="https://github.com/susam/vimer/issues" 35 | 36 | NOTICE=" 37 | This is free and open source software. You can use, copy, modify, 38 | merge, publish, distribute, sublicense, and/or sell copies of it, 39 | under the terms of the MIT License. You can obtain a copy of the 40 | MIT License at <$LICENSE_URL>. 41 | 42 | This software is provided \"AS IS\", WITHOUT WARRANTY OF ANY KIND, 43 | express or implied. See the MIT License for details." 44 | 45 | NAME=${0##*/} 46 | 47 | TMP_DIR=/tmp/vimer 48 | EDITORS=gvim:mvim 49 | 50 | # Starting point of this script. 51 | # 52 | # Arguments: 53 | # arg...: All arguments this script was invoked with 54 | main() 55 | { 56 | if [ -z "$VIM_CMD" ] 57 | then 58 | VIM_CMD="$(find_vim)" 59 | fi 60 | 61 | parse_arguments "$@" 62 | } 63 | 64 | 65 | # Find a GVim or MacVim. 66 | # 67 | # If either GVim or MacVim is found, print its name; do not print 68 | # anything otherwise. 69 | find_vim() 70 | { 71 | echo $EDITORS | tr : '\n' | while read -r v 72 | do 73 | if "$v" --version > /dev/null 2>&1 74 | then 75 | printf "%s" "$v" 76 | break 77 | fi 78 | done 79 | } 80 | 81 | 82 | # Parse command line arguments passed to this script. 83 | # 84 | # Arguments: 85 | # arg...: All arguments this script was invoked with 86 | # 87 | # Errors: 88 | # Exit with an error message if invalid arguments are specified. 89 | parse_arguments() 90 | { 91 | while [ $# -gt 0 ] 92 | do 93 | case $1 in 94 | -t | --tab) 95 | tab=-tab 96 | shift 97 | ;; 98 | -s | --server) 99 | [ $# -lt 2 ] && quit Argument missing after: \""$1"\". 100 | [ -z "$2" ] && quit Non-empty string must follow \""$1"\". 101 | server=$2 102 | shift 2 103 | ;; 104 | -n | --name) 105 | printf "%s\n" "$VIM_CMD" 106 | exit 107 | ;; 108 | -h | --help) 109 | show_help 110 | exit 111 | ;; 112 | -v | --version) 113 | show_version 114 | exit 115 | ;; 116 | *) 117 | break 118 | ;; 119 | esac 120 | done 121 | 122 | if [ $# -eq 0 ] 123 | then 124 | # If no file arguments are specified, start a new instance of 125 | # GVim or MacVim. 126 | exec_vim 127 | elif [ "$1" = "-" ] 128 | then 129 | # If hyphen is specified as a file argument, read input from 130 | # standard input. 131 | [ $# -gt 1 ] && quit Too many edit arguments: \""$2"\". 132 | exec_vim_with_stdin 133 | fi 134 | 135 | # Consume remaining file arguments. 136 | while [ "$#" -gt 0 ] 137 | do 138 | args="$args \"$1\"" 139 | shift 140 | done 141 | 142 | # Execute GVim or MacVim with remaining file arguments. 143 | exec_vim "$args" 144 | } 145 | 146 | 147 | # Save standard input in a temporary file and edit it. 148 | exec_vim_with_stdin() 149 | { 150 | # Create temporary directory. 151 | if ! mkdir -p "$TMP_DIR" 152 | then 153 | quit Cannot create temporary directory: "$TMP_DIR". 154 | fi 155 | 156 | # Determine a unique temporary filename. 157 | n=0 158 | while : 159 | do 160 | d=$(date "+%Y-%m-%d_%H-%M-%S") 161 | stdin_file="$TMP_DIR/_STDIN_${d}_${n}" 162 | n=$(( $n + 1 )) 163 | if [ ! -e "$stdin_file" ] 164 | then 165 | break 166 | fi 167 | done 168 | 169 | # Create temporary file and edit it. 170 | cat > "$stdin_file" 171 | exec_vim "$stdin_file" 172 | } 173 | 174 | 175 | # Execute GVim or MacVim with specified arguments. 176 | # 177 | # This function accepts only a single argument that may represent 178 | # multiple arguments for GVim or MacVim. For example, if GVim or MacVim 179 | # needs to be invoked with two arguments, e.g. "foo bar.txt" and "baz 180 | # qux.txt", then this function must be invoked as follows. 181 | # 182 | # exec_vim "\"foo bar.txt\" \"baz qux.txt\"" 183 | # 184 | # Note that the above call has only one argument that represents two 185 | # quoted arguments that need to be passed to GVim or MacVim. 186 | # 187 | # Arguments: 188 | # args...: All arguments specified as a single argument. 189 | # 190 | # Errors: 191 | # Exit with an error message if VIM_CMD variable is not set. 192 | exec_vim() 193 | { 194 | if [ -z "$VIM_CMD" ] 195 | then 196 | quit Cannot find GVim or MacVim. 197 | fi 198 | 199 | # If server name is specified, open files in an existing instance of 200 | # GVim or MacVim with the specified server name, or start a new 201 | # instance of GVim or MacVim with the specified server name. 202 | if [ -n "$server" ] 203 | then 204 | opts="$opts --servername \"$server\"" 205 | fi 206 | 207 | # If file arguments are specified, open them in an existing instance 208 | # of GVim or MacVim. 209 | if [ -n "$1" ] 210 | then 211 | opts="$opts --remote$tab-silent" 212 | fi 213 | 214 | 215 | eval exec "$VIM_CMD" "$opts" "$1" 216 | } 217 | 218 | 219 | # Terminate the script with an error message. 220 | # 221 | # Arguments: 222 | # string...: String to print to standard error stream. 223 | # 224 | # Errors: 225 | # Unconditionally cause the script to terminate with an error message 226 | # and exit code 1. 227 | quit() 228 | { 229 | printf "%s: %s\n" "$NAME" "$*" >&2 230 | exit 1 231 | } 232 | 233 | 234 | # Show help. 235 | show_help() 236 | { 237 | cat <. 261 | eof 262 | } 263 | 264 | 265 | # Show version and copyright. 266 | show_version() 267 | { 268 | cat < "%stdin_file%" 186 | call :exec_vim "%stdin_file%" 187 | 188 | endlocal 189 | goto :eof 190 | 191 | 192 | rem Execute GVim with specified arguments. 193 | rem 194 | rem Arguments: 195 | rem arg...: One or more arguments to GVim 196 | rem 197 | rem Errors: 198 | rem Exit with an error message if VIM_CMD variable is not set. 199 | :exec_vim 200 | if "%VIM_CMD%" == "" ( 201 | call :err Cannot find GVim. 202 | exit /b 1 203 | ) 204 | 205 | rem If server name is specified, open files in an existing instance 206 | rem of GVim with the specified server name, or start a new instance 207 | rem of GVim with the specified server name. 208 | if not "%server%" == "" ( 209 | set opts=%opts% --servername "%server%" 210 | ) 211 | 212 | rem If file arguments are specified, open them in an existing 213 | rem instance of GVim. 214 | if not "%~1" == "" ( 215 | set opts=%opts% --remote%tab%-silent 216 | ) 217 | 218 | start "" "%VIM_CMD%" %opts% %* 219 | goto :eof 220 | 221 | 222 | rem Show the known name or path of GVim executable. 223 | :show_name 224 | echo %VIM_CMD% 225 | call :pause 226 | goto :eof 227 | 228 | 229 | rem Add a new context menu option to open files with this script. 230 | :enable 231 | setlocal 232 | if "%tab%" == "-tab" (set k=%TAB_SHORTCUT%) else (set k=%BUF_SHORTCUT%) 233 | set d=\"%VIM_CMD%\" --remote%tab%-silent \"%%1\" 234 | reg add "HKCR\*\shell\%k%\command" /f /ve /d "%d%" 235 | endlocal 236 | call :pause 237 | goto :eof 238 | 239 | 240 | rem Remove context menu option to open files with this script. 241 | :disable 242 | setlocal 243 | if "%tab%" == "-tab" (set k=%TAB_SHORTCUT%) else (set k=%BUF_SHORTCUT%) 244 | reg delete "HKCR\*\shell\%k%" /f 245 | endlocal 246 | call :pause 247 | goto :eof 248 | 249 | 250 | rem Show the path of this script. 251 | :where_am_i 252 | echo %~f0 253 | call :pause 254 | goto :eof 255 | 256 | 257 | rem Print error message. 258 | rem 259 | rem Arguments: 260 | rem string...: String to print to standard error stream. 261 | :err 262 | >&2 echo %NAME%: %* 263 | call :pause 264 | goto :eof 265 | 266 | 267 | rem Show help. 268 | :show_help 269 | echo Usage: %NAME% [-t] [-s] [-e^|-d] [-n] [-w] [-h] [-v] [-^|FILE...] 270 | echo. 271 | echo This is a wrapper script to open files in existing GVim. If an 272 | echo existing instance of GVim is running, the files are opened in it, 273 | echo otherwise, a new GVim instance is launched. If no FILE is 274 | echo specified, a new GVim instance is launched. 275 | echo. 276 | echo If this script cannot find GVim, set the VIM_CMD environment 277 | echo variable with the command to execute GVim as its value. 278 | echo. 279 | echo Arguments: 280 | echo - Read text from standard input. 281 | echo FILE... Read text from one or more files. 282 | echo. 283 | echo Options: 284 | echo -t, --tab Open each file in new tab. 285 | echo -s, --server NAME Open files in GVim server with specified NAME. 286 | echo -e, --enable Enable context menu option to edit files. 287 | echo -d, --disable Disable context menu option to edit files. 288 | echo -n, --name Show the name/path of GVim being used. 289 | echo -w, --where Show the path where this script is present. 290 | echo -h, --help, /? Show this help and exit. 291 | echo -v, --version Show version and exit. 292 | echo. 293 | echo Report bugs to ^<%SUPPORT_URL%^>. 294 | call :pause 295 | goto :eof 296 | 297 | 298 | rem Show version and copyright. 299 | :show_version 300 | echo Vimer %VERSION% 301 | echo %COPYRIGHT% 302 | echo. 303 | echo This is free and open source software. You can use, copy, modify, 304 | echo merge, publish, distribute, sublicense, and/or sell copies of it, 305 | echo under the terms of the MIT License. You can obtain a copy of the 306 | echo MIT License at <%LICENSE_URL%>. 307 | echo. 308 | echo This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, 309 | echo express or implied. See the MIT License for details. 310 | call :pause 311 | goto :eof 312 | 313 | 314 | rem Pause if this script was invoked from command prompt. 315 | :pause 316 | echo %cmdcmdline% | findstr /i /c:"%~nx0" > nul && pause > nul 317 | goto :eof 318 | --------------------------------------------------------------------------------