subcommand 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Makefile ADDED
@@ -0,0 +1,29 @@
1
+ #DISTFILES := README.markdown get_serial_number colors.sh todoapp.sh
2
+ #VERSION := `cat VERSION_FILE`
3
+
4
+ all: install
5
+
6
+ install:
7
+
8
+ rake build && sudo rake install
9
+
10
+ #
11
+ # Testing
12
+ #
13
+ TESTS = $(wildcard tests/t[0-9][0-9][0-9][0-9]-*.sh)
14
+ #TEST_OPTIONS=--verbose
15
+
16
+ test-pre-clean:
17
+ rm -rf tests/test-results "tests/trash directory"*
18
+
19
+ aggregate-results: $(TESTS)
20
+
21
+ $(TESTS): test-pre-clean
22
+ -cd tests && sh $(notdir $@) $(TEST_OPTIONS)
23
+
24
+ test: aggregate-results
25
+ tests/aggregate-results.sh tests/test-results/t*-*
26
+ rm -rf tests/test-results
27
+
28
+ # Force tests to get run every time
29
+ .PHONY: test test-pre-clean aggregate-results $(TESTS)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.2
1
+ 1.0.3
data/lib/subcommand.rb CHANGED
@@ -12,12 +12,12 @@
12
12
  # @examples
13
13
  # if a program has subcommands foo and baz
14
14
  #
15
- # ruby opt.rb help
16
- # ruby opt.rb --help
17
- # ruby opt.rb help foo
18
- # ruby opt.rb foo --help
19
- # ruby opt.rb baz --quiet "some text"
20
- # ruby opt.rb --verbose foo --force file.zzz
15
+ # ruby subcommand.rb help
16
+ # ruby subcommand.rb --help
17
+ # ruby subcommand.rb help foo
18
+ # ruby subcommand.rb foo --help
19
+ # ruby subcommand.rb baz --quiet "some text"
20
+ # ruby subcommand.rb --verbose foo --force file.zzz
21
21
  #
22
22
  # == STEPS
23
23
  # 1. define global_options (optional)
@@ -121,7 +121,7 @@ module Subcommands
121
121
  # print aliases
122
122
  unless @aliases.empty?
123
123
  cmdtext << "\n\nAliases: \n"
124
- @aliases.each_pair { |name, val| cmdtext << " #{name} - #{val}" }
124
+ @aliases.each_pair { |name, val| cmdtext << " #{name} - #{val}\n" }
125
125
  end
126
126
 
127
127
  cmdtext << "\n\nSee '#{$0} help COMMAND' for more information on a specific command."
@@ -136,15 +136,12 @@ module Subcommands
136
136
  @global.order!
137
137
  cmd = ARGV.shift
138
138
  if cmd
139
- #puts "Command: #{cmd}, args:#{ARGV}, #{@commands.keys} "
139
+ $stderr.puts "Command: #{cmd}, args:#{ARGV}, #{@commands.keys} "
140
140
  sc = @commands[cmd]
141
141
  #puts "sc: #{sc}: #{@commands}"
142
- #puts "sc: ="+@commands.include?(cmd)
143
142
  unless sc
144
143
  # see if an alias exists
145
- alas = @aliases[cmd]
146
- sc = @commands[alas] if alas
147
- cmd = alas if alas
144
+ sc, cmd = _check_alias cmd
148
145
  end
149
146
  # if valid command parse the args
150
147
  if sc
@@ -154,19 +151,23 @@ module Subcommands
154
151
  # else if help <command> then print its help GIT style (3)
155
152
  if !ARGV.empty? && cmd == "help"
156
153
  cmd = ARGV.shift
157
- #puts " 110 help #{cmd}"
154
+ $stderr.puts " 110 help #{cmd}"
158
155
  sc = @commands[cmd]
159
156
  # if valid command print help, else print global help
157
+ unless sc
158
+ sc, cmd = _check_alias cmd
159
+ end
160
160
  if sc
161
161
  #puts " 111 help #{cmd}"
162
162
  puts sc.call
163
163
  else
164
- puts "Invalid command: #{cmd}"
164
+ # no help for this command XXX check for alias
165
+ puts "Invalid command: #{cmd}."
165
166
  puts @global
166
167
  end
167
168
  else
168
169
  # invalid command
169
- puts "Invalid command: #{cmd}"
170
+ puts "Invalid command: #{cmd}" unless cmd == "help"
170
171
  puts @global
