dotopts 0.1.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.
- data/.index +55 -0
- data/Gemfile.lock +33 -0
- data/HISTORY.md +10 -0
- data/LICENSE.txt +23 -0
- data/README.md +149 -0
- data/demo/09_battery/commands_only.md +49 -0
- data/demo/09_battery/profiles_basic.md +71 -0
- data/demo/09_battery/profiles_complex.md +68 -0
- data/demo/09_battery/profiles_regex.md +71 -0
- data/demo/09_battery/substitution.md +27 -0
- data/demo/applique/battery.rb +28 -0
- data/demo/applique/require.rb +6 -0
- data/lib/dotopts.rb +3 -0
- data/lib/dotopts/api.rb +41 -0
- data/lib/dotopts/parser.rb +159 -0
- data/spec/fixtures/yard.opts +3 -0
- data/spec/helper.rb +23 -0
- data/spec/spec_api.rb +17 -0
- data/spec/spec_parser.rb +68 -0
- metadata +120 -0
data/.index
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
---
|
2
|
+
revision: 2013
|
3
|
+
type: ruby
|
4
|
+
sources:
|
5
|
+
- var
|
6
|
+
authors:
|
7
|
+
- name: trans
|
8
|
+
email: transfire@gmail.com
|
9
|
+
organizations:
|
10
|
+
- name: Rubyworks
|
11
|
+
requirements:
|
12
|
+
- groups:
|
13
|
+
- test
|
14
|
+
development: true
|
15
|
+
name: qed
|
16
|
+
- groups:
|
17
|
+
- test
|
18
|
+
development: true
|
19
|
+
name: spectroscope
|
20
|
+
- groups:
|
21
|
+
- test
|
22
|
+
development: true
|
23
|
+
name: ae
|
24
|
+
conflicts: []
|
25
|
+
alternatives: []
|
26
|
+
resources:
|
27
|
+
- type: home
|
28
|
+
uri: http://rubyworks.github.com/dotopts
|
29
|
+
label: Homepage
|
30
|
+
- type: code
|
31
|
+
uri: http://github.com/rubyworks/dotopts
|
32
|
+
label: Source Code
|
33
|
+
- type: mail
|
34
|
+
uri: http://groups.google.com/group/rubyworks-mailinglist
|
35
|
+
label: Mailing List
|
36
|
+
repositories:
|
37
|
+
- name: upstream
|
38
|
+
scm: git
|
39
|
+
uri: git@github.com:rubyworks/dotopts.git
|
40
|
+
categories: []
|
41
|
+
copyrights:
|
42
|
+
- holder: Rubyworks
|
43
|
+
year: '2013'
|
44
|
+
license: BSD-2-Clause
|
45
|
+
customs: []
|
46
|
+
paths:
|
47
|
+
lib:
|
48
|
+
- lib
|
49
|
+
created: '2013-01-23'
|
50
|
+
summary: Automatic Arguments for Ruby
|
51
|
+
title: DotOpts
|
52
|
+
version: 0.1.0
|
53
|
+
name: dotopts
|
54
|
+
description: DotOpts is an automatic commandline argument augmenter for Ruby tools.
|
55
|
+
date: '2013-01-25'
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
dotopts (0.1.0)
|
5
|
+
|
6
|
+
PATH
|
7
|
+
remote: ../ae
|
8
|
+
specs:
|
9
|
+
ae (1.8.1)
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: http://rubygems.org/
|
13
|
+
specs:
|
14
|
+
ansi (1.4.3)
|
15
|
+
brass (1.2.1)
|
16
|
+
facets (2.9.3)
|
17
|
+
qed (2.9.1)
|
18
|
+
ansi
|
19
|
+
brass
|
20
|
+
facets (>= 2.8)
|
21
|
+
rubytest (0.6.0)
|
22
|
+
ansi
|
23
|
+
spectroscope (0.1.0)
|
24
|
+
rubytest
|
25
|
+
|
26
|
+
PLATFORMS
|
27
|
+
ruby
|
28
|
+
|
29
|
+
DEPENDENCIES
|
30
|
+
ae!
|
31
|
+
dotopts!
|
32
|
+
qed
|
33
|
+
spectroscope
|
data/HISTORY.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
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.
|
23
|
+
|
data/README.md
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
[](http://travis-ci.org/rubyworks/dotopts)
|
2
|
+
[](http://badge.fury.io/rb/dotopts)
|
3
|
+
|
4
|
+
<br/>
|
5
|
+
|
6
|
+
# DotOpts
|
7
|
+
|
8
|
+
**Universal Command Options Configuration (for Ruby Executables)**
|
9
|
+
|
10
|
+
[Website](http://rubyworks.github.com/dotopts) /
|
11
|
+
[Report Issue](http://github.com/rubyworks/dotopts/issues) /
|
12
|
+
[Source Code](http://github.com/rubyworks/dotopts)
|
13
|
+
|
14
|
+
|
15
|
+
## About
|
16
|
+
|
17
|
+
DotOpts is an automatic command line argument augmenter. I looks for a local
|
18
|
+
local `.opts` configuration file and applies the appropriate arguments
|
19
|
+
when a matching command is invoked.
|
20
|
+
|
21
|
+
|
22
|
+
## Features
|
23
|
+
|
24
|
+
* Works with any and all Ruby-based executables.
|
25
|
+
* Can be used to set environment variables in addition to arguments.
|
26
|
+
* Supports environment variable substitution.
|
27
|
+
* Supports conditional augmentation using environment settings.
|
28
|
+
* Simple and easy to use plain-text configuration format.
|
29
|
+
|
30
|
+
|
31
|
+
## Install
|
32
|
+
|
33
|
+
DotOpts can be install via Rubygems:
|
34
|
+
|
35
|
+
gem install dotopts
|
36
|
+
|
37
|
+
If you would like to use DotOpts with all Ruby tools, regardless of
|
38
|
+
wether they have built-in support for DotOpts, then add `-rdotopts`
|
39
|
+
to you `RUBYOPT` environment variable.
|
40
|
+
|
41
|
+
export RUBYOPT="-rdotopts"
|
42
|
+
|
43
|
+
This ensures DotOpts is required whenever Ruby is used.
|
44
|
+
|
45
|
+
|
46
|
+
## Usage
|
47
|
+
|
48
|
+
### Setting Arguments
|
49
|
+
|
50
|
+
A simple example of a projects `.opts` file:
|
51
|
+
|
52
|
+
yardoc
|
53
|
+
yard doc
|
54
|
+
--title="Bad Ass Program"
|
55
|
+
|
56
|
+
This simply says, that whenever `yardoc` or `yard doc` is executed then
|
57
|
+
add the `--title="Bad Ass Program"` argument to the end of the command
|
58
|
+
line arguments (internally `ARGV`).
|
59
|
+
|
60
|
+
|
61
|
+
### Setting Environment Variables
|
62
|
+
|
63
|
+
Environment variables can also be set by prepending first and subsequent
|
64
|
+
lines with `$ `.
|
65
|
+
|
66
|
+
yardoc
|
67
|
+
yard doc
|
68
|
+
$ RUBYOPTS="-rbadass"
|
69
|
+
--title="Bad Ass Program"
|
70
|
+
|
71
|
+
The space after the cash sign is important! Otherwise it will be interpreted
|
72
|
+
as a variable substitution.
|
73
|
+
|
74
|
+
|
75
|
+
### Conditional Profiles
|
76
|
+
|
77
|
+
The `.opts` configuration file support profiles via the square brackets.
|
78
|
+
Profiles are chosen via the `$profile` or `$p` environment variable.
|
79
|
+
|
80
|
+
```
|
81
|
+
[coverage]
|
82
|
+
rubytest
|
83
|
+
-r simplecov
|
84
|
+
```
|
85
|
+
|
86
|
+
So the above means that `-r simplecov` should be added the argument list when
|
87
|
+
`rubytest` is executed, but only if `$profile` or `$p` is equal to `"coverage"`.
|
88
|
+
|
89
|
+
Square brackets can also be used to match against any environment variable
|
90
|
+
by using the `=` sign.
|
91
|
+
|
92
|
+
```
|
93
|
+
[RUBY_ENGINE=jruby]
|
94
|
+
rake test
|
95
|
+
-r jruby-sandbox
|
96
|
+
```
|
97
|
+
|
98
|
+
To condition a configuration on multiple environment settings, add each
|
99
|
+
to the square brackets separated by a space.
|
100
|
+
|
101
|
+
```
|
102
|
+
[coverage RUBY_ENGINE=jruby]
|
103
|
+
rubytest
|
104
|
+
-r jruby-sandbox
|
105
|
+
-r simplecov
|
106
|
+
```
|
107
|
+
|
108
|
+
Finally, environment values can be matched against simple regular expressions
|
109
|
+
using a tilde (`~`) before the value. Be sure to out the value in quotes when
|
110
|
+
using regular expressions.
|
111
|
+
|
112
|
+
```
|
113
|
+
[~"cov(erage)?" RUBY_ENGINE=~"jruby|rubinius"]
|
114
|
+
rubytest
|
115
|
+
-r jruby-sandbox
|
116
|
+
-r simplecov
|
117
|
+
```
|
118
|
+
|
119
|
+
## Third Party Support
|
120
|
+
|
121
|
+
Ruby tool developers can support dotopts out-of-the-box simple by running
|
122
|
+
`require 'dotopt'` in their program before parsing the commandline. DotOpts
|
123
|
+
simply inject arguments into `ARGV` so it can work with any commandline
|
124
|
+
option parser.
|
125
|
+
|
126
|
+
|
127
|
+
## Development
|
128
|
+
|
129
|
+
### Universal Solution?
|
130
|
+
|
131
|
+
It would be awesome if it were possible to have DotOpts apply to *all* executables,
|
132
|
+
not just Ruby-based executables. But I do not know of such a solution for Bash, Zsh
|
133
|
+
or any other shell. Of course, each scripting language could potentially have
|
134
|
+
its own implementation of DotOpts, which would cover many more executables, but it
|
135
|
+
would still not cover all of them.
|
136
|
+
|
137
|
+
If you are a shell genius and have an epiphany on how it might be done, please
|
138
|
+
drop me a note via [Issues](http://github.com/rubyworks/dotopts/issues). I'd be more
|
139
|
+
than happy to code and maintain it.
|
140
|
+
|
141
|
+
|
142
|
+
## Copyrights & Licensing
|
143
|
+
|
144
|
+
DotOpts is copyrighted open-source software.
|
145
|
+
|
146
|
+
*Copyright (c) 2013 Rubyworks. All rights reserved.*
|
147
|
+
|
148
|
+
It can be modified and redistributed in accordance with the [BSD-2-Clause](http://spdex.org/licenses/bsd-2-clause) license.
|
149
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Example Battery
|
2
|
+
|
3
|
+
## Most basic example
|
4
|
+
|
5
|
+
Given an .opts file:
|
6
|
+
|
7
|
+
yard
|
8
|
+
--title "Big Title"
|
9
|
+
|
10
|
+
When we run `yard`, we should get the arguments:
|
11
|
+
|
12
|
+
--title
|
13
|
+
Big Title
|
14
|
+
|
15
|
+
## Example with later matching commande
|
16
|
+
|
17
|
+
Given an .opts file with a number of profiles:
|
18
|
+
|
19
|
+
something
|
20
|
+
--title "Little Title"
|
21
|
+
|
22
|
+
yard
|
23
|
+
--title "Orange Title"
|
24
|
+
|
25
|
+
When we run `yard` we should get the arguments:
|
26
|
+
|
27
|
+
--title
|
28
|
+
Orange Title
|
29
|
+
|
30
|
+
## Example with multiple matching commands
|
31
|
+
|
32
|
+
Given an .opts file with a number of commands:
|
33
|
+
|
34
|
+
yard
|
35
|
+
--title "First Title"
|
36
|
+
|
37
|
+
something
|
38
|
+
--title "Little Title"
|
39
|
+
|
40
|
+
yard
|
41
|
+
--output-dir "doc"
|
42
|
+
|
43
|
+
When we run `yard` we should get the arguments:
|
44
|
+
|
45
|
+
--title
|
46
|
+
First Title
|
47
|
+
--output-dir
|
48
|
+
doc
|
49
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Examples with Just Profiles
|
2
|
+
|
3
|
+
## Basic example with multiple profiles
|
4
|
+
|
5
|
+
Given an .opts file:
|
6
|
+
|
7
|
+
yard
|
8
|
+
--title "Cool Title"
|
9
|
+
|
10
|
+
[something]
|
11
|
+
yard
|
12
|
+
--title "Big Title"
|
13
|
+
|
14
|
+
When we run `yard`, we should get the arguments:
|
15
|
+
|
16
|
+
--title
|
17
|
+
Cool Title
|
18
|
+
|
19
|
+
## Example with single profile
|
20
|
+
|
21
|
+
Given an .opts file with a leading profile:
|
22
|
+
|
23
|
+
[example]
|
24
|
+
yard
|
25
|
+
--title "Funny Title"
|
26
|
+
|
27
|
+
When we run `p=example yard`, we should get the arguments:
|
28
|
+
|
29
|
+
--title
|
30
|
+
Funny Title
|
31
|
+
|
32
|
+
## Example with later matching profile
|
33
|
+
|
34
|
+
Given an .opts file with a number of profiles:
|
35
|
+
|
36
|
+
[something]
|
37
|
+
yard
|
38
|
+
--title "Little Title"
|
39
|
+
|
40
|
+
[example]
|
41
|
+
yard
|
42
|
+
--title "Orange Title"
|
43
|
+
|
44
|
+
When we run `p=example yard` we should get the arguments:
|
45
|
+
|
46
|
+
--title
|
47
|
+
Orange Title
|
48
|
+
|
49
|
+
## Example with multiple matching profiles
|
50
|
+
|
51
|
+
Given an .opts file with a number of profiles:
|
52
|
+
|
53
|
+
[example]
|
54
|
+
yard
|
55
|
+
--title "First Title"
|
56
|
+
|
57
|
+
[something]
|
58
|
+
yard
|
59
|
+
--title "Little Title"
|
60
|
+
|
61
|
+
[example]
|
62
|
+
yard
|
63
|
+
--output-dir "doc"
|
64
|
+
|
65
|
+
When we run `p=example yard` we should get the arguments:
|
66
|
+
|
67
|
+
--title
|
68
|
+
First Title
|
69
|
+
--output-dir
|
70
|
+
doc
|
71
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# Environment Profile Battery
|
2
|
+
|
3
|
+
## Basic environment profile
|
4
|
+
|
5
|
+
Given an .opts file:
|
6
|
+
|
7
|
+
[a=1]
|
8
|
+
yard
|
9
|
+
--title "Sexy Title"
|
10
|
+
|
11
|
+
When we run `a=1 yard`, we should get the arguments:
|
12
|
+
|
13
|
+
--title
|
14
|
+
Sexy Title
|
15
|
+
|
16
|
+
## Multi-matching profile
|
17
|
+
|
18
|
+
Given an .opts file:
|
19
|
+
|
20
|
+
[a=1 b=2]
|
21
|
+
yard
|
22
|
+
--title "Soapy Title"
|
23
|
+
|
24
|
+
When we run `a=1 b=2 yard`, we should get the arguments:
|
25
|
+
|
26
|
+
--title
|
27
|
+
Soapy Title
|
28
|
+
|
29
|
+
## Multiple multi-matching profiles
|
30
|
+
|
31
|
+
Given an .opts file:
|
32
|
+
|
33
|
+
[a=1 b=1]
|
34
|
+
yard
|
35
|
+
--title "Untimely Title"
|
36
|
+
|
37
|
+
[a=1 b=3]
|
38
|
+
yard
|
39
|
+
--title "Timely Title"
|
40
|
+
|
41
|
+
When we run `a=1 b=3 yard`, we should get the arguments:
|
42
|
+
|
43
|
+
--title
|
44
|
+
Timely Title
|
45
|
+
|
46
|
+
## Multiple matching multi-matching profiles
|
47
|
+
|
48
|
+
Given an .opts file:
|
49
|
+
|
50
|
+
[a=1 b=1]
|
51
|
+
yard
|
52
|
+
--title "Rocking Title"
|
53
|
+
|
54
|
+
[a=1 b=3]
|
55
|
+
yard
|
56
|
+
--title "Hat Title"
|
57
|
+
|
58
|
+
[a=1]
|
59
|
+
yard
|
60
|
+
--output-dir "doc"
|
61
|
+
|
62
|
+
When we run `a=1 b=1 yard`, we should get the arguments:
|
63
|
+
|
64
|
+
--title
|
65
|
+
Rocking Title
|
66
|
+
--output-dir
|
67
|
+
doc
|
68
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Environment Profile Battery
|
2
|
+
|
3
|
+
## Basic profile regex
|
4
|
+
|
5
|
+
Given an .opts file:
|
6
|
+
|
7
|
+
[~"q(x)?"]
|
8
|
+
yard
|
9
|
+
--title "Sexy Title"
|
10
|
+
|
11
|
+
When we run `p=q yard`, we should get the arguments:
|
12
|
+
|
13
|
+
--title
|
14
|
+
Sexy Title
|
15
|
+
|
16
|
+
And when we run `p=qx yard`, we should get the arguments:
|
17
|
+
|
18
|
+
--title
|
19
|
+
Sexy Title
|
20
|
+
|
21
|
+
## Basic environment profile regex
|
22
|
+
|
23
|
+
Given an .opts file:
|
24
|
+
|
25
|
+
[a=~"x|y"]
|
26
|
+
yard
|
27
|
+
--title "Reggie Title"
|
28
|
+
|
29
|
+
When we run `a=x yard`, we should get the arguments:
|
30
|
+
|
31
|
+
--title
|
32
|
+
Reggie Title
|
33
|
+
|
34
|
+
And when we run `a=y yard`, we should get the arguments:
|
35
|
+
|
36
|
+
--title
|
37
|
+
Reggie Title
|
38
|
+
|
39
|
+
## Complex profile
|
40
|
+
|
41
|
+
Given an .opts file:
|
42
|
+
|
43
|
+
[~"q(x)?" a=~"x|y"]
|
44
|
+
yard
|
45
|
+
--title "Complex Title"
|
46
|
+
|
47
|
+
When we run `p=q a=x yard`, we should get the arguments:
|
48
|
+
|
49
|
+
--title
|
50
|
+
Complex Title
|
51
|
+
|
52
|
+
When we run `p=q a=x yard`, we should get the arguments:
|
53
|
+
|
54
|
+
--title
|
55
|
+
Complex Title
|
56
|
+
|
57
|
+
When we run `p=qx a=x yard`, we should get the arguments:
|
58
|
+
|
59
|
+
--title
|
60
|
+
Complex Title
|
61
|
+
|
62
|
+
When we run `p=q a=y yard`, we should get the arguments:
|
63
|
+
|
64
|
+
--title
|
65
|
+
Complex Title
|
66
|
+
|
67
|
+
When we run `p=qx a=y yard`, we should get the arguments:
|
68
|
+
|
69
|
+
--title
|
70
|
+
Complex Title
|
71
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Substituions Battery
|
2
|
+
|
3
|
+
## Most basic example
|
4
|
+
|
5
|
+
Given an .opts file:
|
6
|
+
|
7
|
+
yard
|
8
|
+
--title $title
|
9
|
+
|
10
|
+
When we run `title=Title yard`, we should get the arguments:
|
11
|
+
|
12
|
+
--title
|
13
|
+
Title
|
14
|
+
|
15
|
+
## Environment profile substitutions
|
16
|
+
|
17
|
+
Given an .opts file:
|
18
|
+
|
19
|
+
[a=$b]
|
20
|
+
yard
|
21
|
+
--title "New Title"
|
22
|
+
|
23
|
+
When we run `a=1 b=1 yard`, we should get the arguments:
|
24
|
+
|
25
|
+
--title
|
26
|
+
New Title
|
27
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
When 'Given an .opts file' do |text|
|
2
|
+
ENV.replace({})
|
3
|
+
ARGV.replace([])
|
4
|
+
|
5
|
+
@opts_parser = nil
|
6
|
+
@opts_text = text
|
7
|
+
end
|
8
|
+
|
9
|
+
When 'we run `/(.*?)/`' do |command|
|
10
|
+
args = command.split(/\s+/)
|
11
|
+
|
12
|
+
while (/=/ =~ args.first)
|
13
|
+
name, value = args.shift.split('=')
|
14
|
+
ENV[name] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
ENV['cmd'] = args.shift
|
18
|
+
|
19
|
+
ARGV.replace(args)
|
20
|
+
|
21
|
+
@opts_parser = DotOpts::Parser.parse(@opts_text)
|
22
|
+
end
|
23
|
+
|
24
|
+
When 'we should get the arguments' do |text|
|
25
|
+
args = text.split("\n").map{ |x| x.strip }
|
26
|
+
args.assert == @opts_parser.arguments
|
27
|
+
end
|
28
|
+
|
data/lib/dotopts.rb
ADDED
data/lib/dotopts/api.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module DotOpts
|
2
|
+
require 'dotopts/parser'
|
3
|
+
|
4
|
+
#
|
5
|
+
CONFIG_FILE = '.options'
|
6
|
+
|
7
|
+
# Configure
|
8
|
+
def self.configure!(config_file)
|
9
|
+
if config_file = config_file || config_file()
|
10
|
+
text = File.read(config_file)
|
11
|
+
parser = Parser.parse(text)
|
12
|
+
ARGV.concat parser.arguments
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the `.ruby` file of the current project.
|
17
|
+
#
|
18
|
+
# @return {String] The .ruby file of the project.
|
19
|
+
def self.config_file
|
20
|
+
if project_root
|
21
|
+
file = File.join(project_root, CONFIG_FILE)
|
22
|
+
return file if File.exist?(file)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Find the root directory of the current project.
|
27
|
+
#
|
28
|
+
# @return [String,nil] The root directory of the project.
|
29
|
+
def self.project_root(start_dir=Dir.pwd)
|
30
|
+
dir = start_dir
|
31
|
+
home = File.expand_path('~')
|
32
|
+
until dir == home || dir == '/'
|
33
|
+
if file = Dir[File.join(dir, '{.ruby,.git,.hg}')].first
|
34
|
+
return dir
|
35
|
+
end
|
36
|
+
dir = File.dirname(dir)
|
37
|
+
end
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module DotOpts
|
2
|
+
|
3
|
+
class Parser
|
4
|
+
require 'shellwords'
|
5
|
+
|
6
|
+
#
|
7
|
+
RE_PROFILE_HEADER = /^\[/
|
8
|
+
|
9
|
+
#
|
10
|
+
RE_COMMAND_HEADER = /^\w/
|
11
|
+
|
12
|
+
#
|
13
|
+
RE_BLANK_STRING = /^\s*$/
|
14
|
+
|
15
|
+
#
|
16
|
+
def self.parse(text)
|
17
|
+
parser = new(text)
|
18
|
+
parser.parse
|
19
|
+
parser
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
def initialize(text)
|
24
|
+
@text = text
|
25
|
+
@arguments = []
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
attr :text
|
30
|
+
|
31
|
+
#
|
32
|
+
attr :arguments
|
33
|
+
|
34
|
+
#
|
35
|
+
def parse
|
36
|
+
lines = @text.lines.to_a
|
37
|
+
|
38
|
+
remove_initial_blank_lines(lines)
|
39
|
+
|
40
|
+
# put initial non-profiled settings last
|
41
|
+
if lines.first !~ RE_PROFILE_HEADER
|
42
|
+
index = lines.index{ |line| line =~ RE_PROFILE_HEADER }
|
43
|
+
if index
|
44
|
+
lines = lines[index..-1] + ['[]'] + lines[0...index]
|
45
|
+
else
|
46
|
+
lines = ['[]'] + lines
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
parse_profiles(lines)
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
def parse_profiles(lines)
|
55
|
+
until lines.empty?
|
56
|
+
line = lines.first.rstrip
|
57
|
+
if md = RE_PROFILE_HEADER.match(line)
|
58
|
+
profile = md.post_match.chomp(']')
|
59
|
+
matches = shellwords(profile).all? do |shellword|
|
60
|
+
case shellword
|
61
|
+
when /^\~/
|
62
|
+
true if Regexp.new(shellword.sub('~','')) === (ENV['profile'] || ENV['p']).to_s
|
63
|
+
when /=~/
|
64
|
+
name, value = shellword.split('=~')
|
65
|
+
#name = 'profile' if name.empty?
|
66
|
+
true if Regexp.new(value) === ENV[name]
|
67
|
+
when /=/
|
68
|
+
name, value = shellword.split('=')
|
69
|
+
#name = 'profile' if name.empty?
|
70
|
+
true if subenv(value) == ENV[name]
|
71
|
+
else
|
72
|
+
true if shellword == (ENV['profile'] || ENV['p']).to_s
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if matches
|
77
|
+
lines.shift while RE_PROFILE_HEADER =~ lines.first
|
78
|
+
lines.shift while RE_BLANK_STRING =~ lines.first
|
79
|
+
parse_commands(lines)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
lines.shift
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
def parse_commands(lines)
|
88
|
+
while line = lines.first
|
89
|
+
line = line.strip
|
90
|
+
if md = RE_COMMAND_HEADER.match(line)
|
91
|
+
if current_command == line
|
92
|
+
lines.shift while RE_COMMAND_HEADER =~ lines.first
|
93
|
+
lines.shift while RE_BLANK_STRING =~ lines.first
|
94
|
+
parse_environment(lines)
|
95
|
+
parse_arguments(lines)
|
96
|
+
next
|
97
|
+
end
|
98
|
+
elsif RE_PROFILE_HEADER.match(line)
|
99
|
+
return
|
100
|
+
end
|
101
|
+
lines.shift
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
def parse_environment(lines)
|
107
|
+
while line = lines.first
|
108
|
+
line = line.strip
|
109
|
+
next if line.empty?
|
110
|
+
break unless line.start_with?('$ ')
|
111
|
+
line = line.sub(/\$\s+/, '')
|
112
|
+
shellwords(line).each do |s|
|
113
|
+
name, value = s.split('=')
|
114
|
+
@environment[name] = subenv(value) unless name.empty?
|
115
|
+
end
|
116
|
+
lines.shift
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
def parse_arguments(lines)
|
122
|
+
while line = lines.first
|
123
|
+
line = line.rstrip
|
124
|
+
break if RE_PROFILE_HEADER =~ line
|
125
|
+
break if RE_COMMAND_HEADER =~ line
|
126
|
+
shellwords(line).each do |s|
|
127
|
+
@arguments << subenv(s) unless s.empty?
|
128
|
+
end
|
129
|
+
lines.shift
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# @todo Note sure the cmd environment variable override is a good idea.
|
135
|
+
#
|
136
|
+
def current_command
|
137
|
+
ENV['cmd'] || File.basename($0)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Substitute environment variables.
|
141
|
+
#
|
142
|
+
# @return [String]
|
143
|
+
def subenv(value)
|
144
|
+
value.gsub(/\$(\w+)/){ |m| ENV[$1] }
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
def shellwords(value)
|
149
|
+
Shellwords.shellwords(value)
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
def remove_initial_blank_lines(lines)
|
154
|
+
lines.shift while RE_BLANK_STRING =~ lines.first
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spectroscope'
|
2
|
+
require 'ae'
|
3
|
+
|
4
|
+
require 'dotopts/api'
|
5
|
+
|
6
|
+
module Kernel
|
7
|
+
|
8
|
+
def with_env(hash)
|
9
|
+
hold = {}
|
10
|
+
hash.each do |name, value|
|
11
|
+
name, value = name.to_s, value.to_s
|
12
|
+
hold[name], ENV[name] = ENV[name], value
|
13
|
+
end
|
14
|
+
begin
|
15
|
+
yield
|
16
|
+
ensure
|
17
|
+
hold.each do |name, value|
|
18
|
+
ENV[name] = value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/spec/spec_api.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
describe DotOpts do
|
4
|
+
|
5
|
+
it "can configure!" do
|
6
|
+
ENV['cmd'] = 'yard' # FIXME: try `foo` and watch what happens
|
7
|
+
|
8
|
+
example_avex_file = File.dirname(__FILE__) + '/fixtures/yard.opts'
|
9
|
+
|
10
|
+
DotOpts.configure!(example_avex_file)
|
11
|
+
|
12
|
+
ARGV[-2].assert == '--title'
|
13
|
+
ARGV[-1].assert == 'Big Title'
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
data/spec/spec_parser.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
describe DotOpts::Parser do
|
4
|
+
|
5
|
+
before do
|
6
|
+
ENV['cmd'] = 'yard' # FIXME: try `foo` and watch what happens
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "without profiles" do
|
10
|
+
|
11
|
+
it "can parse configuration" do
|
12
|
+
text = "yard\n" +
|
13
|
+
" --title Super"
|
14
|
+
parser = DotOpts::Parser.parse(text)
|
15
|
+
|
16
|
+
parser.arguments.assert == ['--title', 'Super']
|
17
|
+
end
|
18
|
+
|
19
|
+
it "can parse configuration with multiple arguments" do
|
20
|
+
text = "yard\n" +
|
21
|
+
" --title Super\n" +
|
22
|
+
" --private\n"
|
23
|
+
|
24
|
+
parser = DotOpts::Parser.parse(text)
|
25
|
+
|
26
|
+
parser.arguments.assert == ['--title', 'Super', '--private']
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "with profiles" do
|
32
|
+
|
33
|
+
it "can parse configuration with initial profile" do
|
34
|
+
text = "[example]\n" +
|
35
|
+
"yard\n" +
|
36
|
+
" --title Super"
|
37
|
+
|
38
|
+
parser = with_env('profile'=>'example') do
|
39
|
+
DotOpts::Parser.parse(text)
|
40
|
+
end
|
41
|
+
|
42
|
+
parser.arguments.assert == ['--title', 'Super']
|
43
|
+
end
|
44
|
+
|
45
|
+
it "can parse configuration with lower profile" do
|
46
|
+
text = "[something]\n" +
|
47
|
+
"yard\n" +
|
48
|
+
" --title Sucky\n" +
|
49
|
+
"\n" +
|
50
|
+
"[example]\n" +
|
51
|
+
"yard\n" +
|
52
|
+
" --title Super"
|
53
|
+
|
54
|
+
parser = with_env('profile'=>'example') do
|
55
|
+
DotOpts::Parser.parse(text)
|
56
|
+
end
|
57
|
+
|
58
|
+
parser.arguments.assert == ['--title', 'Super']
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
after do
|
64
|
+
ENV['cmd'] = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dotopts
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- trans
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: qed
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: spectroscope
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: ae
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: DotOpts is an automatic commandline argument augmenter for Ruby tools.
|
63
|
+
email:
|
64
|
+
- transfire@gmail.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files:
|
68
|
+
- LICENSE.txt
|
69
|
+
- HISTORY.md
|
70
|
+
- README.md
|
71
|
+
files:
|
72
|
+
- .index
|
73
|
+
- demo/09_battery/profiles_basic.md
|
74
|
+
- demo/09_battery/commands_only.md
|
75
|
+
- demo/09_battery/profiles_regex.md
|
76
|
+
- demo/09_battery/profiles_complex.md
|
77
|
+
- demo/09_battery/substitution.md
|
78
|
+
- demo/applique/require.rb
|
79
|
+
- demo/applique/battery.rb
|
80
|
+
- lib/dotopts/api.rb
|
81
|
+
- lib/dotopts/parser.rb
|
82
|
+
- lib/dotopts.rb
|
83
|
+
- spec/spec_api.rb
|
84
|
+
- spec/helper.rb
|
85
|
+
- spec/spec_parser.rb
|
86
|
+
- spec/fixtures/yard.opts
|
87
|
+
- Gemfile.lock
|
88
|
+
- LICENSE.txt
|
89
|
+
- HISTORY.md
|
90
|
+
- README.md
|
91
|
+
homepage: http://rubyworks.github.com/dotopts
|
92
|
+
licenses:
|
93
|
+
- BSD-2-Clause
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 1.8.24
|
113
|
+
signing_key:
|
114
|
+
specification_version: 3
|
115
|
+
summary: Automatic Arguments for Ruby
|
116
|
+
test_files:
|
117
|
+
- spec/spec_api.rb
|
118
|
+
- spec/helper.rb
|
119
|
+
- spec/spec_parser.rb
|
120
|
+
has_rdoc:
|