scide 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/scide/command.rb +94 -39
- data/lib/scide/commands/edit.rb +27 -3
- data/lib/scide/commands/run.rb +16 -3
- data/lib/scide/commands/show.rb +22 -1
- data/lib/scide/commands/tail.rb +27 -3
- data/lib/scide/config.rb +49 -19
- data/lib/scide/global.rb +18 -3
- data/lib/scide/opts.rb +7 -0
- data/lib/scide/overmind.rb +28 -4
- data/lib/scide/project.rb +46 -11
- data/lib/scide/screen.rb +50 -16
- data/lib/scide/window.rb +55 -10
- data/lib/scide.rb +57 -9
- data/scide.gemspec +7 -2
- data/spec/command_spec.rb +87 -0
- data/spec/commands/edit_spec.rb +19 -0
- data/spec/commands/run_spec.rb +9 -0
- data/spec/commands/show_spec.rb +15 -0
- data/spec/commands/tail_spec.rb +14 -0
- metadata +22 -17
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/lib/scide/command.rb
CHANGED
@@ -1,69 +1,124 @@
|
|
1
1
|
module Scide
|
2
2
|
|
3
|
+
# A command to be used in a GNU Screen window. There are several
|
4
|
+
# command implementations (show command, run command, tail file, etc).
|
5
|
+
# See under Scide::Commands.
|
3
6
|
class Command
|
4
7
|
|
5
|
-
|
8
|
+
# The options given to this command. These are built by merging
|
9
|
+
# global options, project options and window options.
|
10
|
+
attr_reader :options
|
6
11
|
|
12
|
+
# Returns a new command for the given window.
|
13
|
+
#
|
14
|
+
# ==== Arguments
|
15
|
+
# * <tt>window</tt> - The window in which the command will be used.
|
16
|
+
# Command options are retrieved from Scide::Window#options. See
|
17
|
+
# #initialize.
|
18
|
+
# * <tt>contents</tt> - The command configuration (String or Hash).
|
19
|
+
#
|
20
|
+
# ==== String Initialization
|
21
|
+
# The string must be in the format <tt>COMMAND [CONTENTS]</tt>.
|
22
|
+
#
|
23
|
+
# <tt>TYPE</tt> is the name of the command class under
|
24
|
+
# Scide::Commands, in uppercase camelcase. For example, <tt>TAIL</tt>
|
25
|
+
# corresponds to Scide::Commands::Tail, <tt>MY_COMMAND</tt> would
|
26
|
+
# correspond to Scide::Commands::MyCommand.
|
27
|
+
#
|
28
|
+
# <tt>CONTENTS</tt> is the contents of the command.
|
29
|
+
#
|
30
|
+
# ==== Hash Initialization
|
31
|
+
# The following options can be given:
|
32
|
+
# * <tt>:command => string</tt> is the same <tt>COMMAND</tt> as
|
33
|
+
# for string initialization above.
|
34
|
+
# * <tt>:contents => string or other</tt> is the same <tt>CONTENTS</tt>
|
35
|
+
# as for string initialization above. Typically this is only a
|
36
|
+
# string, but more advanced commands might be initialized with
|
37
|
+
# arrays or hashes.
|
38
|
+
def self.resolve window, contents
|
7
39
|
if contents.kind_of? Hash
|
8
|
-
|
9
|
-
properties = properties.merge contents[:properties] if contents.key? :properties
|
10
|
-
end
|
11
|
-
|
12
|
-
klass, contents = if contents.kind_of? Hash
|
13
|
-
resolve_from_hash contents, properties, options
|
40
|
+
resolve_from_hash window, contents
|
14
41
|
elsif contents.kind_of? String
|
15
|
-
resolve_from_string
|
42
|
+
resolve_from_string window, contents
|
43
|
+
else
|
44
|
+
raise ArgumentError, 'command must be a string or a hash'
|
16
45
|
end
|
17
|
-
|
18
|
-
klass.new contents, properties, build_options(options, klass)
|
19
46
|
end
|
20
47
|
|
21
|
-
|
22
|
-
|
23
|
-
|
48
|
+
# Returns a new command with the given options.
|
49
|
+
#
|
50
|
+
# ==== Arguments
|
51
|
+
# * <tt>contents</tt> - The contents of the command. Typically this
|
52
|
+
# is only a string, but more advanced commands might be initialized
|
53
|
+
# with arrays or hashes. By default, the contents can be retrieved
|
54
|
+
# as a string with #text_with_options.
|
55
|
+
# * <tt>options</tt> - Options that can be used in the string contents
|
56
|
+
# of the command. See #text_with_options.
|
57
|
+
def initialize contents, options = {}
|
58
|
+
|
59
|
+
# fill text only if it's not already there, in case a subclass does
|
60
|
+
# some initialization work before calling super
|
61
|
+
@text ||= contents.to_s
|
62
|
+
|
63
|
+
# merge given options to the already initialized ones, if any
|
64
|
+
@options = (@options || {}).merge options
|
24
65
|
end
|
25
66
|
|
67
|
+
# Returns a representation of this command as a GNU Screen
|
68
|
+
# configuration fragment.
|
69
|
+
#
|
70
|
+
# This default implementation raises an error and must be
|
71
|
+
# overriden by subclasses.
|
26
72
|
def to_screen
|
27
73
|
raise 'Use a subclass'
|
28
74
|
end
|
29
75
|
|
30
|
-
|
31
|
-
|
76
|
+
# Returns the text of this command with filtered option placeholders.
|
77
|
+
#
|
78
|
+
# ==== Examples
|
79
|
+
# com_text = 'tail %{tail} -f file.txt -c %{foo}'
|
80
|
+
# com = Scide::Command.new com_text, :tail => '-n 1000', :foo => 400
|
81
|
+
#
|
82
|
+
# com.text_with_options #=> 'tail -n 1000 -f file.txt -c 400'
|
83
|
+
def text_with_options
|
84
|
+
@text.dup.tap do |s|
|
85
|
+
@options.each_pair do |key, value|
|
86
|
+
s.gsub! /\%\{#{Regexp.escape key}\}/, value.to_s
|
87
|
+
end
|
88
|
+
end
|
32
89
|
end
|
33
90
|
|
34
91
|
private
|
35
92
|
|
36
|
-
|
37
|
-
|
38
|
-
|
93
|
+
# Returns a new command for the given window. The given
|
94
|
+
# contents are a hash. See Scide::Command.resolve.
|
95
|
+
def self.resolve_from_hash window, contents
|
96
|
+
begin
|
97
|
+
klass = Scide::Commands.const_get contents[:command].downcase.camelize
|
98
|
+
klass.new contents[:contents], window.options.dup
|
99
|
+
rescue NameError => err
|
100
|
+
raise ArgumentError, "unknown '#{contents[:command]}' command type"
|
101
|
+
end
|
39
102
|
end
|
40
103
|
|
41
|
-
|
104
|
+
# Returns a new command for the given window. The given
|
105
|
+
# contents are a string. See Scide::Command.resolve.
|
106
|
+
def self.resolve_from_string window, contents
|
42
107
|
klass_name, text = contents.split /\s+/, 2
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
klass_name = klass.name.demodulize.downcase
|
49
|
-
current_options = options.try(:[], klass_name)
|
50
|
-
current_klass = klass
|
51
|
-
while current_klass != Scide::Command and current_options.blank?
|
52
|
-
current_klass = current_klass.superclass
|
53
|
-
current_options = options.try(:[], current_klass.name.demodulize.downcase)
|
108
|
+
begin
|
109
|
+
klass = Scide::Commands.const_get klass_name.downcase.camelize
|
110
|
+
klass.new text, window.options.dup
|
111
|
+
rescue NameError => err
|
112
|
+
raise ArgumentError, "unknown '#{klass_name}' command type"
|
54
113
|
end
|
55
|
-
current_options
|
56
114
|
end
|
115
|
+
end
|
57
116
|
|
58
|
-
|
59
|
-
|
60
|
-
@properties.each_pair do |key, value|
|
61
|
-
s.gsub! /\%\{#{key}\}/, value
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
117
|
+
# Module containing scide command classes.
|
118
|
+
module Commands
|
65
119
|
end
|
66
120
|
end
|
67
121
|
|
122
|
+
# load pre-defined commands
|
68
123
|
deps_dir = File.join File.dirname(__FILE__), 'commands'
|
69
|
-
%w( run tail
|
124
|
+
%w( show run tail edit ).each{ |dep| require File.join(deps_dir, dep) }
|
data/lib/scide/commands/edit.rb
CHANGED
@@ -2,11 +2,35 @@ module Scide
|
|
2
2
|
|
3
3
|
module Commands
|
4
4
|
|
5
|
+
# Edits a file with the default editor (<tt>$EDITOR</tt>).
|
6
|
+
#
|
7
|
+
# ==== Configuration Example
|
8
|
+
# # this YAML configuration,
|
9
|
+
# projects:
|
10
|
+
# project1:
|
11
|
+
# options:
|
12
|
+
# edit: '-c MyVimCommand'
|
13
|
+
# windows:
|
14
|
+
# - "window1 EDIT $HOME/fubar.txt"
|
15
|
+
#
|
16
|
+
# # will produce the following command in window1:
|
17
|
+
# $EDITOR -c MyVimCommand $HOME/fubar.txt
|
5
18
|
class Edit < Scide::Commands::Run
|
6
19
|
|
7
|
-
|
8
|
-
|
9
|
-
|
20
|
+
# Returns a new edit command.
|
21
|
+
#
|
22
|
+
# See class definition for examples.
|
23
|
+
#
|
24
|
+
# ==== Arguments
|
25
|
+
# * <tt>contents</tt> - The file to edit.
|
26
|
+
# * <tt>options</tt> - Options that can be used in the contents
|
27
|
+
# of the command.
|
28
|
+
#
|
29
|
+
# ==== Options
|
30
|
+
# * <tt>:edit => string</tt> - Arguments to the editor.
|
31
|
+
def initialize contents, options = {}
|
32
|
+
super contents, options
|
33
|
+
@text = [ '$EDITOR', options[:edit].to_s, @text.to_s ].select(&:present?).join(' ')
|
10
34
|
end
|
11
35
|
end
|
12
36
|
end
|
data/lib/scide/commands/run.rb
CHANGED
@@ -2,10 +2,23 @@ module Scide
|
|
2
2
|
|
3
3
|
module Commands
|
4
4
|
|
5
|
-
|
5
|
+
# Runs a command.
|
6
|
+
#
|
7
|
+
# ==== Configuration Example
|
8
|
+
# # this YAML configuration,
|
9
|
+
# projects:
|
10
|
+
# project1:
|
11
|
+
# windows:
|
12
|
+
# - "window1 RUN rails server"
|
13
|
+
#
|
14
|
+
# # will produce the following command in window1:
|
15
|
+
# rails server
|
16
|
+
class Run < Scide::Commands::Show
|
6
17
|
|
7
|
-
|
8
|
-
|
18
|
+
# Appends a carriage return to the command so that
|
19
|
+
# it will not only be shown but also executed.
|
20
|
+
def text_with_options
|
21
|
+
"#{super}\\012"
|
9
22
|
end
|
10
23
|
end
|
11
24
|
end
|
data/lib/scide/commands/show.rb
CHANGED
@@ -2,10 +2,31 @@ module Scide
|
|
2
2
|
|
3
3
|
module Commands
|
4
4
|
|
5
|
+
# Prepares and shows a command but do not run it.
|
6
|
+
#
|
7
|
+
# ==== Configuration Example
|
8
|
+
# # this YAML configuration,
|
9
|
+
# projects:
|
10
|
+
# project1:
|
11
|
+
# options:
|
12
|
+
# host: 127.0.0.1
|
13
|
+
# windows:
|
14
|
+
# - "window1 SHOW ssh %{host}"
|
15
|
+
#
|
16
|
+
# # will produce the following command in window1:
|
17
|
+
# ssh 127.0.0.1
|
5
18
|
class Show < Scide::Command
|
6
19
|
|
20
|
+
def initialize contents, options = {}
|
21
|
+
super contents, options
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns a configuration fragment that will put
|
25
|
+
# this command GNU \Screen window without running it.
|
26
|
+
# This will use screen's <tt>stuff</tt> command to
|
27
|
+
# put the text in the window.
|
7
28
|
def to_screen
|
8
|
-
%|stuff "#{
|
29
|
+
%|stuff "#{text_with_options}"|
|
9
30
|
end
|
10
31
|
end
|
11
32
|
end
|
data/lib/scide/commands/tail.rb
CHANGED
@@ -2,11 +2,35 @@ module Scide
|
|
2
2
|
|
3
3
|
module Commands
|
4
4
|
|
5
|
+
# Tails a file.
|
6
|
+
#
|
7
|
+
# ==== Configuration Example
|
8
|
+
# # this YAML configuration,
|
9
|
+
# projects:
|
10
|
+
# project1:
|
11
|
+
# options:
|
12
|
+
# tail: '-n 1000'
|
13
|
+
# windows:
|
14
|
+
# - "window1 TAIL $HOME/fubar.txt"
|
15
|
+
#
|
16
|
+
# # will produce the following command in window1:
|
17
|
+
# tail -n 1000 -f $HOME/fubar.txt
|
5
18
|
class Tail < Scide::Commands::Run
|
6
19
|
|
7
|
-
|
8
|
-
|
9
|
-
|
20
|
+
# Returns a new tail command.
|
21
|
+
#
|
22
|
+
# See class definition for examples.
|
23
|
+
#
|
24
|
+
# ==== Arguments
|
25
|
+
# * <tt>contents</tt> - The file to tail.
|
26
|
+
# * <tt>options</tt> - Options that can be used in the
|
27
|
+
# contents of the command.
|
28
|
+
#
|
29
|
+
# ==== Options
|
30
|
+
# * <tt>tail => string</tt> - Arguments to tail.
|
31
|
+
def initialize contents, options = {}
|
32
|
+
super contents, options
|
33
|
+
@text = [ 'tail', options[:tail].to_s, '-f', @text.to_s ].select(&:present?).join(' ')
|
10
34
|
end
|
11
35
|
end
|
12
36
|
end
|
data/lib/scide/config.rb
CHANGED
@@ -1,18 +1,47 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
|
-
CONFIG_FILE = File.join File.expand_path('~'), '.scide', 'config.yml'
|
4
|
-
|
5
3
|
module Scide
|
6
4
|
|
5
|
+
# Complete scide configuration as an object graph.
|
7
6
|
class Config
|
7
|
+
|
8
|
+
# The file from which the configuration is normally loaded.
|
9
|
+
# This defaults to <tt>$HOME/.scide/config.yml</tt>.
|
10
|
+
DEFAULT_CONFIG_FILE = File.join File.expand_path('~'), '.scide', 'config.yml'
|
11
|
+
|
12
|
+
# The file from which this configuration will be loaded.
|
8
13
|
attr_accessor :file
|
9
|
-
|
14
|
+
|
15
|
+
# GNU Screen options. Accessible after calling #load!.
|
16
|
+
attr_reader :screen
|
10
17
|
|
18
|
+
# The global configuration. Accessible after calling #load!.
|
19
|
+
attr_reader :global
|
20
|
+
|
21
|
+
# The project definitions (windows, option overrides, etc). Accessible
|
22
|
+
# after calling #load!.
|
23
|
+
attr_reader :projects
|
24
|
+
|
25
|
+
# Returns an empty configuration.
|
26
|
+
#
|
27
|
+
# ==== Arguments
|
28
|
+
# * <tt>file</tt> - The file from which to load the configuration. If not
|
29
|
+
# given, this defaults to DEFAULT_CONFIG_FILE.
|
11
30
|
def initialize file = nil
|
12
|
-
@file = file.try(:to_s) ||
|
31
|
+
@file = file.try(:to_s) || DEFAULT_CONFIG_FILE
|
13
32
|
end
|
14
33
|
|
15
|
-
|
34
|
+
# Loads this configuration. This will read from #file and parse the contents
|
35
|
+
# as YAML. Configuration elements can then be retrieved with #global,
|
36
|
+
# #projects and #screen.
|
37
|
+
#
|
38
|
+
# ==== Errors
|
39
|
+
# * <tt>config_not_found</tt> - #file does not exist.
|
40
|
+
# * <tt>config_not_readable</tt> - #file cannot be read by the user running scide.
|
41
|
+
# * <tt>malformed_config</tt> - #file contains malformed YAML.
|
42
|
+
# * <tt>invalid_config</tt> - #file contains invalid configuration (see README).
|
43
|
+
# * <tt>unexpected</tt> - #file could not be read.
|
44
|
+
def load!
|
16
45
|
|
17
46
|
Scide.fail :config_not_found, "ERROR: expected to find configuration at #{@file}" unless File.exists? @file
|
18
47
|
Scide.fail :config_not_readable, "ERROR: configuration #{@file} is not readable" unless File.readable? @file
|
@@ -34,26 +63,27 @@ module Scide
|
|
34
63
|
# laziness
|
35
64
|
@config = HashWithIndifferentAccess.new @config
|
36
65
|
|
66
|
+
invalid_config 'screen configuration must be a hash' unless @config[:screen].nil? or @config[:screen].kind_of?(Hash)
|
67
|
+
invalid_config 'projects configuration must be a hash' unless @config[:projects].nil? or @config[:projects].kind_of?(Hash)
|
68
|
+
|
37
69
|
begin
|
38
|
-
|
39
|
-
|
70
|
+
@screen = @config[:screen]
|
71
|
+
@global = Scide::Global.new @config[:global]
|
72
|
+
@projects = @config[:projects].inject(HashWithIndifferentAccess.new) do |memo,obj|
|
73
|
+
memo[obj[0]] = Scide::Project.new @global, obj[0], obj[1]; memo
|
74
|
+
end
|
75
|
+
rescue ArgumentError => err
|
40
76
|
invalid_config err
|
41
77
|
end
|
42
|
-
|
43
|
-
@global = Scide::Global.new @config[:global]
|
44
|
-
@screen = @config[:screen]
|
45
|
-
@projects = @config[:projects].inject(HashWithIndifferentAccess.new) do |memo,obj|
|
46
|
-
memo[obj[0].to_sym] = Scide::Project.new obj[1], obj[0], @global; memo
|
47
|
-
end
|
48
78
|
end
|
49
79
|
|
50
|
-
|
51
|
-
raise 'global configuration must be a hash' if @config[:global] and !@config[:global].kind_of?(Hash)
|
52
|
-
raise 'configuration must contain a hash of projects' unless @config[:projects].kind_of? Hash
|
53
|
-
end
|
80
|
+
private
|
54
81
|
|
55
|
-
|
56
|
-
|
82
|
+
# Causes scide to fail with an <tt>invalid_config</tt> error (see Scide#fail).
|
83
|
+
# Builds a complete error message containing the full path to the
|
84
|
+
# configuration file and the given message.
|
85
|
+
def invalid_config msg
|
86
|
+
Scide.fail :invalid_config, "ERROR: configuration #{@file} is invalid.\n #{msg}"
|
57
87
|
end
|
58
88
|
end
|
59
89
|
end
|
data/lib/scide/global.rb
CHANGED
@@ -1,13 +1,28 @@
|
|
1
1
|
module Scide
|
2
2
|
|
3
|
+
# Global scide options (base path for all projects,
|
4
|
+
# shared options).
|
3
5
|
class Global
|
4
|
-
|
6
|
+
|
7
|
+
# The path under which all projects reside by default.
|
8
|
+
# (Can be overriden at the project level.)
|
9
|
+
attr_reader :path
|
10
|
+
|
11
|
+
# Global options shared by all projects.
|
12
|
+
attr_reader :options
|
5
13
|
|
14
|
+
# Builds global options.
|
15
|
+
#
|
16
|
+
# ==== Arguments
|
17
|
+
# * <tt>contents</tt> - The global options hash.
|
6
18
|
def initialize contents
|
7
|
-
|
8
|
-
|
19
|
+
raise ArgumentError, 'global configuration must be a hash' unless contents.kind_of? Hash
|
20
|
+
|
21
|
+
@options = contents[:options] || {}
|
9
22
|
|
23
|
+
# default to home directory
|
10
24
|
@path = contents[:path].try(:to_s) || File.expand_path('~')
|
25
|
+
# expand from home directory unless absolute
|
11
26
|
@path = File.join File.expand_path('~'), @path unless @path.match /^\//
|
12
27
|
end
|
13
28
|
end
|
data/lib/scide/opts.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
module Scide
|
2
2
|
|
3
|
+
# Pre-configured scide option parser.
|
3
4
|
class Opts < Upoj::Opts
|
4
5
|
|
6
|
+
# Returns the scide option parser. Run scide with <tt>--usage</tt>
|
7
|
+
# to see available options.
|
5
8
|
def initialize
|
6
9
|
super({
|
7
10
|
:banner => {
|
@@ -17,6 +20,10 @@ module Scide
|
|
17
20
|
help!.usage!
|
18
21
|
end
|
19
22
|
|
23
|
+
# Parses the given arguments.
|
24
|
+
#
|
25
|
+
# Causes scide to fail with an <tt>invalid_argument</tt> error (see Scide#fail)
|
26
|
+
# if an argument is invalid.
|
20
27
|
def parse! args
|
21
28
|
begin
|
22
29
|
super args
|
data/lib/scide/overmind.rb
CHANGED
@@ -1,27 +1,51 @@
|
|
1
1
|
module Scide
|
2
2
|
|
3
|
+
# Utility class to run scide in a script.
|
3
4
|
class Overmind
|
4
5
|
|
6
|
+
# Awakens the overmind.
|
5
7
|
def initialize
|
6
8
|
@cli = Scide::Opts.new
|
7
9
|
@config = Scide::Config.new
|
8
10
|
end
|
9
11
|
|
12
|
+
# Parses command-line arguments and loads the configuration file.
|
13
|
+
# Any error will be run through Scide.fail.
|
10
14
|
def brood
|
11
15
|
@cli.parse! ARGV
|
12
16
|
@config.file = @cli.funnel[:config] if @cli.funnel.key? :config
|
13
|
-
@config.load
|
17
|
+
@config.load!
|
14
18
|
@initialized = true
|
15
19
|
self
|
16
20
|
end
|
17
21
|
|
22
|
+
# Runs GNU \Screen with the project given as argument.
|
23
|
+
# The <tt>--dry-run</tt> option will cause scide to print the
|
24
|
+
# resulting configuration instead of running it.
|
25
|
+
#
|
26
|
+
# ==== Errors
|
27
|
+
# * <tt>not_initialized</tt> - If #brood was not called.
|
28
|
+
# * <tt>unknown_project</tt> - If the given project is not found
|
29
|
+
# in the configuration file.
|
30
|
+
# * <tt>screen_not_found</tt> - If the GNU \Screen binary is not
|
31
|
+
# found with <tt>which</tt>.
|
18
32
|
def dominate
|
19
33
|
|
20
|
-
Scide.fail :not_initialized, 'ERROR: call #brood to initialize' unless @initialized
|
34
|
+
Scide.fail :not_initialized, 'ERROR: call #brood to initialize.' unless @initialized
|
21
35
|
|
22
36
|
project_key = ARGV.shift
|
23
|
-
|
24
|
-
|
37
|
+
|
38
|
+
if project_key.blank?
|
39
|
+
available_projects = @config.projects.keys.join(', ')
|
40
|
+
Scide.fail :invalid_argument, "You must choose a project. Available projects: #{available_projects}."
|
41
|
+
end
|
42
|
+
|
43
|
+
unless @config.projects.key? project_key
|
44
|
+
Scide.fail :unknown_project, "ERROR: there is no project '#{project_key}' in configuration #{@config.file}."
|
45
|
+
end
|
46
|
+
|
47
|
+
screen = Scide::Screen.new @config.projects[project_key], @config.screen
|
48
|
+
screen.check_binary
|
25
49
|
|
26
50
|
if @cli.funnel[:'dry-run']
|
27
51
|
puts
|
data/lib/scide/project.rb
CHANGED
@@ -1,29 +1,64 @@
|
|
1
1
|
module Scide
|
2
2
|
|
3
|
+
# Scide configuration for one project.
|
3
4
|
class Project
|
4
|
-
attr_accessor :properties, :options, :path
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
# The project key in the projects configuration hash.
|
7
|
+
attr_reader :key
|
8
8
|
|
9
|
+
# The path where the project is located. See #initialize.
|
10
|
+
attr_reader :path
|
11
|
+
|
12
|
+
# Project-specific options. Can be used by commands. See #initialize.
|
13
|
+
attr_reader :options
|
14
|
+
|
15
|
+
# Returns a project configuration.
|
16
|
+
#
|
17
|
+
# If not given in the project hash, #path is built by joining
|
18
|
+
# the global path and <tt>key</tt>.
|
19
|
+
#
|
20
|
+
# ==== Arguments
|
21
|
+
# * <tt>global</tt> - The global configuration.
|
22
|
+
# * <tt>key</tt> - The key identifying the project. This is the
|
23
|
+
# key in the projects hash.
|
24
|
+
# * <tt>contents</tt> - The project hash.
|
25
|
+
#
|
26
|
+
# ==== Project Options
|
27
|
+
#
|
28
|
+
# #options is built by merging the options given in the project
|
29
|
+
# hash with the global options.
|
30
|
+
#
|
31
|
+
# The following default options are added if not given:
|
32
|
+
# * <tt>name</tt> - Defaults to the project key.
|
33
|
+
# * <tt>path</tt> - The path where the project is located.
|
34
|
+
def initialize global, key, contents
|
35
|
+
raise ArgumentError, "project '#{key}' must be a hash" unless contents.kind_of? Hash
|
36
|
+
raise ArgumentError, "windows of project '#{key}' must be an array" unless contents[:windows].nil? or contents[:windows].kind_of?(Array)
|
37
|
+
raise ArgumentError, "options of project '#{key}' must be a hash" unless contents[:options].nil? or contents[:options].kind_of?(Hash)
|
38
|
+
|
39
|
+
@global, @key = global, key
|
40
|
+
|
41
|
+
# path defaults to project key
|
9
42
|
@path = contents[:path].try(:to_s) || key.to_s
|
43
|
+
# expand from home directory if not absolute
|
10
44
|
@path = File.join global.path, @path unless @path.match /^\//
|
11
45
|
|
12
|
-
@
|
13
|
-
@
|
14
|
-
|
15
|
-
@options = global.options.merge(contents[:options] || {})
|
46
|
+
@options = global.options.dup.merge(contents[:options] || {})
|
47
|
+
@options[:name] ||= key
|
48
|
+
@options[:path] ||= @path
|
16
49
|
|
17
|
-
@windows = []
|
18
|
-
contents[:windows].each do |w|
|
19
|
-
@windows << Scide::Window.new(w, self)
|
20
|
-
end
|
50
|
+
@windows = contents[:windows].collect{ |w| Scide::Window.new self, w }
|
21
51
|
end
|
22
52
|
|
53
|
+
# Returns a representation of this project as a GNU Screen
|
54
|
+
# configuration fragment. Returns nil if this project has
|
55
|
+
# no configured windows.
|
23
56
|
def to_screen
|
57
|
+
return nil if @windows.blank?
|
24
58
|
String.new.tap do |s|
|
25
59
|
@windows.each_with_index do |w,i|
|
26
60
|
s << w.to_screen(i)
|
61
|
+
s << "\n" if i != @windows.length - 1
|
27
62
|
end
|
28
63
|
end
|
29
64
|
end
|
data/lib/scide/screen.rb
CHANGED
@@ -1,57 +1,91 @@
|
|
1
1
|
require 'tempfile'
|
2
2
|
|
3
|
-
DEFAULT_HARDSTATUS = '%{= kG}[ %{G}%H %{g}][%= %{=kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B}%Y-%m-%d %{W}%c %{g}]'
|
4
|
-
|
5
3
|
module Scide
|
6
4
|
|
5
|
+
# Configuration of a GNU Screen session (windows for a specific project).
|
6
|
+
#
|
7
|
+
# The configuration will disable the startup message and display a hardstatus line.
|
8
|
+
# It will also display the windows of the given project.
|
7
9
|
class Screen
|
10
|
+
|
11
|
+
# The default screen hardstatus line.
|
12
|
+
DEFAULT_HARDSTATUS = '%{= kG}[ %{G}%H %{g}][%= %{=kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B}%Y-%m-%d %{W}%c %{g}]'
|
8
13
|
|
9
|
-
|
10
|
-
|
14
|
+
# Returns a screen configuration for the given project.
|
15
|
+
#
|
16
|
+
# ==== Arguments
|
17
|
+
# * <tt>project</tt> - The project.
|
18
|
+
# * <tt>options</tt> - Screen-specific options (see below).
|
19
|
+
#
|
20
|
+
# ==== Options
|
21
|
+
# * <tt>binary</tt> - Screen binary (defaults to <tt>screen</tt>).
|
22
|
+
# * <tt>args</tt> - Command-line arguments that will be given to screen (e.g. <tt>-U</tt> for unicode).
|
23
|
+
# * <tt>hardstatus</tt> - Hardstatus line configuration (defaults to #DEFAULT_HARDSTATUS).
|
24
|
+
def initialize project, options
|
25
|
+
raise ArgumentError, 'screen configuration must be a hash' unless options.nil? or options.kind_of?(Hash)
|
11
26
|
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
@project = config.projects[project_key]
|
27
|
+
@project = project
|
28
|
+
@options = options || {}
|
16
29
|
end
|
17
30
|
|
31
|
+
# Runs screen with this configuration.
|
32
|
+
#
|
33
|
+
# The configuration is saved to a temporary file, then removed.
|
18
34
|
def run
|
19
35
|
file = Tempfile.new 'scide'
|
20
|
-
save file
|
36
|
+
save file.path
|
21
37
|
system to_command(file.path)
|
22
38
|
file.unlink
|
23
39
|
end
|
24
40
|
|
41
|
+
# Returns the command that will be used to run screen with this configuration.
|
42
|
+
#
|
43
|
+
# ==== Arguments
|
44
|
+
# * <tt>tmp_file</tt> - The temporary file in which the configuration will be stored.
|
45
|
+
# (Optional for dry-run.)
|
25
46
|
def to_command tmp_file = 'TEMPORARY_FILE'
|
26
|
-
"cd #{@project.path} && #{binary} #{
|
47
|
+
"cd #{@project.path} && #{binary} #{args} -c #{tmp_file}"
|
27
48
|
end
|
28
49
|
|
29
|
-
|
50
|
+
# Verifies that the screen binary is there. If not, causes scide
|
51
|
+
# to fail with a <tt>screen_not_found</tt> error (see Scide#fail}.
|
52
|
+
def check_binary
|
30
53
|
Scide.fail :screen_not_found, "ERROR: #{binary} not found" unless system("which #{binary}", { [ :out, :err ] => :close })
|
31
54
|
end
|
32
55
|
|
56
|
+
# Returns a representation of this configuration as a string.
|
33
57
|
def to_s
|
34
58
|
String.new.tap do |s|
|
35
59
|
s << "startup_message off\n"
|
36
60
|
s << "hardstatus on\n"
|
37
61
|
s << "hardstatus alwayslastline\n"
|
38
|
-
s << "hardstatus string '#{
|
62
|
+
s << "hardstatus string '#{hardstatus}'\n\n"
|
39
63
|
s << @project.to_screen
|
40
64
|
end
|
41
65
|
end
|
42
66
|
|
43
67
|
private
|
44
68
|
|
69
|
+
# Returns the screen hardstatus line given as option, or
|
70
|
+
# the default #DEFAULT_HARDSTATUS.
|
71
|
+
def hardstatus
|
72
|
+
@options[:hardstatus] || DEFAULT_HARDSTATUS
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the screen binary given as option, or the
|
76
|
+
# default (<tt>screen</tt>).
|
45
77
|
def binary
|
46
|
-
@
|
78
|
+
@options[:binary] || 'screen'
|
47
79
|
end
|
48
80
|
|
49
|
-
|
50
|
-
|
81
|
+
# Returns the screen command-line arguments given as options.
|
82
|
+
def args
|
83
|
+
@options[:args]
|
51
84
|
end
|
52
85
|
|
86
|
+
# Saves this configuration to the file at the given path.
|
53
87
|
def save file
|
54
|
-
File.open(file
|
88
|
+
File.open(file, 'w'){ |f| f.write to_s }
|
55
89
|
end
|
56
90
|
end
|
57
91
|
end
|
data/lib/scide/window.rb
CHANGED
@@ -1,35 +1,80 @@
|
|
1
1
|
module Scide
|
2
2
|
|
3
|
+
# Configuration of a GNU Screen window (name, command).
|
3
4
|
class Window
|
5
|
+
|
6
|
+
# Window-specific options. Can be used by commands. See #initialize.
|
7
|
+
attr_reader :options
|
4
8
|
|
5
|
-
|
9
|
+
# Returns a window for the given project.
|
10
|
+
#
|
11
|
+
# ==== Arguments
|
12
|
+
# * <tt>project</tt> - The project owning this window.
|
13
|
+
# * <tt>contents</tt> - The window configuration (String or Hash).
|
14
|
+
#
|
15
|
+
# ==== String Initialization
|
16
|
+
# The string must be in the format <tt>NAME [COMMAND]</tt> where
|
17
|
+
# <tt>NAME</tt> is the window name and <tt>COMMAND</tt> (optional)
|
18
|
+
# is the command configuration (see Scide::Command).
|
19
|
+
#
|
20
|
+
# ==== Hash Initialization
|
21
|
+
# The following options can be given:
|
22
|
+
# * <tt>:name => string</tt> - The window name.
|
23
|
+
# * <tt>:options => hash</tt> - Window-specific options (will be
|
24
|
+
# merged to the project options).
|
25
|
+
# * <tt>:command => string</tt> - The command to use for this window
|
26
|
+
# (will be built using Scide::Command#resolve).
|
27
|
+
# * <tt>:string => string</tt> - If given, <tt>:name</tt> and <tt>:command</tt>
|
28
|
+
# are ignored and string initialization will be performed with <tt>string</tt>.
|
29
|
+
# <tt>:options</tt> can still be used to override project options.
|
30
|
+
def initialize project, contents
|
6
31
|
@project = project
|
32
|
+
|
7
33
|
if contents.kind_of? Hash
|
8
|
-
init_from_hash contents
|
34
|
+
init_from_hash! contents
|
9
35
|
elsif contents.kind_of? String
|
10
|
-
init_from_string contents
|
36
|
+
init_from_string! contents
|
37
|
+
else
|
38
|
+
raise ArgumentError, "window '#{contents}' must be a string or a hash"
|
11
39
|
end
|
12
40
|
end
|
13
41
|
|
42
|
+
# Returns a representation of this window as a GNU Screen
|
43
|
+
# configuration frament.
|
44
|
+
#
|
45
|
+
# ==== Arguments
|
46
|
+
# * <tt>index</tt> - The position of the window (zero-based).
|
14
47
|
def to_screen index
|
15
48
|
String.new.tap do |s|
|
16
|
-
s << "screen -t #{@name} #{index}
|
17
|
-
s << @command.to_screen if @command
|
49
|
+
s << "screen -t #{@name} #{index}"
|
50
|
+
s << "\n#{@command.to_screen}" if @command
|
18
51
|
end
|
19
52
|
end
|
20
53
|
|
21
54
|
private
|
22
55
|
|
23
|
-
|
24
|
-
|
25
|
-
|
56
|
+
# Initializes this window from a hash. See #initialize for options.
|
57
|
+
def init_from_hash! contents
|
58
|
+
raise ArgumentError, "options of window '#{@name}' must be a hash" unless contents[:options].nil? or contents[:options].kind_of?(Hash)
|
59
|
+
@options = @project.options.dup.merge(contents[:options] || {})
|
60
|
+
|
61
|
+
if contents[:string].present?
|
62
|
+
init_from_string! contents[:string]
|
63
|
+
else
|
64
|
+
raise ArgumentError, "window '#{contents}' must have a name" unless contents[:name].present?
|
65
|
+
@name = contents[:name]
|
66
|
+
@command = Command.resolve self, contents if contents.key? :command
|
67
|
+
end
|
26
68
|
end
|
27
69
|
|
28
|
-
|
70
|
+
# Initializes this window from a string. See #initialize for format.
|
71
|
+
def init_from_string! contents
|
72
|
+
raise ArgumentError, "window '#{contents}' must not be an empty string" unless contents.present?
|
29
73
|
content_parts = contents.split /\s+/, 2
|
30
74
|
@name = content_parts[0]
|
75
|
+
@options ||= @project.options.dup
|
31
76
|
if content_parts.length == 2
|
32
|
-
@command = Command.resolve content_parts[1]
|
77
|
+
@command = Command.resolve self, content_parts[1]
|
33
78
|
end
|
34
79
|
end
|
35
80
|
end
|
data/lib/scide.rb
CHANGED
@@ -1,26 +1,74 @@
|
|
1
1
|
require 'paint'
|
2
2
|
require 'upoj-rb'
|
3
3
|
|
4
|
+
# Generator of GNU Screen configuration files.
|
4
5
|
module Scide
|
6
|
+
|
7
|
+
# Current version.
|
5
8
|
VERSION = File.open(File.join(File.dirname(__FILE__), '..', 'VERSION'), 'r').read
|
9
|
+
|
10
|
+
# Exit status codes.
|
11
|
+
#
|
12
|
+
# ==== Codes
|
13
|
+
# * <tt>unexpected</tt> - 1.
|
14
|
+
# * <tt>invalid_argument</tt> - 2.
|
15
|
+
# * <tt>not_initialized</tt> - 3.
|
16
|
+
# * <tt>screen_not_found</tt> - 4.
|
17
|
+
# * <tt>config_not_found</tt> - 10.
|
18
|
+
# * <tt>config_not_readable</tt> - 11.
|
19
|
+
# * <tt>malformed_config</tt> - 12.
|
20
|
+
# * <tt>invalid_config</tt> - 13.
|
21
|
+
# * <tt>unknown_project</tt> - 14.
|
6
22
|
EXIT = {
|
7
23
|
:unexpected => 1,
|
8
24
|
:invalid_argument => 2,
|
9
25
|
:not_initialized => 3,
|
10
26
|
:screen_not_found => 4,
|
11
|
-
:config_not_found =>
|
12
|
-
:config_not_readable =>
|
13
|
-
:malformed_config =>
|
14
|
-
:invalid_config =>
|
15
|
-
:unknown_project =>
|
27
|
+
:config_not_found => 10,
|
28
|
+
:config_not_readable => 11,
|
29
|
+
:malformed_config => 12,
|
30
|
+
:invalid_config => 13,
|
31
|
+
:unknown_project => 14
|
16
32
|
}
|
17
33
|
|
34
|
+
# Prints a message on <tt>stderr</tt> and exits.
|
35
|
+
# If #condition is a key from #EXIT, the corresponding value
|
36
|
+
# will be used as the exit code. Otherwise, scide exits with
|
37
|
+
# status 1.
|
18
38
|
def self.fail condition, msg
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
39
|
+
if @@exit_on_fail
|
40
|
+
puts
|
41
|
+
warn Paint[msg, :yellow]
|
42
|
+
puts
|
43
|
+
EXIT.key?(condition) ? exit(EXIT[condition]) : exit(1)
|
44
|
+
else
|
45
|
+
raise Scide::Error.new condition, msg
|
46
|
+
end
|
23
47
|
end
|
48
|
+
|
49
|
+
# By default, scide is meant to be used as a standalone script
|
50
|
+
# and exits if an error occurs. If <tt>exit_on_fail</tt> is
|
51
|
+
# false, a Scide::Error will be raised instead. Scide can then
|
52
|
+
# be used by another script.
|
53
|
+
def self.exit_on_fail= exit_on_fail
|
54
|
+
@@exit_on_fail = exit_on_fail
|
55
|
+
end
|
56
|
+
|
57
|
+
# Scide error. Can be raised if #exit_on_fail is set to false.
|
58
|
+
class Error < StandardError
|
59
|
+
attr_reader :condition
|
60
|
+
|
61
|
+
# Returns a new error.
|
62
|
+
def initialize condition, msg
|
63
|
+
super msg
|
64
|
+
@condition = condition
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
@@exit_on_fail = true
|
24
71
|
end
|
25
72
|
|
73
|
+
# load scide components
|
26
74
|
%w( command config global opts overmind project screen window ).each{ |dep| require File.join(File.dirname(__FILE__), 'scide', dep) }
|
data/scide.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "scide"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["AlphaHydrae"]
|
12
|
-
s.date = "2011-10-
|
12
|
+
s.date = "2011-10-02"
|
13
13
|
s.description = "Utility to generate GNU screen configuration files."
|
14
14
|
s.email = "hydrae.alpha@gmail.com"
|
15
15
|
s.executables = ["scide"]
|
@@ -42,6 +42,11 @@ Gem::Specification.new do |s|
|
|
42
42
|
"lib/scide/screen.rb",
|
43
43
|
"lib/scide/window.rb",
|
44
44
|
"scide.gemspec",
|
45
|
+
"spec/command_spec.rb",
|
46
|
+
"spec/commands/edit_spec.rb",
|
47
|
+
"spec/commands/run_spec.rb",
|
48
|
+
"spec/commands/show_spec.rb",
|
49
|
+
"spec/commands/tail_spec.rb",
|
45
50
|
"spec/helper.rb"
|
46
51
|
]
|
47
52
|
s.homepage = "http://github.com/AlphaHydrae/scide"
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Scide
|
4
|
+
module Commands
|
5
|
+
class FuBar < Scide::Commands::Show
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Scide::Command do
|
11
|
+
|
12
|
+
it "should be abstract" do
|
13
|
+
com = Scide::Command.new 'fubar'
|
14
|
+
lambda{ com.to_screen }.should raise_error(StandardError)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should use given contents as text" do
|
18
|
+
com = Scide::Command.new 'fubar'
|
19
|
+
com.text_with_options.should == 'fubar'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should take options" do
|
23
|
+
com = Scide::Command.new 'fubar %{foo} %{bar}', :foo => 1, :bar => 2
|
24
|
+
com.text_with_options.should == 'fubar 1 2'
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'Class' do
|
28
|
+
before :each do
|
29
|
+
@options = { :a => 1, :b => true }
|
30
|
+
@window = double('window')
|
31
|
+
@window.stub(:options){ @options }
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should resolve command with a string" do
|
35
|
+
com = Scide::Command.resolve @window, 'SHOW fubar'
|
36
|
+
com.should be_a_kind_of(Scide::Commands::Show)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should use second part of string as contents when resolving a command with a string" do
|
40
|
+
com = Scide::Command.resolve @window, 'SHOW fubar'
|
41
|
+
com.text_with_options.should == 'fubar'
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should resolve command with a hash" do
|
45
|
+
com = Scide::Command.resolve @window, :command => 'SHOW', :contents => 'fubar'
|
46
|
+
com.should be_a_kind_of(Scide::Commands::Show)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should give duplicated window options to the resolved string command" do
|
50
|
+
@window.should_receive :options
|
51
|
+
com = Scide::Command.resolve @window, 'SHOW fubar'
|
52
|
+
com.options.should == @options
|
53
|
+
com.options.should_not equal(@options)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should give duplicated window options to the resolved hash command" do
|
57
|
+
@window.should_receive :options
|
58
|
+
com = Scide::Command.resolve @window, :command => 'SHOW', :contents => 'fubar'
|
59
|
+
com.options.should == @options
|
60
|
+
com.options.should_not equal(@options)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should resolve camel-case command class names with a string" do
|
64
|
+
puts Scide::Commands::FuBar
|
65
|
+
com = Scide::Command.resolve @window, 'FU_BAR'
|
66
|
+
com.should be_a_kind_of(Scide::Commands::FuBar)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should resolve camel-case command class names with a hash" do
|
70
|
+
com = Scide::Command.resolve @window, :command => 'FU_BAR'
|
71
|
+
com.should be_a_kind_of(Scide::Commands::FuBar)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should raise an error when type of contents is unknown" do
|
75
|
+
lambda{ Scide::Command.resolve(@window, []) }.should raise_error(ArgumentError)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should raise an error when trying to resolve a blank string" do
|
79
|
+
lambda{ Scide::Command.resolve(@window, ' ') }.should raise_error(ArgumentError)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should raise an error when trying to resolve an unknown command" do
|
83
|
+
lambda{ Scide::Command.resolve(@window, 'SHW fubar') }.should raise_error(ArgumentError)
|
84
|
+
lambda{ Scide::Command.resolve(@window, :command => 'SHW', :contents => 'fubar') }.should raise_error(ArgumentError)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Scide::Commands::Edit do
|
4
|
+
|
5
|
+
it "should use the preferred editor" do
|
6
|
+
com = Scide::Commands::Edit.new nil
|
7
|
+
com.text_with_options.should == '$EDITOR\012'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should use given contents as arguments to the editor" do
|
11
|
+
com = Scide::Commands::Edit.new 'fubar'
|
12
|
+
com.text_with_options.should == '$EDITOR fubar\012'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should use the :edit option as arguments to the editor" do
|
16
|
+
com = Scide::Commands::Edit.new 'fubar', :edit => '-c MyCommand'
|
17
|
+
com.text_with_options.should == '$EDITOR -c MyCommand fubar\012'
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Scide::Commands::Show do
|
4
|
+
|
5
|
+
it "should produce a GNU Screen stuff command" do
|
6
|
+
com = Scide::Commands::Show.new 'fubar'
|
7
|
+
com.to_screen.should == 'stuff "fubar"'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should use #text_with_options as argument to stuff" do
|
11
|
+
com = Scide::Commands::Show.new 'fubar'
|
12
|
+
text_with_options = com.text_with_options
|
13
|
+
com.to_screen.should == %|stuff "#{text_with_options}"|
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Scide::Commands::Tail do
|
4
|
+
|
5
|
+
it "should use given contents as argument -f of tail" do
|
6
|
+
com = Scide::Commands::Tail.new 'fubar'
|
7
|
+
com.text_with_options.should == 'tail -f fubar\012'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should use the :tail option as arguments to tail" do
|
11
|
+
com = Scide::Commands::Tail.new 'fubar', :tail => '-n 1000'
|
12
|
+
com.text_with_options.should == 'tail -n 1000 -f fubar\012'
|
13
|
+
end
|
14
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scide
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-02 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: upoj-rb
|
16
|
-
requirement: &
|
16
|
+
requirement: &2156558600 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.0.4
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2156558600
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &2156558080 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2156558080
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: shoulda
|
38
|
-
requirement: &
|
38
|
+
requirement: &2156557480 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2156557480
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bundler
|
49
|
-
requirement: &
|
49
|
+
requirement: &2156556880 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 1.0.0
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2156556880
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: jeweler
|
60
|
-
requirement: &
|
60
|
+
requirement: &2156556280 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.6.4
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2156556280
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rcov
|
71
|
-
requirement: &
|
71
|
+
requirement: &2156555680 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *2156555680
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rdoc
|
82
|
-
requirement: &
|
82
|
+
requirement: &2156555080 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,7 +87,7 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *2156555080
|
91
91
|
description: Utility to generate GNU screen configuration files.
|
92
92
|
email: hydrae.alpha@gmail.com
|
93
93
|
executables:
|
@@ -121,6 +121,11 @@ files:
|
|
121
121
|
- lib/scide/screen.rb
|
122
122
|
- lib/scide/window.rb
|
123
123
|
- scide.gemspec
|
124
|
+
- spec/command_spec.rb
|
125
|
+
- spec/commands/edit_spec.rb
|
126
|
+
- spec/commands/run_spec.rb
|
127
|
+
- spec/commands/show_spec.rb
|
128
|
+
- spec/commands/tail_spec.rb
|
124
129
|
- spec/helper.rb
|
125
130
|
homepage: http://github.com/AlphaHydrae/scide
|
126
131
|
licenses:
|
@@ -137,7 +142,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
137
142
|
version: '0'
|
138
143
|
segments:
|
139
144
|
- 0
|
140
|
-
hash:
|
145
|
+
hash: 1145488263121204374
|
141
146
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
147
|
none: false
|
143
148
|
requirements:
|