171
172
  end
172
173
  exit 0
@@ -174,6 +175,26 @@ module Subcommands
174
175
  end
175
176
  return @command_name
176
177
  end
178
+ def alias_command name, *args
179
+ @aliases[name.to_s] = args
180
+ end
181
+ def _check_alias cmd
182
+ alas = @aliases[cmd]
183
+ $stderr.puts "195 alas: #{alas} "
184
+ if alas
185
+ case alas
186
+ when Array
187
+ cmd = alas.shift
188
+ $stderr.puts "Array cmd: #{cmd} "
189
+ ARGV.unshift alas.shift unless alas.empty?
190
+ $stderr.puts "ARGV #{ARGV} "
191
+ else
192
+ cmd = alas
193
+ end
194
+ end
195
+ sc = @commands[cmd] if cmd
196
+ return sc, cmd
197
+ end
177
198
  end
178
199
 
179
200
  if __FILE__ == $PROGRAM_NAME
@@ -205,6 +226,9 @@ if __FILE__ == $PROGRAM_NAME
205
226
  options[:quiet] = v
206
227
  end
207
228
  end
229
+ alias_command :bar, 'baz'
230
+ alias_command :boo, 'foo', '--force'
231
+ alias_command :zoo, 'foo', 'ruby'
208
232
 
209
233
  # do the parsing.
210
234
  cmd = opt_parse()
