executable 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/{HISTORY.rdoc → HISTORY.md} +31 -4
- data/LICENSE.txt +22 -0
- data/{README.rdoc → README.md} +66 -31
- data/demo/{00_introduction.rdoc → 00_introduction.md} +1 -1
- data/demo/{01_single_command.rdoc → 01_single_command.md} +1 -1
- data/demo/{02_multiple_commands.rdoc → 02_multiple_commands.md} +1 -1
- data/demo/{03_help_text.rdoc → 03_help_text.md} +5 -5
- data/demo/{04_manpage.rdoc → 04_manpage.md} +4 -4
- data/demo/{06_delegate_example.rdoc → 06_delegate_example.md} +1 -1
- data/demo/{07_command_methods.rdoc → 07_command_methods.md} +1 -1
- data/demo/{08_dispatach.rdoc → 08_dispatach.md} +1 -1
- data/demo/{05_optparse_example.rdoc → 09_optparse_example.md} +1 -1
- data/demo/samples/bin/hello +9 -2
- data/lib/executable/completion.rb +82 -0
- data/lib/executable/core_ext/unbound_method.rb +102 -0
- data/lib/executable/core_ext.rb +1 -102
- data/lib/executable/dispatch.rb +1 -1
- data/lib/executable/domain.rb +52 -5
- data/lib/executable/help.rb +28 -19
- data/lib/executable/parser.rb +7 -3
- data/lib/executable/version.rb +2 -22
- data/lib/executable.rb +3 -2
- metadata +43 -89
- data/.ruby +0 -61
- data/.yardopts +0 -7
- data/COPYING.rdoc +0 -35
- data/DEMO.rdoc +0 -568
- data/Schedule.reap +0 -17
- data/meta/authors +0 -2
- data/meta/copyrights +0 -3
- data/meta/created +0 -1
- data/meta/description +0 -6
- data/meta/name +0 -1
- data/meta/organization +0 -1
- data/meta/repositories +0 -2
- data/meta/requirements +0 -6
- data/meta/resources +0 -7
- data/meta/summary +0 -1
- data/meta/version +0 -1
- data/test/test_executable.rb +0 -59
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: dd281be8d7d039a36b1628be53a86817d12d30f1d69258d1f5b0dfa84cc99ad4
|
|
4
|
+
data.tar.gz: 459d53385e0333dd991c4d93f1a2b06e14cf8af188f541d7a0eb50f13b265e45
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c519372eba2ab84e43c919859e52117fbd3d0715ded1721b99f0b471221630ebdd55b8a58485dc6544f3e557a43d71d2fea6e828179dab02a76fbc084388e4a3
|
|
7
|
+
data.tar.gz: b08c3be0ddf83ac87fb68e29404add4b847b95c6aaaa748bb40bbfd8e585c6a6b126fba8649750776d8d544a5c0600b1e1ee0216bad9990e7a9b4b974bcabeec
|
data/{HISTORY.rdoc → HISTORY.md}
RENAMED
|
@@ -1,6 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
# RELEASE HISTORY
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## 1.3.0 / 2026-04-05
|
|
4
|
+
|
|
5
|
+
Maintenance release. Modernized project tooling.
|
|
6
|
+
|
|
7
|
+
Changes:
|
|
8
|
+
|
|
9
|
+
* Replace custom Indexer system with standard gemspec.
|
|
10
|
+
* Replace Travis CI with GitHub Actions.
|
|
11
|
+
* Update Rakefile.
|
|
12
|
+
* Fix typo in version.rb module name (Exectuable -> Executable).
|
|
13
|
+
* Switch tests to minitest.
|
|
14
|
+
* Update URLs to HTTPS.
|
|
15
|
+
* Clean up obsolete files and .gitignore.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## 1.2.1 / 2012-12-19
|
|
19
|
+
|
|
20
|
+
This release imporves the help output and manpage lookup
|
|
21
|
+
as well as a few helpful additions the the API.
|
|
22
|
+
|
|
23
|
+
Changes:
|
|
24
|
+
|
|
25
|
+
* Improve manpage lookup.
|
|
26
|
+
* Improve overall help output.
|
|
27
|
+
* Add alias_switch and alias_accessor helpers.
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## 1.2.0 / 2012-01-31
|
|
4
31
|
|
|
5
32
|
Version 1.2.0 is complete rewrite of Executable. Actually it was decided that
|
|
6
33
|
the old design was too simplistic in it design concept, so another library
|
|
@@ -20,7 +47,7 @@ Changes:
|
|
|
20
47
|
* Supports manpage look-up and display.
|
|
21
48
|
|
|
22
49
|
|
|
23
|
-
|
|
50
|
+
## 1.1.0 / 2011-04-21
|
|
24
51
|
|
|
25
52
|
This release simplifies Executable, removing the #option_missing method
|
|
26
53
|
and using the standard #method_missing callback instead. Along with this
|
|
@@ -44,7 +71,7 @@ Changes:
|
|
|
44
71
|
* The #method_missing callback takes the value of the option being set.
|
|
45
72
|
|
|
46
73
|
|
|
47
|
-
|
|
74
|
+
## 1.0.0 / 2011-04-15
|
|
48
75
|
|
|
49
76
|
This is the initialize release of Executable (as a stand alone project).
|
|
50
77
|
Executable is a mixin that can turn any class into an commandline interface.
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
BSD-2-Clause License
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
|
4
|
+
modification, are permitted provided that the following conditions are met:
|
|
5
|
+
|
|
6
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
7
|
+
this list of conditions and the following disclaimer.
|
|
8
|
+
|
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
10
|
+
notice, this list of conditions and the following disclaimer in the
|
|
11
|
+
documentation and/or other materials provided with the distribution.
|
|
12
|
+
|
|
13
|
+
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
14
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
16
|
+
COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
17
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
18
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
19
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
20
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
21
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
22
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/{README.rdoc → README.md}
RENAMED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
# Executable
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
{Report Issue}[http://github.com/rubyworks/executable/features] |
|
|
6
|
-
{#rubyworks}[irc://irc.freenode.org/rubyworks]
|
|
3
|
+
[Source Code](https://github.com/rubyworks/executable) |
|
|
4
|
+
[Report Issue](https://github.com/rubyworks/executable/issues)
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
== DESCRIPTION
|
|
6
|
+
[](https://rubygems.org/gems/executable)
|
|
7
|
+
[](https://github.com/rubyworks/executable/actions/workflows/test.yml)
|
|
12
8
|
|
|
13
9
|
Executable is to the commandline, what ActiveRecord is the database.
|
|
14
10
|
You can think of Executable as a *COM*, a Command-line Object Mapper,
|
|
@@ -18,7 +14,7 @@ a complete command line tool using nothing more than Ruby's standard
|
|
|
18
14
|
syntax. No special DSL is required.
|
|
19
15
|
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
## Features
|
|
22
18
|
|
|
23
19
|
* Easy to use, just mixin or subclass.
|
|
24
20
|
* Define #call to control the command procedure.
|
|
@@ -28,18 +24,13 @@ syntax. No special DSL is required.
|
|
|
28
24
|
* Generate help in plain text or markdown.
|
|
29
25
|
|
|
30
26
|
|
|
31
|
-
|
|
27
|
+
## Limitations
|
|
32
28
|
|
|
33
29
|
* Ruby 1.9+ only.
|
|
34
30
|
* Help doesn't handle aliases well (yet).
|
|
35
31
|
|
|
36
32
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Please see HISTORY.rdoc file.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
== SYNOPSIS
|
|
33
|
+
## Overview
|
|
43
34
|
|
|
44
35
|
CLIs can be built by using a Executable as a mixin, or by subclassing
|
|
45
36
|
`Executable::Command`. Methods seemlessly handle command-line options.
|
|
@@ -48,13 +39,14 @@ methods (those ending in '?') modify them to be boolean switches.
|
|
|
48
39
|
|
|
49
40
|
For example, here is a simple "Hello, World!" commandline tool.
|
|
50
41
|
|
|
42
|
+
```ruby
|
|
51
43
|
require 'executable'
|
|
52
44
|
|
|
53
45
|
class HelloCommand
|
|
54
46
|
include Executable
|
|
55
47
|
|
|
56
48
|
# Say it in uppercase?
|
|
57
|
-
def
|
|
49
|
+
def loud=(bool)
|
|
58
50
|
@loud = bool
|
|
59
51
|
end
|
|
60
52
|
|
|
@@ -64,11 +56,11 @@ For example, here is a simple "Hello, World!" commandline tool.
|
|
|
64
56
|
end
|
|
65
57
|
|
|
66
58
|
# Show this message.
|
|
67
|
-
def help
|
|
59
|
+
def help!
|
|
68
60
|
cli.show_help
|
|
69
61
|
exit
|
|
70
62
|
end
|
|
71
|
-
alias :h
|
|
63
|
+
alias :h! :help!
|
|
72
64
|
|
|
73
65
|
# Say hello.
|
|
74
66
|
def call(name)
|
|
@@ -78,17 +70,21 @@ For example, here is a simple "Hello, World!" commandline tool.
|
|
|
78
70
|
puts str
|
|
79
71
|
end
|
|
80
72
|
end
|
|
73
|
+
```
|
|
81
74
|
|
|
82
75
|
To make the command available on the command line, add an executable
|
|
83
|
-
to your project
|
|
76
|
+
to your project calling the #execute or #run methods.
|
|
84
77
|
|
|
78
|
+
```ruby
|
|
85
79
|
#!usr/bin/env ruby
|
|
86
80
|
require 'hello.rb'
|
|
87
81
|
HelloCommand.run
|
|
82
|
+
```
|
|
88
83
|
|
|
89
84
|
If we named this file `hello`, set its execute flag and made it available
|
|
90
85
|
on our systems $PATH, then:
|
|
91
86
|
|
|
87
|
+
```
|
|
92
88
|
$ hello
|
|
93
89
|
Hello, World!
|
|
94
90
|
|
|
@@ -97,9 +93,11 @@ on our systems $PATH, then:
|
|
|
97
93
|
|
|
98
94
|
$ hello --loud John
|
|
99
95
|
HELLO, JOHN!
|
|
96
|
+
```
|
|
100
97
|
|
|
101
98
|
Executable can also generate help text for commands.
|
|
102
99
|
|
|
100
|
+
```
|
|
103
101
|
$ hello --help
|
|
104
102
|
USAGE: hello [options]
|
|
105
103
|
|
|
@@ -107,38 +105,75 @@ Executable can also generate help text for commands.
|
|
|
107
105
|
|
|
108
106
|
--loud Say it in uppercase?
|
|
109
107
|
--help Show this message
|
|
108
|
+
```
|
|
110
109
|
|
|
111
110
|
If you look back at the class definition you can see it's pulling
|
|
112
111
|
comments from the source to provide descriptions. It pulls the
|
|
113
|
-
description the command itself from the `#call` method.
|
|
112
|
+
description for the command itself from the `#call` method.
|
|
114
113
|
|
|
115
114
|
Basic help like this is fine for personal tools, but for public facing
|
|
116
115
|
production applications it is desirable to utilize manpages. To this end,
|
|
117
116
|
Executable provides Markdown formatted help as well. We can access this,
|
|
118
117
|
for example, via `HelloCommand.help.markdown`. The idea with this is that
|
|
119
118
|
we can save the output to `man/hello.ronn` or copy it the top of our `bin/`
|
|
120
|
-
file, edit it to perfection and then use tools such a
|
|
121
|
-
|
|
119
|
+
file, edit it to perfection and then use tools such a [ronn](https://github.com/rtomayko/ronn),
|
|
120
|
+
[binman](https://github.com/sunaku/binman) or [md2man](https://github.com/sunaku/md2man)
|
|
122
121
|
to generate the manpages. What's particularly cool about Executable,
|
|
123
122
|
is that once we have a manpage in the standard `man/` location in our project,
|
|
124
123
|
the `#show_help` method will use it instead of the plain text.
|
|
125
124
|
|
|
126
|
-
For a more
|
|
127
|
-
|
|
125
|
+
For a more detailed example see [QED](http://rubyworks.github.com/executable/demo.html),
|
|
126
|
+
[API](http://rubydoc.info/gems/executable/frames) documentation and, in particular,
|
|
127
|
+
the [Wiki](http://wiki.github.com/rubyworks/).
|
|
128
128
|
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
## Installation
|
|
131
131
|
|
|
132
132
|
Install with RubyGems in the usual fashion.
|
|
133
133
|
|
|
134
|
+
```
|
|
134
135
|
$ gem install executable
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Contributing
|
|
139
|
+
|
|
140
|
+
Executable is a [Rubyworks](http://rubyworks.github.com) project. As such it largely
|
|
141
|
+
uses in-house tools for development.
|
|
142
|
+
|
|
143
|
+
### Submitting Patches
|
|
144
|
+
|
|
145
|
+
If it is a very small change, just pasting it to an issue is fine. For anything more than
|
|
146
|
+
this please send us a traditional patch, but even better use Github pull requests.
|
|
147
|
+
Good contributions have the following:
|
|
148
|
+
|
|
149
|
+
* Well documented code following the conventions of the project.
|
|
150
|
+
* Clearly written tests with good test coverage written using the project's chosen test framework.
|
|
151
|
+
* Use of a git topic branch to keep the change set well isolated.
|
|
152
|
+
|
|
153
|
+
The more of these bullet points a pull request covers, the more likely and quickly it will
|
|
154
|
+
be accepted and merged.
|
|
155
|
+
|
|
156
|
+
### Testing
|
|
157
|
+
|
|
158
|
+
[QED](http://rubyworks.github.com/qed) and [Microtest](http://rubyworks.github.com/microtest)
|
|
159
|
+
are used for this project. To run the QED demos just run the `qed` command, probably with bundler,
|
|
160
|
+
so `bundle exec qed`. And to run the microtests you can use `rubytest test/`, again with bundler,
|
|
161
|
+
`bundle exec rubytest test/`.
|
|
162
|
+
|
|
163
|
+
### Getting In Touch
|
|
164
|
+
|
|
165
|
+
For direct dialog we have an IRC channel, #rubyworks on freenode. But it's not always manned,
|
|
166
|
+
so a [mailing list](http://groups.google.com/groups/rubyworks-mailinglist) is also available.
|
|
167
|
+
Of course these days, the GitHub [issues page](http://github.com/rubyworks/executable) is
|
|
168
|
+
generally the place get in touch for anything specific to this project.
|
|
135
169
|
|
|
136
170
|
|
|
137
|
-
|
|
171
|
+
## Copyrights
|
|
138
172
|
|
|
139
|
-
|
|
173
|
+
Executable is copyrighted open source software.
|
|
140
174
|
|
|
141
|
-
|
|
175
|
+
Copyright (c) 2008 Rubyworks (BSD-2-Clause)
|
|
142
176
|
|
|
143
|
-
|
|
177
|
+
It can be distributed and modified in accordance with the **BSD-2-Clause** license.
|
|
144
178
|
|
|
179
|
+
See LICENSE.txt for details.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
## Command Help
|
|
2
2
|
|
|
3
3
|
Executable Commands can generate help output. It does this by extracting
|
|
4
4
|
the commenst associated with the option methods. A description of the
|
|
@@ -62,7 +62,7 @@ The help output,
|
|
|
62
62
|
|
|
63
63
|
should be clearly laid out as follows:
|
|
64
64
|
|
|
65
|
-
Usage:
|
|
65
|
+
Usage: my c1 [options...] [subcommand]
|
|
66
66
|
|
|
67
67
|
This does c1.
|
|
68
68
|
|
|
@@ -81,12 +81,12 @@ The help feature can also output ronn-style markdown,
|
|
|
81
81
|
|
|
82
82
|
should be clearly laid out as follows:
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
my-c1(1) - This does c1.
|
|
85
|
+
========================
|
|
86
86
|
|
|
87
87
|
## SYNOPSIS
|
|
88
88
|
|
|
89
|
-
`
|
|
89
|
+
`my c1` [options...] [subcommand]
|
|
90
90
|
|
|
91
91
|
## DESCRIPTION
|
|
92
92
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
### Manpages
|
|
2
2
|
|
|
3
3
|
If a man page is available for a given command using the #show_help
|
|
4
4
|
method will automatically find the manpage and display it.
|
|
5
5
|
|
|
6
6
|
sample = File.dirname(__FILE__) + '/samples'
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
manpage = Hello.cli.manpage
|
|
8
|
+
manpage = `ruby #{sample}/bin/hello --manpage`.strip
|
|
11
9
|
|
|
12
10
|
manpage.assert == sample + '/man/hello.1'
|
|
13
11
|
|
|
12
|
+
Note: Would rather use #load for this, but without a `.rb` on
|
|
13
|
+
the `hello` file, it doesn't seem possible.
|
|
14
14
|
|
data/demo/samples/bin/hello
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
3
|
require 'executable'
|
|
4
4
|
|
|
5
5
|
class Hello < Executable::Command
|
|
6
6
|
# Say it in uppercase?
|
|
7
|
-
def
|
|
7
|
+
def loud=(bool)
|
|
8
8
|
@loud = bool
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -27,5 +27,12 @@ class Hello < Executable::Command
|
|
|
27
27
|
str = str.upcase if loud?
|
|
28
28
|
puts str
|
|
29
29
|
end
|
|
30
|
+
|
|
31
|
+
# Where's the manpage?
|
|
32
|
+
def manpage!
|
|
33
|
+
puts cli.manpage
|
|
34
|
+
exit
|
|
35
|
+
end
|
|
30
36
|
end
|
|
31
37
|
|
|
38
|
+
Hello.execute
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module Executable
|
|
2
|
+
|
|
3
|
+
# Encpsulates command completion.
|
|
4
|
+
#
|
|
5
|
+
class Completion
|
|
6
|
+
|
|
7
|
+
#
|
|
8
|
+
# Setup new completion object.
|
|
9
|
+
#
|
|
10
|
+
def initialize(cli_class)
|
|
11
|
+
@cli_class = cli_class
|
|
12
|
+
|
|
13
|
+
@subcommands = nil
|
|
14
|
+
@options = nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
#
|
|
18
|
+
alias_method :inspect, :to_s
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# The Executable subclass to which this help applies.
|
|
22
|
+
#
|
|
23
|
+
attr :cli_class
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# List of subcommands converted to a printable string.
|
|
27
|
+
# But will return +nil+ if there are no subcommands.
|
|
28
|
+
#
|
|
29
|
+
# @return [String,NilClass] subcommand list text
|
|
30
|
+
#
|
|
31
|
+
def subcommands
|
|
32
|
+
@subcommands ||= @cli_class.subcommands.keys
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
def options
|
|
37
|
+
@options ||= (
|
|
38
|
+
method_list.map do |meth|
|
|
39
|
+
case meth.name
|
|
40
|
+
when /^(.*?)[\!\=]$/
|
|
41
|
+
name = meth.name.to_s.chomp('!').chomp('=')
|
|
42
|
+
mark = name.to_s.size == 1 ? '-' : '--'
|
|
43
|
+
mark + name
|
|
44
|
+
end
|
|
45
|
+
end.compact.sort
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
#
|
|
50
|
+
def to_s
|
|
51
|
+
(subcommands + options).join(' ')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
def call(*args)
|
|
56
|
+
puts self
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
#
|
|
62
|
+
# Produce a list relavent methods.
|
|
63
|
+
#
|
|
64
|
+
def method_list
|
|
65
|
+
list = []
|
|
66
|
+
methods = []
|
|
67
|
+
stop_at = cli_class.ancestors.index(Executable::Command) ||
|
|
68
|
+
cli_class.ancestors.index(Executable) ||
|
|
69
|
+
-1
|
|
70
|
+
ancestors = cli_class.ancestors[0...stop_at]
|
|
71
|
+
ancestors.reverse_each do |a|
|
|
72
|
+
a.instance_methods(false).each do |m|
|
|
73
|
+
list << cli_class.instance_method(m)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
list
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
class UnboundMethod
|
|
2
|
+
if !method_defined?(:source_location)
|
|
3
|
+
if Proc.method_defined? :__file__ # /ree/
|
|
4
|
+
def source_location
|
|
5
|
+
[__file__, __line__] rescue nil
|
|
6
|
+
end
|
|
7
|
+
elsif defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/
|
|
8
|
+
require 'java'
|
|
9
|
+
def source_location
|
|
10
|
+
to_java.source_location(Thread.current.to_java.getContext())
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#
|
|
16
|
+
def comment
|
|
17
|
+
Source.get_above_comment(*source_location)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Source lookup.
|
|
21
|
+
#
|
|
22
|
+
module Source
|
|
23
|
+
extend self
|
|
24
|
+
|
|
25
|
+
# Read and cache file.
|
|
26
|
+
#
|
|
27
|
+
# @param file [String] filename, should be full path
|
|
28
|
+
#
|
|
29
|
+
# @return [Array] file content in array of lines
|
|
30
|
+
def read(file)
|
|
31
|
+
@read ||= {}
|
|
32
|
+
@read[file] ||= File.readlines(file)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Get comment from file searching up from given line number.
|
|
36
|
+
#
|
|
37
|
+
# @param file [String] filename, should be full path
|
|
38
|
+
# @param line [Integer] line number in file
|
|
39
|
+
#
|
|
40
|
+
def get_above_comment(file, line)
|
|
41
|
+
get_above_comment_lines(file, line).join("\n").strip
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Get comment from file searching up from given line number.
|
|
45
|
+
#
|
|
46
|
+
# @param file [String] filename, should be full path
|
|
47
|
+
# @param line [Integer] line number in file
|
|
48
|
+
#
|
|
49
|
+
def get_above_comment_lines(file, line)
|
|
50
|
+
text = read(file)
|
|
51
|
+
index = line - 1
|
|
52
|
+
while index >= 0 && text[index] !~ /^\s*\#/
|
|
53
|
+
return [] if text[index] =~ /^\s*end/
|
|
54
|
+
index -= 1
|
|
55
|
+
end
|
|
56
|
+
rindex = index
|
|
57
|
+
while text[index] =~ /^\s*\#/
|
|
58
|
+
index -= 1
|
|
59
|
+
end
|
|
60
|
+
result = text[index..rindex]
|
|
61
|
+
result = result.map{ |s| s.strip }
|
|
62
|
+
result = result.reject{ |s| s[0,1] != '#' }
|
|
63
|
+
result = result.map{ |s| s.sub(/^#/,'').strip }
|
|
64
|
+
#result = result.reject{ |s| s == "" }
|
|
65
|
+
result
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Get comment from file searching down from given line number.
|
|
69
|
+
#
|
|
70
|
+
# @param file [String] filename, should be full path
|
|
71
|
+
# @param line [Integer] line number in file
|
|
72
|
+
#
|
|
73
|
+
def get_following_comment(file, line)
|
|
74
|
+
get_following_comment_lines(file, line).join("\n").strip
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Get comment from file searching down from given line number.
|
|
78
|
+
#
|
|
79
|
+
# @param file [String] filename, should be full path
|
|
80
|
+
# @param line [Integer] line number in file
|
|
81
|
+
#
|
|
82
|
+
def get_following_comment_lines(file, line)
|
|
83
|
+
text = read(file)
|
|
84
|
+
index = line || 0
|
|
85
|
+
while text[index] !~ /^\s*\#/
|
|
86
|
+
return nil if text[index] =~ /^\s*(class|module)/
|
|
87
|
+
index += 1
|
|
88
|
+
end
|
|
89
|
+
rindex = index
|
|
90
|
+
while text[rindex] =~ /^\s*\#/
|
|
91
|
+
rindex += 1
|
|
92
|
+
end
|
|
93
|
+
result = text[index..(rindex-2)]
|
|
94
|
+
result = result.map{ |s| s.strip }
|
|
95
|
+
result = result.reject{ |s| s[0,1] != '#' }
|
|
96
|
+
result = result.map{ |s| s.sub(/^#/,'').strip }
|
|
97
|
+
result.join("\n").strip
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|