Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 16 commits
  • 17 files changed
  • 0 commit comments
  • 2 contributors
View
1  .gitignore
@@ -3,3 +3,4 @@ tags
pkg/*
doc/*
tmp/*
+coverage/*
View
73 README.md
@@ -3,8 +3,8 @@
Using Vim's
[client/server](http://vimdoc.sourceforge.net/htmldoc/remote.html#clientserver)
functionality, this library exposes a way to spawn a Vim instance and control
-it programatically. Apart from being a fun party trick, this can be used to
-integration test Vim script.
+it programatically. Apart from being a fun party trick, this can be used to do
+integration testing on Vimscript.
This is still fairly experimental, so use with caution. Any issue reports or
contributions are very welcome on the
@@ -12,40 +12,59 @@ contributions are very welcome on the
## Usage
-There are two objects that can be used to control Vim, a "server" and a
-"client". The server takes care of spawning a server Vim instance that will be
-controlled, and the client is its interface.
+Vimrunner can be used in one of two main ways:
-A server can be started in two ways:
+```ruby
+# Vim will automatically be started and killed.
+Vimrunner.start do |vim|
+ vim.edit "file.txt"
+ vim.insert "Hello"
+ vim.write
+end
+```
- - `Vimrunner::Server.start`: Starts a terminal instance. Since it's
- "invisible", it's nice for use in automated tests. If it's impossible to
- start a terminal instance due to missing requirements for the `vim` binary
- (see "Requirements" below), a GUI instance will be started.
- - `Vimrunner::Server.start(:gui => true)`: Starts a GUI instance of Vim. On
- Linux, it'll be `gvim`, on Mac OS X it defaults to `mvim`.
+```ruby
+# Vim will automatically be started but you must manually kill it when you are
+# finished.
+vim = Vimrunner.start
+vim.edit "file.txt"
+vim.insert "Hello"
+vim.write
+vim.kill
+```
-Both methods return a `Server` instance. For a more comprehensive list of
-options you can start the server with, check out
-[the docs](http://rubydoc.info/gems/vimrunner/Vimrunner/Server).
+Vimrunner will attempt to start up the most suitable version of Vim available,
+meaning:
-To be able to send commands to the server, you need a client that knows some
-details about it:
+* `vim` if it supports headlessly creating servers;
+* `mvim` if you are on Mac OS X;
+* `gvim`.
-``` ruby
-server = Vimrunner::Server.start
+If you wish to always start a GUI Vim (viz. skip using a headless `vim`) then
+you can use `start_gvim` like so:
+
+```ruby
+Vimrunner.start_gvim do |vim|
+ # ...
+end
+```
+
+If you require an even more specific version of Vim, you can pass the path to
+it by instantiating your own `Server` instance like so:
-client = Vimrunner::Client.new(server)
-# or,
-client = server.new_client
+```ruby
+Vimrunner::Server.new("/path/to/my/specific/vim").start do |vim|
+ vim.edit "file.txt"
+end
```
-There are also two convenience methods that start a server and return a
-connected client -- `Vimrunner.start_vim` and `Vimrunner.start_gui_vim`.
+(You can also use the non-block form of `start` in both of the above
+examples.)
-For a full list of methods you can invoke on the remote vim instance, check out
-the methods on the `Client` class in
-[the docs](http://rubydoc.info/gems/vimrunner/Vimrunner/Client).
+Calling `start` (or `start_gvim`) will return a `Client` instance with which
+you can control Vim. For a full list of methods you can invoke on the remote
+vim instance, check out the [`Client`
+documentation](http://rubydoc.info/gems/vimrunner/Vimrunner/Client).
## Requirements
View
2  bin/vimrunner
@@ -5,6 +5,6 @@ $: << File.expand_path('../../lib', __FILE__)
require 'irb'
require 'vimrunner'
-$vim = Vimrunner.start_gui_vim
+$vim = Vimrunner.start_gvim
IRB.start
View
55 lib/vimrunner.rb
@@ -1,16 +1,51 @@
-require 'vimrunner/client'
-require 'vimrunner/server'
+require "vimrunner/server"
+require "vimrunner/platform"
module Vimrunner
- # Starts a new Server with a terminal Vim instance and returns a client,
- # connected to it.
- def self.start_vim
- Client.new(Server.start)
+
+ # Public: Start a Vim process and return a Client through which it can be
+ # controlled.
+ #
+ # vim - The String path to the Vim you wish to use (default: the most
+ # appropriate Vim for your system).
+ # blk - An optional block which will be passed a Client with which you can
+ # communicate with the Vim process. Upon exiting the block, the Vim
+ # process will be terminated.
+ #
+ # Examples
+ #
+ # client = Vimrunner.start
+ # # => #<Vimrunner::Client>
+ #
+ # Vimrunner.start do |client|
+ # client.command("version")
+ # end
+ #
+ # Returns a Client for the started Server.
+ def self.start(vim = Platform.vim, &blk)
+ Server.new(vim).start(&blk)
end
- # Starts a new Server with a GUI Vim instance and returns a client, connected
- # to it.
- def self.start_gui_vim
- Client.new(Server.start(:gui => true))
+ # Public: Start a Vim process with a GUI and return a Client through which
+ # it can be controlled.
+ #
+ # vim - The String path to the Vim you wish to use (default: the most
+ # appropriate Vim for your system).
+ # blk - An optional block which will be passed a Client with which you can
+ # communicate with the Vim process. Upon exiting the block, the Vim
+ # process will be terminated.
+ #
+ # Examples
+ #
+ # client = Vimrunner.start
+ # # => #<Vimrunner::Client>
+ #
+ # Vimrunner.start do |client|
+ # client.command("version")
+ # end
+ #
+ # Returns a Client for the started Server.
+ def self.start_gvim(&blk)
+ Server.new(Platform.gvim).start(&blk)
end
end
View
117 lib/vimrunner/client.rb
@@ -1,9 +1,4 @@
-require 'vimrunner/shell'
-
module Vimrunner
-
- # A Client is simply a proxy to a Vim server. It's initialized with a Server
- # instance and sends commands, keys and signals to it.
class Client
attr_reader :server
@@ -11,55 +6,74 @@ def initialize(server)
@server = server
end
- # Adds a plugin to Vim's runtime. Initially, Vim is started without
- # sourcing any plugins to ensure a clean state. This method can be used to
- # populate the instance's environment.
+ # Public: Adds a plugin to Vim's runtime. Initially, Vim is started
+ # without sourcing any plugins to ensure a clean state. This method can be
+ # used to populate the instance's environment.
#
# dir - The base directory of the plugin, the one that contains
# its autoload, plugin, ftplugin, etc. directories.
- # entry_script - The Vim script that's runtime'd to initialize the plugin.
- # Optional.
+ # entry_script - The Vim script that's runtime'd to initialize the plugin
+ # (optional).
#
- # Example:
+ # Examples
#
# vim.add_plugin 'rails', 'plugin/rails.vim'
#
+ # Returns nothing.
def add_plugin(dir, entry_script = nil)
command("set runtimepath+=#{dir}")
command("runtime #{entry_script}") if entry_script
end
- # Invokes one of the basic actions the Vim server supports, sending a key
- # sequence. The keys are sent as-is, so it'd probably be better to use the
- # wrapper methods, #normal, #insert and so on.
+ # Public: Switches Vim to normal mode and types in the given keys.
+ #
+ # Returns nothing.
+ def normal(keys = "")
+ server.remote_send("<C-\\><C-n>#{keys}")
+ end
+
+ # Public: Invokes one of the basic actions the Vim server supports,
+ # sending a key sequence. The keys are sent as-is, so it'd probably be
+ # better to use the wrapper methods, #normal, #insert and so on.
+ #
+ # Returns nothing.
def type(keys)
- invoke_vim '--remote-send', keys
+ server.remote_send(keys)
end
- # Executes the given command in the Vim instance and returns its output,
- # stripping all surrounding whitespace.
- def command(vim_command)
+ # Public: Starts a search in Vim for the given text. The result is that
+ # the cursor is positioned on its first occurrence.
+ #
+ # Returns nothing.
+ def search(text)
normal
+ type "/#{text}<CR>"
+ end
- escaped_command = vim_command.to_s.gsub("'", "''")
- expression = "VimrunnerEvaluateCommandOutput('#{escaped_command}')"
+ # Public: Switches Vim to insert mode and types in the given text.
+ #
+ # Returns nothing.
+ def insert(text)
+ normal "i#{text}"
+ end
- invoke_vim('--remote-expr', expression).strip.tap do |output|
- raise InvalidCommandError if output =~ /^Vim:E\d+:/
- end
+ # Public: Writes the file being edited to disk. Note that you probably
+ # want to set the file's name first by using Runner#edit.
+ def write
+ command :write
end
- # Starts a search in Vim for the given text. The result is that the cursor
- # is positioned on its first occurrence.
- def search(text)
- normal
- type "/#{text}<cr>"
+ # Public: Echo each expression with a space in between.
+ #
+ # Returns the String output.
+ def echo(*expressions)
+ command "echo #{expressions.join(' ')}"
end
- # Sets a setting in Vim. If +value+ is nil, the setting is considered to be
- # a boolean.
+ # Public: Sets a setting in Vim. If +value+ is nil, the setting is
+ # considered to be a boolean.
#
- # Examples:
+ # Examples
#
# vim.set 'expandtab' # invokes ":set expandtab"
# vim.set 'tabstop', 3 # invokes ":set tabstop=3"
@@ -72,34 +86,28 @@ def set(setting, value = nil)
end
end
- # Edits the file +filename+ with Vim.
+ # Public: Edits the file +filename+ with Vim.
#
# Note that this doesn't use the '--remote' Vim flag, it simply types in
- # the command manually. This is necessary to avoid the Vim instance getting
- # focus.
+ # the command manually. This is necessary to avoid the Vim instance
+ # getting focus.
+ #
+ # Returns nothing.
def edit(filename)
command "edit #{filename}"
end
- # Writes the file being edited to disk. Note that you probably want to set
- # the file's name first by using Runner#edit.
- def write
- command :write
- end
-
- # Echo each expression with a space in between.
- def echo(*expressions)
- command "echo #{expressions.join(' ')}"
- end
-
- # Switches Vim to insert mode and types in the given text.
- def insert(text = '')
- normal "i#{text}"
- end
+ # Public: Executes the given command in the Vim instance and returns its
+ # output, stripping all surrounding whitespace.
+ #
+ # Returns the string output.
+ # Raises InvalidCommandError if the command is not recognised by vim.
+ def command(commands)
+ expression = "VimrunnerEvaluateCommandOutput('#{escape(commands)}')"
- # Switches Vim to normal mode and types in the given keys.
- def normal(keys = '')
- type "<c-\\><c-n>#{keys}"
+ server.remote_expr(expression).tap do |output|
+ raise InvalidCommandError if output =~ /^Vim:E\d+:/
+ end
end
# Kills the server it's connected to.
@@ -109,9 +117,8 @@ def kill
private
- def invoke_vim(*args)
- args = [server.vim_path, '--servername', server.name, *args]
- Shell.run *args
+ def escape(string)
+ string.to_s.gsub("'", "''")
end
end
end
View
6 lib/vimrunner/errors.rb
@@ -1,6 +1,12 @@
module Vimrunner
class InvalidCommandError < RuntimeError; end
+ class NoSuitableVimError < RuntimeError
+ def message
+ "No suitable Vim executable could be found for this system."
+ end
+ end
+
class TimeoutError < RuntimeError
def message
"Timed out while waiting for serverlist. Is an X11 server running?"
View
77 lib/vimrunner/platform.rb
@@ -0,0 +1,77 @@
+require "rbconfig"
+
+require "vimrunner/errors"
+
+module Vimrunner
+
+ # Public: The Platform module contains logic for finding a Vim executable
+ # that supports the clientserver functionality on the current system. Its
+ # methods can be used to fetch a Vim path for initializing a Server.
+ #
+ # Examples
+ #
+ # Vimrunner::Platform.vim
+ # # => "gvim"
+ module Platform
+ extend self
+
+ # Public: Looks for a Vim executable that's suitable for the current
+ # platform. Also attempts to find an appropriate GUI vim if terminal ones
+ # are unsuitable.
+ #
+ # Returns the String Vim executable.
+ # Raises NoSuitableVimError if no suitable Vim can be found.
+ def vim
+ vims.find { |vim| suitable?(vim) } or raise NoSuitableVimError
+ end
+
+ # Public: Looks for a GUI Vim executable that's suitable for the current
+ # platform.
+ #
+ # Returns the String Vim executable.
+ # Raises NoSuitableVimError if no suitable Vim can be found.
+ def gvim
+ gvims.find { |gvim| suitable?(gvim) } or raise NoSuitableVimError
+ end
+
+ private
+
+ def gvims
+ if mac?
+ %w( mvim gvim )
+ else
+ %w( gvim )
+ end
+ end
+
+ def vims
+ %w( vim ) + gvims
+ end
+
+ def suitable?(vim)
+ features = features(vim)
+
+ if gui?(vim)
+ features.include?("+clientserver")
+ else
+ features.include?("+clientserver") && features.include?("+xterm_clipboard")
+ end
+ end
+
+ def gui?(vim)
+ executable = File.basename(vim)
+
+ executable[0, 1] == "g" || executable[0, 1] == "m"
+ end
+
+ def features(vim)
+ IO.popen([vim, "--version"]) { |io| io.read.strip }
+ rescue Errno::ENOENT
+ ""
+ end
+
+ def mac?
+ RbConfig::CONFIG["host_os"] =~ /darwin/
+ end
+ end
+end
View
200 lib/vimrunner/server.rb
@@ -1,156 +1,122 @@
-require 'timeout'
-require 'rbconfig'
-require 'pty'
+require "timeout"
+require "pty"
-require 'vimrunner/errors'
-require 'vimrunner/shell'
-require 'vimrunner/client'
+require "vimrunner/errors"
+require "vimrunner/client"
module Vimrunner
- # The Server is a wrapper around the Vim server process that is controlled by
- # clients. It will attempt to start the most appropriate Vim binary available
- # on the system, though there are some options that can control this
- # behaviour. See #initialize for more details.
+ # Public: A Server has the responsibility of starting a Vim process and
+ # communicating with it through the clientserver interface. The process can
+ # be started with "start" and stopped with "kill". A Client would be
+ # necessary as the actual interface, though it is possible to use a Server
+ # directly to invoke --remote commands on its Vim instance.
class Server
- class << self
+ VIMRC = File.expand_path("../../../vim/vimrc", __FILE__)
- # A convenience method that initializes a new server and starts it.
- def start(options = {})
- server = new(options)
- server.start
- end
-
- # The default path to use when starting a server with a terminal Vim. If
- # the "vim" executable is not compiled with clientserver capabilities,
- # the GUI version is started instead.
- def vim_path
- if mac?
- 'mvim'
- else
- 'vim'
- end
- end
-
- # The default path to use when starting a server with the GUI version of
- # Vim. Defaults to "mvim" on a mac and "gvim" on linux.
- def gui_vim_path
- if mac?
- 'mvim'
- else
- 'gvim'
- end
- end
-
- # The path to a vimrc file containing some required vimscript. The server
- # is started with no settings or a vimrc, apart from this one.
- def vimrc_path
- File.join(File.expand_path('../../..', __FILE__), 'vim', 'vimrc')
- end
-
- # Returns true if the current operating system is Mac OS X.
- def mac?
- host_os =~ /darwin/
- end
+ attr_reader :name, :executable
- # Returns true if the given Vim binary is compiled with support for the
- # client/server functionality.
- def clientserver_enabled?(vim_path)
- vim_version = %x[#{vim_path} --version]
- vim_version.include? '+clientserver' and vim_version.include? '+xterm_clipboard'
- end
-
- private
-
- def host_os
- RbConfig::CONFIG['host_os']
- end
+ # Public: Initialize a Server
+ #
+ # executable - a String representing a Vim executable.
+ def initialize(executable)
+ @executable = executable
+ @name = "VIMRUNNER#{rand}"
end
- attr_accessor :pid
- attr_reader :name, :vim_path
-
- # A Server is initialized with two options that control its behaviour:
+ # Public: Start a Server. This spawns a background process.
#
- # :gui - Whether or not to start Vim with a GUI, either 'gvim' or 'mvim'
- # depending on the OS. The default is false, which means that
- # the server will start itself as a terminal instance. Note
- # that, if the terminal Vim doesn't have client/server
- # support, a GUI version will be started anyway.
+ # Examples
#
- # :vim_path - A path to a custom Vim binary. If this option is not set,
- # the server attempts to guess an appropriate one, given the
- # :gui option and the current OS.
+ # client = Vimrunner::Server.new("vim").start
+ # # => #<Vimrunner::Client>
#
- # Note that simply initializing a Server doesn't start the binary. You need
- # to call the #start method to do that.
+ # Vimrunner::Server.new("vim").start do |client|
+ # client.edit("foo")
+ # end
#
- # Examples:
- #
- # server = Server.new # Will start a 'vim' if possible
- # server = Server.new(:gui => true) # Will start a 'gvim' or 'mvim' depending on the OS
- # server = Server.new(:vim_path => '/opt/bin/vim') # Will start a server with the given vim instance
- #
- def initialize(options = {})
- @gui = options[:gui]
- @vim_path = options[:vim_path]
- @name = "VIMRUNNER#{rand.to_s}"
+ # Returns a new Client instance initialized with this Server.
+ # Yields a new Client instance initialized with this Server.
+ def start
+ if block_given?
+ spawn do |r, w, pid|
+ begin
+ wait_until_started
+ @result = yield(new_client)
+ ensure
+ r.close
+ w.close
+ end
+ end
- if not @vim_path or not Server.clientserver_enabled? @vim_path
- @vim_path = Server.vim_path
- end
+ @result
+ else
+ @r, @w, @pid = spawn
+ wait_until_started
- if @gui or not Server.clientserver_enabled? @vim_path
- @gui = true
- @vim_path = Server.gui_vim_path
+ new_client
end
end
- # Starts a Vim server.
- def start
- command = "#{vim_path} -f -u #{Server.vimrc_path} --noplugin --servername #{name}"
-
- if gui?
- @pid = Kernel.spawn(command, [:in, :out, :err] => :close)
- else
- _out, _in, @pid = PTY.spawn(command)
- end
+ # Public: Kills the Vim instance in the background.
+ #
+ # Returns self.
+ def kill
+ @r.close
+ @w.close
+ Process.detach(@pid)
- wait_until_started
self
end
- # A convenience method that returns a new Client instance, connected to
- # the server.
+ # Public: A convenience method that returns a new Client instance,
+ # connected to this server.
+ #
+ # Returns a Client.
def new_client
Client.new(self)
end
- # Returns true if the server is a GUI version of Vim. This can be forced by
- # instantiating the server with :gui => true
- def gui?
- @gui
+ # Public: Retrieves a list of names of currently running Vim servers.
+ #
+ # Returns an Array of String server names currently running.
+ def serverlist
+ execute([executable, "--serverlist"]).split("\n")
end
- # Kills the Vim instance in the background by sending it a TERM signal.
- def kill
- Shell.kill(@pid)
+ # Public: Evaluates an expression in the Vim server and returns the result.
+ # A wrapper around --remote-expr.
+ #
+ # expression - a String with a Vim expression to evaluate.
+ #
+ # Returns the String output of the expression.
+ def remote_expr(expression)
+ execute([executable, "--servername", name, "--remote-expr", expression])
end
- # Retrieve a list of names of currently running Vim servers.
- def serverlist
- %x[#{vim_path} --serverlist].strip.split "\n"
+ # Public: Sends the given keys
+ # A wrapper around --remote-expr.
+ #
+ # keys - a String with a sequence of Vim-compatible keystrokes.
+ #
+ # Returns nothing.
+ def remote_send(keys)
+ execute([executable, "--servername", name, "--remote-send", keys])
end
private
+ def execute(command)
+ IO.popen(command) { |io| io.read.strip }
+ end
+
+ def spawn(&blk)
+ PTY.spawn(executable, "-f", "--servername", name, "-u", VIMRC, &blk)
+ end
+
def wait_until_started
Timeout.timeout(5, TimeoutError) do
- servers = serverlist
- while servers.empty? or not servers.include? name
- sleep 0.1
- servers = serverlist
- end
+ sleep 0.1 while !serverlist.include?(name)
end
end
end
View
24 lib/vimrunner/shell.rb
@@ -1,24 +0,0 @@
-module Vimrunner
-
- # The Shell module contains functions that interact directly with the shell.
- # They're general utilities that help with some of the specific use cases
- # that pop up with the Vim runner.
- module Shell
- extend self
-
- # Executes a shell command, waits until it's finished, and returns the
- # output
- def run(*command)
- IO.popen(command) { |io| io.read.strip }
- end
-
- # Sends a TERM signal to the given PID. Returns true if the process was
- # found and killed, false otherwise.
- def kill(pid)
- Process.kill('TERM', pid)
- true
- rescue Errno::ESRCH
- false
- end
- end
-end
View
21 spec/spec_helper.rb
@@ -1,16 +1,17 @@
-require 'fileutils'
+require "tmpdir"
+require "simplecov"
-ROOT_DIR = File.expand_path('../..', __FILE__)
+SimpleCov.start
RSpec.configure do |config|
- config.before :each do
- FileUtils.cd ROOT_DIR
- FileUtils.rm_rf 'tmp' if File.exists? 'tmp'
- FileUtils.mkdir 'tmp'
- FileUtils.cd 'tmp'
- end
- config.after :each do
- FileUtils.cd ROOT_DIR
+ # Execute each example in its own temporary directory that is automatically
+ # destroyed after every run.
+ config.around do |example|
+ Dir.mktmpdir do |dir|
+ Dir.chdir(dir) do
+ example.call
+ end
+ end
end
end
View
14 spec/vimrunner/client_spec.rb
@@ -1,14 +1,12 @@
-require 'spec_helper'
-require 'vimrunner/client'
-require 'vimrunner/server'
+require "spec_helper"
+require "vimrunner"
module Vimrunner
describe Client do
- let!(:server) { Server.start }
- let!(:client) { Client.new(server) }
+ let!(:client) { Vimrunner.start }
after :each do
- server.kill
+ client.kill
end
it "is instantiated in the current directory" do
@@ -87,9 +85,9 @@ module Vimrunner
end
it "raises an error for a non-existent Vim command" do
- expect do
+ expect {
client.command(:nonexistent)
- end.to raise_error Vimrunner::InvalidCommandError
+ }.to raise_error(InvalidCommandError)
end
end
end
View
20 spec/vimrunner/errors_spec.rb
@@ -0,0 +1,20 @@
+require "spec_helper"
+require "vimrunner/errors"
+
+module Vimrunner
+ describe NoSuitableVimError do
+ it "has a useful message" do
+ expect {
+ raise NoSuitableVimError
+ }.to raise_error("No suitable Vim executable could be found for this system.")
+ end
+ end
+
+ describe TimeoutError do
+ it "has a useful message" do
+ expect {
+ raise TimeoutError
+ }.to raise_error("Timed out while waiting for serverlist. Is an X11 server running?")
+ end
+ end
+end
View
82 spec/vimrunner/platform_spec.rb
@@ -0,0 +1,82 @@
+require "spec_helper"
+require "vimrunner/platform"
+
+module Vimrunner
+ describe Platform do
+ describe "#vim" do
+ it "raises an error if no suitable vim could be found" do
+ Platform.stub(:suitable? => false)
+
+ expect { Platform.vim }.to raise_error(NoSuitableVimError)
+ end
+
+ it "returns vim if it supports clientserver and xterm_clipboard" do
+ Platform.stub(:features => "+clientserver +xterm_clipboard")
+
+ Platform.vim.should == "vim"
+ end
+
+ it "returns gvim on Linux if vim doesn't support xterm_clipboard" do
+ Platform.stub(:mac? => false)
+ Platform.stub(:features) { |vim|
+ case vim
+ when "vim"
+ "+clientserver -xterm_clipboard"
+ when "gvim"
+ "+clientserver"
+ end
+ }
+
+ Platform.vim.should == "gvim"
+ end
+
+ it "returns mvim on Mac OS X if vim doesn't support clientserver" do
+ Platform.stub(:mac? => true)
+ Platform.stub(:features) { |vim|
+ case vim
+ when "vim"
+ "-clientserver -xterm_clipboard"
+ when "mvim"
+ "+clientserver -xterm_clipboard"
+ end
+ }
+
+ Platform.vim.should == "mvim"
+ end
+
+ it "ignores versions of vim that do not exist on the system" do
+ Platform.stub(:mac? => false)
+ IO.stub(:popen) { |command|
+ if command == ["vim", "--version"]
+ raise Errno::ENOENT
+ else
+ "+clientserver"
+ end
+ }
+
+ Platform.vim.should == "gvim"
+ end
+ end
+
+ describe "#gvim" do
+ it "raises an error if no suitable gvim could be found" do
+ Platform.stub(:suitable? => false)
+ expect { Platform.gvim }.to raise_error(NoSuitableVimError)
+ end
+
+ it "returns gvim on Linux" do
+ Platform.stub(:mac? => false)
+ Platform.stub(:features => "+clientserver")
+
+ Platform.gvim.should == "gvim"
+ end
+
+ it "returns mvim on Mac OS X" do
+ Platform.stub(:mac? => true)
+ Platform.stub(:features => "+clientserver")
+
+ Platform.gvim.should == "mvim"
+ end
+ end
+ end
+end
View
173 spec/vimrunner/server_spec.rb
@@ -1,146 +1,85 @@
-require 'spec_helper'
-require 'vimrunner/server'
+require "spec_helper"
+require "vimrunner/server"
+require "vimrunner/platform"
module Vimrunner
describe Server do
- it "can start a vim server process" do
- server = Server.start
- server.serverlist.should include(server.name)
- server.kill
- end
-
- it "can start more than one vim server process" do
- begin
- first = Server.start
- second = Server.start
+ let(:server) { Server.new(Platform.vim) }
- first.serverlist.should include(first.name, second.name)
- ensure
- first.kill
- second.kill
+ describe "#start" do
+ it "starts a vim server process" do
+ begin
+ server.start
+ server.serverlist.should include(server.name)
+ ensure
+ server.kill
+ end
end
- end
- describe "#new_client" do
- around do |example|
+ it "can start more than one vim server process" do
begin
- @server = Server.start
- example.call
+ first = Server.new(Platform.vim)
+ second = Server.new(Platform.vim)
+
+ first.start
+ second.start
+
+ first.serverlist.should include(first.name, second.name)
ensure
- @server.kill
+ first.kill
+ second.kill
+ end
+ end
+
+ it "can start a vim server process with a block" do
+ server.start do |client|
+ server.serverlist.should include(server.name)
end
end
+ end
+ describe "#new_client" do
it "returns a client" do
- @server.new_client.should be_a(Client)
+ server.new_client.should be_a(Client)
end
it "is attached to the server" do
- @server.new_client.server.should == @server
+ server.new_client.server.should == server
end
end
- describe "#vim_path" do
- context "with a clientserver-enabled vim" do
- before :each do
- Server.stub(:clientserver_enabled? => true)
- end
-
- it "can be explicitly overridden" do
- server = Server.new(:vim_path => '/opt/local/bin/vim')
- server.vim_path.should eq '/opt/local/bin/vim'
- end
-
- context "with GUI" do
- let(:server) { Server.new(:gui => true) }
-
- it "defaults to 'mvim' on Mac OS X" do
- Server.stub(:mac? => true)
- server.vim_path.should eq 'mvim'
- end
-
- it "defaults to 'gvim' on Linux" do
- Server.stub(:mac? => false)
- server.vim_path.should eq 'gvim'
- end
+ describe "#remote_expr" do
+ it "uses the server's executable to send remote expressions" do
+ server.should_receive(:execute).
+ with([server.executable, "--servername", server.name,
+ "--remote-expr", "version"])
- it "is registered as a GUI" do
- server.should be_gui
- end
- end
-
- context "without GUI" do
- let(:server) { Server.new }
-
- it "defaults to 'mvim' on Mac OS X" do
- Server.stub(:mac? => true)
- server.vim_path.should eq 'mvim'
- end
-
- it "defaults to 'vim' on Linux" do
- Server.stub(:mac? => false)
- server.vim_path.should eq 'vim'
- end
-
- it "is not registered as a GUI" do
- server.should_not be_gui
- end
- end
+ server.remote_expr("version")
end
+ end
- context "without a clientserver-enabled vim" do
- before :each do
- Server.stub(:clientserver_enabled? => false)
- end
-
- it "will use gvim instead of the override on Linux" do
- Server.stub(:mac? => false)
- server = Server.new(:vim_path => '/opt/local/bin/vim')
- server.vim_path.should eq 'gvim'
- end
-
- it "will use mvim instead of the override on Mac OS X" do
- Server.stub(:mac? => true)
- server = Server.new(:vim_path => '/opt/local/bin/vim')
- server.vim_path.should eq 'mvim'
- end
-
- context "with GUI" do
- let(:server) { Server.new(:gui => true) }
-
- it "defaults to 'mvim' on Mac OS X" do
- Server.stub(:mac? => true)
- server.vim_path.should eq 'mvim'
- end
-
- it "defaults to 'gvim' on Linux" do
- Server.stub(:mac? => false)
- server.vim_path.should eq 'gvim'
- end
+ describe "#remote_send" do
+ it "uses the server's executable to send remote keys" do
+ server.should_receive(:execute).
+ with([server.executable, "--servername", server.name,
+ "--remote-send", "ihello"])
- it "is registered as a GUI" do
- server.should be_gui
- end
- end
+ server.remote_send("ihello")
+ end
+ end
- context "without GUI" do
- let(:server) { Server.new }
+ describe "#serverlist" do
+ it "uses the server's executable to list servers" do
+ server.should_receive(:execute).
+ with([server.executable, "--serverlist"]).and_return("VIM")
- it "falls back to gvim on Linux" do
- Server.stub(:clientserver_enabled? => false, :mac? => false)
- server.vim_path.should eq 'gvim'
- end
+ server.serverlist
+ end
- it "falls back to mvim on Mac OS X" do
- Server.stub(:clientserver_enabled? => false, :mac? => true)
- server.vim_path.should eq 'mvim'
- end
+ it "splits the servers into an array" do
+ server.stub(:execute => "VIM\nVIM2")
- it "is registered as a GUI" do
- Server.stub(:clientserver_enabled? => false, :mac? => false)
- server.should be_gui
- end
- end
+ server.serverlist.should == ["VIM", "VIM2"]
end
end
end
View
26 spec/vimrunner/shell_spec.rb
@@ -1,26 +0,0 @@
-require 'spec_helper'
-require 'vimrunner/shell'
-
-module Vimrunner
- describe Shell do
- it "can execute an external command and return the output" do
- Shell.run('echo', 'foo').should eq 'foo'
- Shell.run('echo', 'bar baz').should eq 'bar baz'
- end
-
- it "can kill a process by its PID" do
- pid = Process.fork { sleep 1; exit(42) }
-
- Shell.kill(pid).should be_true
-
- Process.wait(pid)
- $?.exitstatus.should_not eq 42
- end
-
- it "can safely attempt to kill a non-existent process" do
- pid = Process.fork { exit }
- Process.wait(pid)
- Shell.kill(pid).should be_false
- end
- end
-end
View
31 spec/vimrunner_spec.rb
@@ -0,0 +1,31 @@
+require "spec_helper"
+require "vimrunner"
+
+describe Vimrunner do
+ let(:server) { double('server').as_null_object }
+
+ describe "#start" do
+ before do
+ Vimrunner::Platform.stub(:vim => "vim")
+ end
+
+ it "defaults to using the platform vim" do
+ Vimrunner::Server.should_receive(:new).with("vim").and_return(server)
+
+ Vimrunner.start
+ end
+ end
+
+ describe "#start_gvim" do
+ before do
+ Vimrunner::Platform.stub(:gvim => "gvim")
+ end
+
+ it "defaults to using the platform gvim" do
+ Vimrunner::Server.should_receive(:new).with("gvim").and_return(server)
+
+ Vimrunner.start_gvim
+ end
+ end
+end
+
View
5 vimrunner.gemspec
@@ -7,15 +7,16 @@ Gem::Specification.new do |s|
s.authors = ['Andrew Radev']
s.email = ['andrey.radev@gmail.com']
s.homepage = 'http://github.com/AndrewRadev/vimrunner'
- s.summary = 'Lets you control a vim instance through ruby'
+ s.summary = 'Lets you control a Vim instance through Ruby'
s.description = <<-D
Using Vim's client/server functionality, this library exposes a way to
spawn a Vim instance and control it programatically. Apart from being a fun
- party trick, this could be used to do integration testing on vimscript.
+ party trick, this can be used to integration test Vim script.
D
s.add_development_dependency 'rake'
s.add_development_dependency 'rdoc'
+ s.add_development_dependency 'simplecov'
s.add_development_dependency 'rspec', '>= 2.0.0'
s.required_rubygems_version = '>= 1.3.6'

No commit comments for this range

Something went wrong with that request. Please try again.