data/tests/Makefile ADDED
@@ -0,0 +1,2 @@
1
+ test:
2
+ $(MAKE) -C .. test
data/tests/README ADDED
@@ -0,0 +1,313 @@
1
+ todorb.rb tests
2
+ ===============
3
+
4
+ This directory holds test scripts for todorb.rb . The
5
+ first part of this short document describes how to run the tests
6
+ and read their output.
7
+
8
+ When fixing the tools or adding enhancements, you are strongly
9
+ encouraged to add tests in this directory to cover what you are
10
+ trying to fix or enhance. The later part of this short document
11
+ describes how your test scripts should be organized.
12
+
13
+
14
+ Running Tests
15
+ -------------
16
+
17
+ The easiest way to run tests is to say "make test" from the top-level.
18
+ This runs all the tests.
19
+
20
+ rm -rf tests/test-results "tests/trash directory"*
21
+ cd tests && sh t0000-config.sh
22
+ * ok 1: no config file
23
+ * ok 2: config file (default location 1)
24
+ * ok 3: config file (default location 2)
25
+ * ok 4: config file (command line)
26
+ * ok 5: config file (env variable)
27
+ * passed all 5 test(s)
28
+ cd tests && sh t0001-null.sh
29
+ * ok 1: null ls
30
+ * passed all 1 test(s)
31
+ rm -rf tests/test-results
32
+
33
+ Or you can run each test individually from command line, like
34
+ this:
35
+
36
+ $ ./t0001-null.sh
37
+ * ok 1: null ls
38
+ * passed all 1 test(s)
39
+
40
+ You can pass --verbose (or -v), --debug (or -d), and --immediate
41
+ (or -i) command line argument to the test, or by setting GIT_TEST_OPTS
42
+ appropriately before running "make".
43
+
44
+ --verbose::
45
+ This makes the test more verbose. Specifically, the
46
+ command being run and their output if any are also
47
+ output.
48
+
49
+ --debug::
50
+ This may help the person who is developing a new test.
51
+ It causes the command defined with test_debug to run.
52
+
53
+ --immediate::
54
+ This causes the test to immediately exit upon the first
55
+ failed test.
56
+
57
+ --long-tests::
58
+ This causes additional long-running tests to be run (where
59
+ available), for more exhaustive testing.
60
+
61
+ --tee::
62
+ In addition to printing the test output to the terminal,
63
+ write it to files named 't/test-results/$TEST_NAME.out'.
64
+ As the names depend on the tests' file names, it is safe to
65
+ run the tests with this option in parallel.
66
+
67
+ Skipping Tests
68
+ --------------
69
+
70
+ In some environments, certain tests have no way of succeeding
71
+ due to platform limitation, such as lack of 'unzip' program, or
72
+ filesystem that do not allow arbitrary sequence of non-NUL bytes
73
+ as pathnames.
74
+
75
+ You should be able to say something like
76
+
77
+ $ SKIP_TESTS=t0000.2 sh ./t0000-config.sh
78
+
79
+ and even:
80
+
81
+ $ SKIP_TESTS='t[0-4]??? t91?? t9200.8' make
82
+
83
+ to omit such tests. The value of the environment variable is a
84
+ SP separated list of patterns that tells which tests to skip,
85
+ and either can match the "t[0-9]{4}" part to skip the whole
86
+ test, or t[0-9]{4} followed by ".$number" to say which
87
+ particular test to skip.
88
+
89
+ Note that some tests in the existing test suite rely on previous
90
+ test item, so you cannot arbitrarily disable one and expect the
91
+ remainder of test to check what the test originally was intended
92
+ to check.
93
+
94
+
95
+ Naming Tests
96
+ ------------
97
+
98
+ The test files are named as:
99
+
100
+ tNNNN-commandname-details.sh
101
+
102
+ where N is a decimal digit.
103
+
104
+ First digit tells the family:
105
+
106
+ 0 - the absolute basics and global stuff
107
+ 1 - basic every-day usage
108
+ 2 - add ins
109
+
110
+ Second digit tells the particular command we are testing.
111
+
112
+ Third digit (optionally) tells the particular switch or group of switches
113
+ we are testing.
114
+
115
+ If you create files under tests/ directory (i.e. here) that is not
116
+ the top-level test script, never name the file to match the above
117
+ pattern. The Makefile here considers all such files as the
118
+ top-level test script and tries to run all of them. A care is
119
+ especially needed if you are creating a common test library
120
+ file, similar to test-lib.sh, because such a library file may
121
+ not be suitable for standalone execution.
122
+
123
+
124
+ Writing Tests
125
+ -------------
126
+
127
+ The test script is written as a shell script. It should start
128
+ with the standard "#!/bin/sh" with copyright notices, and an
129
+ assignment to variable 'test_description', like this:
130
+
131
+ #!/bin/sh
132
+ #
133
+ # Copyright (c) 2005 Junio C Hamano
134
+ #
135
+
136
+ test_description='xxx test (option --frotz)
137
+
138
+ This test registers the following structure in the cache
139
+ and tries to run git-ls-files with option --frotz.'
140
+
141
+
142
+ Source 'test-lib.sh'
143
+ --------------------
144
+
145
+ After assigning test_description, the test script should source
146
+ test-lib.sh like this:
147
+
148
+ . ./test-lib.sh
149
+
150
+ This test harness library does the following things:
151
+
152
+ - If the script is invoked with command line argument --help
153
+ (or -h), it shows the test_description and exits.
154
+
155
+ - Creates an empty test directory with an empty todo file
156
+ database and chdir(2) into it. This directory is 't/trash directory'
157
+ if you must know, but I do not think you care.
158
+
159
+ - Defines standard test helper functions for your scripts to
160
+ use. These functions are designed to make all scripts behave
161
+ consistently when command line arguments --verbose (or -v),
162
+ --debug (or -d), and --immediate (or -i) is given.
163
+
164
+
165
+ End with test_done
166
+ ------------------
167
+
168
+ Your script will be a sequence of tests, using helper functions
169
+ from the test harness library. At the end of the script, call
170
+ 'test_done'.
171
+
172
+
173
+ Test harness library
174
+ --------------------
175
+
176
+ There are a handful helper functions defined in the test harness
177
+ library for your script to use.
178
+
179
+ - test_todo_session <message> < transcript
180
+
181
+ This takes a single string as a parameter, which is treated
182
+ as a base description of what is being tested, and then
183
+ reads from standard input a transcript of todorb.rb commands
184
+ and expected output. Each command is run in the current
185
+ test environment and the output is compared with the
186
+ expected output. (See below for how to generate transcripts
187
+ easily.)
188
+
189
+ - test_tick [interval]
190
+
191
+ The test harness has an internal view of time which is
192
+ implemented by wrapping the date command. This takes a single
193
+ optional positive integer parameter which indicates how much
194
+ to advance the internal time. The default value is one day.
195
+
196
+ - test_expect_success <message> <script>
197
+
198
+ This takes two strings as parameter, and evaluates the
199
+ <script>. If it yields success, test is considered
200
+ successful. <message> should state what it is testing.
201
+
202
+ Example:
203
+
204
+ test_expect_success \
205
+ 'git-write-tree should be able to write an empty tree.' \
206
+ 'tree=$(git-write-tree)'
207
+
208
+ - test_expect_failure <message> <script>
209
+
210
+ This is NOT the opposite of test_expect_success, but is used
211
+ to mark a test that demonstrates a known breakage. Unlike
212
+ the usual test_expect_success tests, which say "ok" on
213
+ success and "FAIL" on failure, this will say "FIXED" on
214
+ success and "still broken" on failure. Failures from these
215
+ tests won't cause -i (immediate) to stop.
216
+
217
+ - test_debug <script>
218
+
219
+ This takes a single argument, <script>, and evaluates it only
220
+ when the test script is started with --debug command line
221
+ argument. This is primarily meant for use during the
222
+ development of a new test script.
223
+
224
+ - test_done
225
+
226
+ Your test script must have test_done at the end. Its purpose
227
+ is to summarize successes and failures in the test script and
228
+ exit with an appropriate error code.
229
+
230
+
231
+ Generating test transcripts
232
+ ---------------------------
233
+
234
+ You can generate test scripts from screenshots as following:
235
+
236
+ $ ./testshell.sh
237
+
238
+ You'll be in a special test environment with an empty TODO2.txt
239
+ and the dates and timestamps will be artificially fixed.
240
+
241
+ Then the session can be used to make a unit test thanks to
242
+ test_todo_session, see the existing tests as examples.
243
+
244
+ Be careful to replace all occurences of the full path to the test
245
+ directory by $HOME as testshell.sh will explain you when you execute it
246
+ otherwise the tests will work properly only on your own computer.
247
+
248
+ Don't use "script" as this would log every keystroke, not only what's
249
+ visible!!
250
+
251
+ ***NOTE***
252
+
253
+ I am not clear how to generate transcripts using the above.
254
+ The script rtest2.sh actually generates a fully working test case/suite.
255
+ You may interactively enter actions and the action and result will get
256
+ written into a test script.
257
+ -- rkumar 2009-12-21 23:43
258
+
259
+ Credits
260
+ -------
261
+
262
+ This test framework was derived from the framework used by
263
+ git itself, written originally by Junio Hamano and licensed
264
+ for use under the GPL. It was specialized for todo.txt-cli
265
+ by Emil Sit and Philippe Teuwen.
266
+ Further modified for todorb.rb by Rahul Kumar.
267
+
268
+ ./rtest2.sh --load dataset1.txt "listing"
269
+ then type commands in there.
270
+ NOTE that a blank line in output terminates what "expect" file gets so test will fail.
271
+
272
+
273
+ Issues and Drawbacks with this framework
274
+ ----------------------------------------
275
+
276
+ This framework uses the standard output of a command as the expected
277
+ result. This usually means the message reported to the user on success or
278
+ failure. If we change the message, the test breaks. Similarly, any
279
+ change to the formatting of a listing breaks *many* tests.
280
+
281
+ The actual result in the file is not being checked, only the informational
282
+ message. To circumvent the problem of recreating test cases whenever output
283
+ changes, one may pipe the commands from a broken test file to rtest2.sh and create
284
+ a fresh file.
285
+ grep '^>>> ' t0001-broken.sh \
286
+ | sed 's/^>>> *//' \
287
+ | ./rtest2.sh --load data1.txt "listing"
288
+
289
+ Note that any data created on top of the broken test file, is to be saved and passed
290
+ in the --load parameter to rtest2.sh.
291
+
292
+ Date related:
293
+ -------------
294
+ This script works fine with shell scripts that use "date" to derive
295
+ date. There's a nice hack in the bin directorythat is created at runtime
296
+ in the trash folder. However, my ruby prog does not use "date". It uses
297
+ Time.now(). So the add method which appends a date appends actual date
298
+ not the fake date 12345000.
299
+
300
+ Fix for ruby programs:
301
+ t = Time.now
302
+ ut = ENV["TODO_TEST_TIME"]
303
+ t = Time.at(ut.to_i) if ut
304
+
305
+ Add the line of picking up unix time stamp from env and using that, if it's there.
306
+
307
+ Testing for failure returned by method
308
+ === 1
309
+ === -1
310
+ prior to output
311
+ PLEASE be sure to unset any TODO_ env variables prior to test, such as
312
+ TODO_SHOW_ALL or else tests will fail when its not set!
313
+ ## vim:tw=72:ai:formatoptions=tcqln:nocindent