planter-cli 3.0.1 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.gitmodules +3 -0
- data/.rubocop.yml +1 -2
- data/CHANGELOG.md +24 -0
- data/README.md +85 -4
- data/bin/plant +1 -1
- data/docker/Dockerfile +2 -4
- data/docker/Dockerfile-2.6 +4 -5
- data/docker/Dockerfile-2.7 +4 -5
- data/docker/Dockerfile-3.0 +4 -4
- data/docker/Dockerfile-3.3 +12 -0
- data/docker/bash_profile +2 -1
- data/docker/sources.list +11 -0
- data/lib/planter/array.rb +56 -1
- data/lib/planter/filelist.rb +5 -4
- data/lib/planter/hash.rb +24 -0
- data/lib/planter/plant.rb +6 -4
- data/lib/planter/prompt.rb +56 -16
- data/lib/planter/string.rb +143 -5
- data/lib/planter/tag.rb +39 -2
- data/lib/planter/version.rb +1 -1
- data/lib/planter.rb +30 -17
- data/lib/tty-spinner/.editorconfig +9 -0
- data/lib/tty-spinner/.github/FUNDING.yml +1 -0
- data/lib/tty-spinner/.github/ISSUE_TEMPLATE/BUG_REPORT.md +31 -0
- data/lib/tty-spinner/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +23 -0
- data/lib/tty-spinner/.github/ISSUE_TEMPLATE/config.yml +5 -0
- data/lib/tty-spinner/.github/PULL_REQUEST_TEMPLATE.md +19 -0
- data/lib/tty-spinner/.github/workflows/ci.yml +59 -0
- data/lib/tty-spinner/.gitignore +14 -0
- data/lib/tty-spinner/.rspec +2 -0
- data/lib/tty-spinner/.rubocop.yml +78 -0
- data/lib/tty-spinner/CHANGELOG.md +151 -0
- data/lib/tty-spinner/CODE_OF_CONDUCT.md +132 -0
- data/lib/tty-spinner/Gemfile +17 -0
- data/lib/tty-spinner/LICENSE.txt +22 -0
- data/lib/tty-spinner/README.md +581 -0
- data/lib/tty-spinner/Rakefile +10 -0
- data/lib/tty-spinner/appveyor.yml +33 -0
- data/lib/tty-spinner/bin/console +14 -0
- data/lib/tty-spinner/bin/setup +8 -0
- data/lib/tty-spinner/demo.gif +0 -0
- data/lib/tty-spinner/examples/auto_spin.rb +10 -0
- data/lib/tty-spinner/examples/basic.rb +10 -0
- data/lib/tty-spinner/examples/clear.rb +11 -0
- data/lib/tty-spinner/examples/color.rb +14 -0
- data/lib/tty-spinner/examples/error.rb +11 -0
- data/lib/tty-spinner/examples/formats.rb +13 -0
- data/lib/tty-spinner/examples/hide_cursor.rb +14 -0
- data/lib/tty-spinner/examples/log.rb +13 -0
- data/lib/tty-spinner/examples/multi/basic.rb +15 -0
- data/lib/tty-spinner/examples/multi/basic_top_level.rb +15 -0
- data/lib/tty-spinner/examples/multi/custom_style.rb +28 -0
- data/lib/tty-spinner/examples/multi/files.rb +16 -0
- data/lib/tty-spinner/examples/multi/jobs.rb +11 -0
- data/lib/tty-spinner/examples/multi/multi.rb +19 -0
- data/lib/tty-spinner/examples/multi/multi_top_level.rb +20 -0
- data/lib/tty-spinner/examples/multi/pause.rb +28 -0
- data/lib/tty-spinner/examples/multi/threaded.rb +30 -0
- data/lib/tty-spinner/examples/pause.rb +24 -0
- data/lib/tty-spinner/examples/run.rb +20 -0
- data/lib/tty-spinner/examples/success.rb +11 -0
- data/lib/tty-spinner/examples/threaded.rb +13 -0
- data/lib/tty-spinner/examples/update.rb +13 -0
- data/lib/tty-spinner/lib/tty/spinner/formats.rb +274 -0
- data/lib/tty-spinner/lib/tty/spinner/multi.rb +352 -0
- data/lib/tty-spinner/lib/tty/spinner/version.rb +7 -0
- data/lib/tty-spinner/lib/tty/spinner.rb +604 -0
- data/lib/tty-spinner/lib/tty-spinner.rb +2 -0
- data/lib/tty-spinner/spec/spec_helper.rb +52 -0
- data/lib/tty-spinner/spec/unit/auto_spin_spec.rb +25 -0
- data/lib/tty-spinner/spec/unit/clear_spec.rb +16 -0
- data/lib/tty-spinner/spec/unit/error_spec.rb +53 -0
- data/lib/tty-spinner/spec/unit/events_spec.rb +35 -0
- data/lib/tty-spinner/spec/unit/formats_spec.rb +9 -0
- data/lib/tty-spinner/spec/unit/frames_spec.rb +31 -0
- data/lib/tty-spinner/spec/unit/hide_cursor_spec.rb +51 -0
- data/lib/tty-spinner/spec/unit/job_spec.rb +12 -0
- data/lib/tty-spinner/spec/unit/join_spec.rb +10 -0
- data/lib/tty-spinner/spec/unit/log_spec.rb +60 -0
- data/lib/tty-spinner/spec/unit/multi/auto_spin_spec.rb +32 -0
- data/lib/tty-spinner/spec/unit/multi/error_spec.rb +107 -0
- data/lib/tty-spinner/spec/unit/multi/line_inset_spec.rb +57 -0
- data/lib/tty-spinner/spec/unit/multi/on_spec.rb +11 -0
- data/lib/tty-spinner/spec/unit/multi/register_spec.rb +46 -0
- data/lib/tty-spinner/spec/unit/multi/spin_spec.rb +101 -0
- data/lib/tty-spinner/spec/unit/multi/stop_spec.rb +95 -0
- data/lib/tty-spinner/spec/unit/multi/success_spec.rb +108 -0
- data/lib/tty-spinner/spec/unit/new_spec.rb +25 -0
- data/lib/tty-spinner/spec/unit/pause_spec.rb +43 -0
- data/lib/tty-spinner/spec/unit/reset_spec.rb +19 -0
- data/lib/tty-spinner/spec/unit/run_spec.rb +30 -0
- data/lib/tty-spinner/spec/unit/spin_spec.rb +117 -0
- data/lib/tty-spinner/spec/unit/stop_spec.rb +88 -0
- data/lib/tty-spinner/spec/unit/success_spec.rb +53 -0
- data/lib/tty-spinner/spec/unit/tty_spec.rb +8 -0
- data/lib/tty-spinner/spec/unit/update_spec.rb +85 -0
- data/lib/tty-spinner/tasks/console.rake +11 -0
- data/lib/tty-spinner/tasks/coverage.rake +11 -0
- data/lib/tty-spinner/tasks/spec.rake +29 -0
- data/lib/tty-spinner/tty-spinner.gemspec +36 -0
- data/scripts/runtests.sh +1 -1
- data/spec/cli_spec.rb +27 -0
- data/spec/planter/string_spec.rb +31 -4
- data/spec/spec_helper.rb +26 -0
- data/spec/templates/test/_planter.yml +3 -6
- data/src/_README.md +85 -4
- metadata +86 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d811f48053b6544dc93bec282620300d673dc5524cc534e0b4fe59d194d09c19
|
4
|
+
data.tar.gz: 8da8c9f74029c96f7286f25c80be21a35d87237c2942db24a9864d881d04f509
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73daffea9046af25fb1c1d1839eb622ca87ec43ab2d5aab4bbf6f593cb4ea24176f9f443aadf4178610d181eb4cec5276ed92cd7ca880f1d5a72ab364e397ab9
|
7
|
+
data.tar.gz: 104ca18f851112b4142f5ef6e5b31eb564d8e83be9de87f0cb1107a42e35f180adf23858896a599f3aeee7eff2683b90b03fe4ffc6ae8dc3945bc237ffffaf14
|
data/.gitignore
CHANGED
data/.gitmodules
ADDED
data/.rubocop.yml
CHANGED
@@ -11,7 +11,7 @@ AllCops:
|
|
11
11
|
- Gemfile
|
12
12
|
- Guardfile
|
13
13
|
- Rakefile
|
14
|
-
- bin/
|
14
|
+
- bin/plant
|
15
15
|
- lib/**/*.rb
|
16
16
|
Exclude:
|
17
17
|
- pkg/**/*.rb
|
@@ -41,7 +41,6 @@ Metrics/BlockLength:
|
|
41
41
|
Max: 45
|
42
42
|
Exclude:
|
43
43
|
- Rakefile
|
44
|
-
- bin/untitled
|
45
44
|
- lib/*.rb
|
46
45
|
|
47
46
|
Metrics/ClassLength:
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
### 3.0.3
|
2
|
+
|
3
|
+
2024-09-02 08:02
|
4
|
+
|
5
|
+
#### CHANGED
|
6
|
+
|
7
|
+
- Multiline is now "paragraph"
|
8
|
+
- Module type now requires "mod" at minimum
|
9
|
+
|
10
|
+
#### NEW
|
11
|
+
|
12
|
+
- Multiple choice variable type (ch|mu)
|
13
|
+
- If/then logic in templates
|
14
|
+
|
15
|
+
### 3.0.2
|
16
|
+
|
17
|
+
2024-09-01 09:46
|
18
|
+
|
19
|
+
#### IMPROVED
|
20
|
+
|
21
|
+
- Add basic CLI tests
|
22
|
+
- Better debug output and output of info messages above spinner
|
23
|
+
- Handle Bash-style globs in file: filenames
|
24
|
+
|
1
25
|
### 3.0.1
|
2
26
|
|
3
27
|
2024-08-31 14:19
|
data/README.md
CHANGED
@@ -27,9 +27,9 @@ git_init: false
|
|
27
27
|
preserve_tags: true
|
28
28
|
```
|
29
29
|
|
30
|
-
### Scripts
|
30
|
+
### Scripts
|
31
31
|
|
32
|
-
Scripts for execution after planting can be stored in `~/.config/planter/scripts` and referenced by filename only. Alternatively, scripts may be stored within a template in a `
|
32
|
+
Scripts for execution after planting can be stored in `~/.config/planter/scripts` and referenced by filename only. Alternatively, scripts may be stored within a template in a `_scripts` subfolder.
|
33
33
|
|
34
34
|
Scripts can be executable files in any language, and receive the template directory and the planted directory as arguments $1 and $2.
|
35
35
|
|
@@ -47,7 +47,7 @@ First, there's a `variables` section that defines variables used in the template
|
|
47
47
|
variables:
|
48
48
|
- key: var_key
|
49
49
|
prompt: Prompt text
|
50
|
-
type: string # [string,
|
50
|
+
type: string # [string,paragraph,float,integer,number,date,choice] defaults to string
|
51
51
|
# value: (force value, string can include %%variables%% and regexes will be replaced. For date type can be today, time, now, etc.)
|
52
52
|
default: Untitled
|
53
53
|
min: 1
|
@@ -64,6 +64,85 @@ repo: # If a repository URL is provided, it will be pulled and duplicated instea
|
|
64
64
|
|
65
65
|
In a template you can add a default value for a placholder by adding `%default value` to it. For example, `%%project%Default Project%%` will set the placeholder to `Default Project` if the variable value matches the default value in the configuration. This allows you to accept the default on the command line but have a different value inserted in the template. To use another variable in its place, use `$KEY` in the placeholder, e.g. `%%project%$title%%` will replace the `project` key with the value of `title` if the default is selected. Modifiers can be used on either side of the `%`, e.g. `%%project%$title:snake%%`.
|
66
66
|
|
67
|
+
#### Multiple choice type
|
68
|
+
|
69
|
+
If the `type` is set to `choice`, then the key `choices` can contain a hash or array of choices. The key that accepts the choice should be surrounded with parenthesis (required for each choice).
|
70
|
+
|
71
|
+
If a Hash is defined, each choice can have a result string:
|
72
|
+
|
73
|
+
```yaml
|
74
|
+
variables:
|
75
|
+
- key: shebang
|
76
|
+
prompt: Shebang line
|
77
|
+
type: choice
|
78
|
+
default: r
|
79
|
+
choices:
|
80
|
+
(r)uby: "#! /usr/bin/env ruby"
|
81
|
+
(j)avascript: "#! /usr/bin/env node"
|
82
|
+
(p)ython: "#! /usr/bin/env python"
|
83
|
+
(b)ash: "#! /bin/bash"
|
84
|
+
(z)sh: "#! /bin/zsh"
|
85
|
+
```
|
86
|
+
|
87
|
+
If an array is defined, the string of the choice will also be its result:
|
88
|
+
|
89
|
+
```yaml
|
90
|
+
variables:
|
91
|
+
- key: language
|
92
|
+
prompt: Programming language
|
93
|
+
type: choice
|
94
|
+
default: 1
|
95
|
+
choices:
|
96
|
+
- 1. ruby
|
97
|
+
- 1. javascript
|
98
|
+
- 1. python
|
99
|
+
- 1. bash
|
100
|
+
- 1. zsh
|
101
|
+
```
|
102
|
+
|
103
|
+
If the choice starts with a number (as above), then a numeric list will be generated and typing the associated index number will accept that choice. Numeric lists are automatically numbered, so the preceding digit doesn't matter, as long as it's a digit. In this case a default can be defined with an integer for its placement in the list (starting with 1), and parenthesis aren't required.
|
104
|
+
|
105
|
+
#### If/then logic
|
106
|
+
|
107
|
+
A template can use if/then logic, which is useful with multiple choice types. It can be applied to any type, though.
|
108
|
+
|
109
|
+
The format for if/then logic is:
|
110
|
+
|
111
|
+
```
|
112
|
+
%%if KEY OPERATOR VALUE%%
|
113
|
+
content
|
114
|
+
%%else if KEY OPERATOR VALUE2%%
|
115
|
+
content 2
|
116
|
+
%%else%%
|
117
|
+
content 3
|
118
|
+
%%endif%%
|
119
|
+
```
|
120
|
+
|
121
|
+
There should be no spaces around the comparison, e.g. `%% if language == javascript %%` won't work. The block must start with an `if` statement and end with `%%endif%%` or `%%end%%`. The `%%else%%` statement is optional -- if it doesn't exist then the entire block will be removed if no conditions are met.
|
122
|
+
|
123
|
+
The key should be an existing key defined in `variables`. The operator can be any of:
|
124
|
+
|
125
|
+
- `==` or `=` (equals)
|
126
|
+
- `=~` (matches regex)
|
127
|
+
- `*=` (contains)
|
128
|
+
- `^=` (starts with)
|
129
|
+
- `$=` (ends with)
|
130
|
+
- `>` (greater than)
|
131
|
+
- `>=` (greater than or equal)
|
132
|
+
- `<` (less than)
|
133
|
+
- `<=` (less than or equal)
|
134
|
+
|
135
|
+
The value after the operator doesn't need to be quoted, anything after the operator will be compared to the value of the key.
|
136
|
+
|
137
|
+
Logic can be used on multiple lines like the example above, or on a single line (useful for filenames):
|
138
|
+
|
139
|
+
```
|
140
|
+
%%project%%.%%if language == javascript%%js%%else if language == ruby%%rb%%else%%sh%%endif%%
|
141
|
+
```
|
142
|
+
|
143
|
+
Content within if/else blocks can contain variables.
|
144
|
+
|
145
|
+
|
67
146
|
### File-specific handling
|
68
147
|
|
69
148
|
A `files` dictionary can specify how to handle specific files. Options are `copy`, `overwrite`, `merge`, or `ask`. The key for each entry is a filename or glob that matches the source filename (accounting for template variables if applicable):
|
@@ -74,6 +153,8 @@ files:
|
|
74
153
|
"%%title%%.md": overwrite
|
75
154
|
```
|
76
155
|
|
156
|
+
Filenames can include wildcards (`*`, `?`), and Bash-ish globbing (`[0-9]`, `[a-z]`, `{one,two,three}`).
|
157
|
+
|
77
158
|
If `merge` is specified, then the source file is scanned for merge comments and those are merged if they don't exist in the copied/existing file. If no merge comments are defined, then the entire contents of the source file are appended to the destination file (unless the file already matches the source). Merge comments start with `merge` and end with `/merge` and can have any comment syntax preceding them, for example:
|
78
159
|
|
79
160
|
```
|
@@ -104,7 +185,7 @@ replacements:
|
|
104
185
|
"(main|app)\.js": "%%script:lower%%.js"
|
105
186
|
```
|
106
187
|
|
107
|
-
Replacements are performed on both file/directory names and file contents.
|
188
|
+
Replacements are performed on both file/directory names and file contents. This is especially handy when the source of the plant is a Git repo, allowing the replacement of elements without having to create %%templated%% filenames and contents.
|
108
189
|
|
109
190
|
### Finder Tags
|
110
191
|
|
data/bin/plant
CHANGED
@@ -105,7 +105,7 @@ elsif ARGV.count.zero?
|
|
105
105
|
end
|
106
106
|
|
107
107
|
ARGV.each do |template|
|
108
|
-
Planter.spinner.update(title: 'Initializing configuration')
|
108
|
+
# Planter.spinner.update(title: 'Initializing configuration')
|
109
109
|
Planter.config = template
|
110
110
|
app = Planter::Plant.new
|
111
111
|
app.plant
|
data/docker/Dockerfile
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
FROM ruby:3.0.1
|
2
|
-
# RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
3
2
|
RUN mkdir /planter
|
4
3
|
WORKDIR /planter
|
5
|
-
|
6
4
|
RUN gem install bundler:2.2.29
|
7
|
-
|
5
|
+
COPY ./docker/sources.list /etc/apt/sources.list
|
6
|
+
RUN apt-get update -y --allow-insecure-repositories || true
|
8
7
|
RUN apt-get install -y less vim
|
9
8
|
COPY ./docker/inputrc /root/.inputrc
|
10
9
|
COPY ./docker/bash_profile /root/.bash_profile
|
11
|
-
RUN mkdir -p /root/.config/planter/templates/test
|
12
10
|
CMD ["/planter/scripts/runtests.sh"]
|
data/docker/Dockerfile-2.6
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
FROM ruby:2.6
|
2
|
-
# RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
3
2
|
RUN mkdir /planter
|
4
3
|
WORKDIR /planter
|
5
|
-
# COPY ./ /planter/
|
6
4
|
RUN gem install bundler:2.2.29
|
7
|
-
|
8
|
-
|
5
|
+
COPY ./docker/sources.list /etc/apt/sources.list
|
6
|
+
RUN apt-get update -y --allow-insecure-repositories || true
|
7
|
+
RUN apt-get install -y sudo || true
|
8
|
+
RUN sudo apt-get install -y less vim || true
|
9
9
|
COPY ./docker/inputrc /root/.inputrc
|
10
10
|
COPY ./docker/bash_profile /root/.bash_profile
|
11
|
-
RUN mkdir -p /root/.config/planter/templates/test
|
12
11
|
CMD ["/planter/scripts/runtests.sh"]
|
data/docker/Dockerfile-2.7
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
FROM ruby:2.7
|
2
|
-
# RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
3
2
|
RUN mkdir /planter
|
4
3
|
WORKDIR /planter
|
5
|
-
# COPY ./ /planter/
|
6
4
|
RUN gem install bundler:2.2.29
|
7
|
-
|
8
|
-
RUN apt-get
|
5
|
+
COPY ./docker/sources.list /etc/apt/sources.list
|
6
|
+
RUN apt-get update -y --allow-insecure-repositories || true
|
7
|
+
RUN apt-get install -y sudo || true
|
8
|
+
RUN sudo apt-get install -y less vim || true
|
9
9
|
COPY ./docker/inputrc /root/.inputrc
|
10
10
|
COPY ./docker/bash_profile /root/.bash_profile
|
11
|
-
RUN mkdir -p /root/.config/planter/templates/test
|
12
11
|
CMD ["/planter/scripts/runtests.sh"]
|
data/docker/Dockerfile-3.0
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
FROM ruby:3.0.0
|
2
|
-
# RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
3
2
|
RUN mkdir /planter
|
4
3
|
WORKDIR /planter
|
5
|
-
# COPY ./ /planter/
|
6
4
|
RUN gem install bundler:2.2.29
|
7
|
-
|
8
|
-
RUN apt-get
|
5
|
+
COPY ./docker/sources.list /etc/apt/sources.list
|
6
|
+
RUN apt-get update -y --allow-insecure-repositories || true
|
7
|
+
RUN apt-get install -y sudo || true
|
8
|
+
RUN sudo apt-get install -y less vim || true
|
9
9
|
COPY ./docker/inputrc /root/.inputrc
|
10
10
|
COPY ./docker/bash_profile /root/.bash_profile
|
11
11
|
CMD ["/planter/scripts/runtests.sh"]
|
@@ -0,0 +1,12 @@
|
|
1
|
+
FROM ruby:3.3.0
|
2
|
+
# RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
3
|
+
RUN mkdir /planter
|
4
|
+
WORKDIR /planter
|
5
|
+
RUN gem install bundler:2.2.29
|
6
|
+
COPY ./docker/sources.list /etc/apt/sources.list
|
7
|
+
RUN apt-get update -y --allow-insecure-repositories || true
|
8
|
+
RUN apt-get install -y sudo || true
|
9
|
+
RUN sudo apt-get install -y less vim || true
|
10
|
+
COPY ./docker/inputrc /root/.inputrc
|
11
|
+
COPY ./docker/bash_profile /root/.bash_profile
|
12
|
+
CMD ["/planter/scripts/runtests.sh"]
|
data/docker/bash_profile
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
export GLI_DEBUG=true
|
3
3
|
export EDITOR="/usr/bin/vim"
|
4
4
|
alias b="bundle exec bin/plant"
|
5
|
+
alias be="bundle exec"
|
5
6
|
alias quit="exit"
|
6
7
|
|
7
8
|
shopt -s nocaseglob
|
@@ -11,5 +12,5 @@ shopt -s histverify
|
|
11
12
|
shopt -s cmdhist
|
12
13
|
|
13
14
|
cd /planter
|
14
|
-
bundle
|
15
|
+
bundle update
|
15
16
|
gem install pkg/*.gem
|
data/docker/sources.list
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
deb http://archive.ubuntu.com/ubuntu/ focal main restricted
|
2
|
+
deb http://archive.ubuntu.com/ubuntu/ focal-updates main restricted
|
3
|
+
deb http://archive.ubuntu.com/ubuntu/ focal universe
|
4
|
+
deb http://archive.ubuntu.com/ubuntu/ focal-updates universe
|
5
|
+
deb http://archive.ubuntu.com/ubuntu/ focal multiverse
|
6
|
+
deb http://archive.ubuntu.com/ubuntu/ focal-updates multiverse
|
7
|
+
deb http://archive.ubuntu.com/ubuntu/ focal-backports main restricted universe multiverse
|
8
|
+
|
9
|
+
deb http://security.ubuntu.com/ubuntu focal-security main restricted
|
10
|
+
deb http://security.ubuntu.com/ubuntu focal-security universe
|
11
|
+
deb http://security.ubuntu.com/ubuntu focal-security multiversesudo apt update
|
data/lib/planter/array.rb
CHANGED
@@ -12,7 +12,7 @@ module Planter
|
|
12
12
|
## @param default [String] The color templated output string
|
13
13
|
##
|
14
14
|
def abbr_choices(default: nil)
|
15
|
-
chars = join(' ').scan(/\((.)\)/).map { |c| c[0] }
|
15
|
+
chars = join(' ').scan(/\((?:(.)\.?)\)/).map { |c| c[0] }
|
16
16
|
out = String.new
|
17
17
|
out << '{xdw}['
|
18
18
|
out << chars.map do |c|
|
@@ -25,6 +25,61 @@ module Planter
|
|
25
25
|
out << '{dw}]{x}'
|
26
26
|
end
|
27
27
|
|
28
|
+
## Convert an array of choices to a string with optional numbering
|
29
|
+
##
|
30
|
+
## @param numeric [Boolean] Include numbering
|
31
|
+
##
|
32
|
+
## @return [Array] Array of choices
|
33
|
+
##
|
34
|
+
def to_options(numeric)
|
35
|
+
map.with_index do |c, i|
|
36
|
+
# v = c.to_s.match(/\(?([a-z]|\d+\.?)\)?/)[1].strip
|
37
|
+
if numeric
|
38
|
+
"(#{i + 1}). #{c.to_s.sub(/^\(?\d+\.?\)? +/, '')}"
|
39
|
+
else
|
40
|
+
c
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
## Find the index of a choice in an array of choices
|
46
|
+
##
|
47
|
+
## @param choice [String] The choice to find
|
48
|
+
##
|
49
|
+
## @return [Integer] Index of the choice
|
50
|
+
##
|
51
|
+
def option_index(choice)
|
52
|
+
index = find_index { |c| c.to_s.match(/\((.+)\)/)[1].strip.sub(/\.$/, '') == choice }
|
53
|
+
index || false
|
54
|
+
end
|
55
|
+
|
56
|
+
## Convert an array of choices to a hash
|
57
|
+
## - If the array contains hashes, they are converted to key/value pairs
|
58
|
+
## - If the array contains strings, they are used as both key and value
|
59
|
+
##
|
60
|
+
## @return [Hash] Hash of choices
|
61
|
+
##
|
62
|
+
def choices_to_hash
|
63
|
+
hash = {}
|
64
|
+
each do |c|
|
65
|
+
if c.is_a?(Hash)
|
66
|
+
hash[c.keys.first.to_s] = c.values.first.to_s
|
67
|
+
else
|
68
|
+
hash[c.to_s] = c.to_s
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
hash
|
73
|
+
end
|
74
|
+
|
75
|
+
## Clean strings in an array by removing numbers and parentheses
|
76
|
+
##
|
77
|
+
## @return [Array] Array with cleaned strings
|
78
|
+
##
|
79
|
+
def to_values
|
80
|
+
map(&:clean_value)
|
81
|
+
end
|
82
|
+
|
28
83
|
##
|
29
84
|
## Stringify keys in an array of hashes or arrays
|
30
85
|
##
|
data/lib/planter/filelist.rb
CHANGED
@@ -39,7 +39,7 @@ module Planter
|
|
39
39
|
handle_operator(file)
|
40
40
|
end
|
41
41
|
rescue StandardError => e
|
42
|
-
Planter.notify("#{e}\n#{e.backtrace}", :debug)
|
42
|
+
Planter.notify("#{e}\n#{e.backtrace}", :debug, above_spinner: true)
|
43
43
|
Planter.notify('Error copying files/directories', :error, exit_code: 128)
|
44
44
|
end
|
45
45
|
|
@@ -141,7 +141,8 @@ module Planter
|
|
141
141
|
# If there are any merge sections left, merge them with the target file
|
142
142
|
if merges.count.positive?
|
143
143
|
File.open(entry.target, 'w') { |f| f.puts "#{target_content.chomp}\n\n#{merges.join("\n\n")}" }
|
144
|
-
Planter.notify("Merged #{entry.file} => #{entry.target} (#{merges.count} merges)", :debug
|
144
|
+
Planter.notify("[Merged] #{entry.file} => #{entry.target} (#{merges.count} merges)", :debug,
|
145
|
+
above_spinner: true)
|
145
146
|
else
|
146
147
|
# If there are no merge sections left, copy the file instead
|
147
148
|
copy_file(entry)
|
@@ -166,12 +167,12 @@ module Planter
|
|
166
167
|
# Copy the file if it isn't a directory
|
167
168
|
FileUtils.cp(file.file, file.target) unless File.directory?(file.file)
|
168
169
|
# Log a message to the console
|
169
|
-
Planter.notify("Copied #{file.file} => #{file.target}", :debug)
|
170
|
+
Planter.notify("[Copied] #{file.file} => #{file.target}", :debug, above_spinner: true)
|
170
171
|
# Return true to indicate success
|
171
172
|
true
|
172
173
|
else
|
173
174
|
# Log a message to the console
|
174
|
-
Planter.notify("Skipped #{file.file} => #{file.target}", :debug)
|
175
|
+
Planter.notify("[Skipped] #{file.file} => #{file.target}", :debug, above_spinner: true)
|
175
176
|
# Return false to indicate that the copy was skipped
|
176
177
|
false
|
177
178
|
end
|
data/lib/planter/hash.rb
CHANGED
@@ -3,6 +3,30 @@
|
|
3
3
|
module Planter
|
4
4
|
## Hash helpers
|
5
5
|
class ::Hash
|
6
|
+
## Turn all keys and values into string
|
7
|
+
##
|
8
|
+
## @return [Hash] copy of the hash where all its keys are strings
|
9
|
+
##
|
10
|
+
def stringify
|
11
|
+
each_with_object({}) do |(k, v), hsh|
|
12
|
+
hsh[k.to_s] = if v.is_a?(Hash) || v.is_a?(Array)
|
13
|
+
v.stringify
|
14
|
+
else
|
15
|
+
v.to_s
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
## Destructive version of #stringify
|
21
|
+
##
|
22
|
+
## @return [Hash] Hash with stringified keys and values
|
23
|
+
##
|
24
|
+
## @see #stringify
|
25
|
+
##
|
26
|
+
def stringify!
|
27
|
+
replace stringify
|
28
|
+
end
|
29
|
+
|
6
30
|
## Turn all keys into string
|
7
31
|
##
|
8
32
|
## @return [Hash] copy of the hash where all its keys are strings
|
data/lib/planter/plant.rb
CHANGED
@@ -45,7 +45,8 @@ module Planter
|
|
45
45
|
default: var[:default],
|
46
46
|
value: var[:value],
|
47
47
|
min: var[:min],
|
48
|
-
max: var[:max]
|
48
|
+
max: var[:max],
|
49
|
+
choices: var[:choices] || nil
|
49
50
|
)
|
50
51
|
answer = q.ask
|
51
52
|
if answer.nil?
|
@@ -158,8 +159,8 @@ module Planter
|
|
158
159
|
s.run
|
159
160
|
end
|
160
161
|
end
|
161
|
-
Planter.spinner.update(title: '
|
162
|
-
Planter.spinner.success
|
162
|
+
Planter.spinner.update(title: 'Planting complete!')
|
163
|
+
Planter.spinner.success
|
163
164
|
end
|
164
165
|
|
165
166
|
##
|
@@ -182,7 +183,8 @@ module Planter
|
|
182
183
|
next if File.binary?(file)
|
183
184
|
|
184
185
|
content = IO.read(file)
|
185
|
-
|
186
|
+
|
187
|
+
new_content = content.apply_logic.apply_variables.apply_regexes
|
186
188
|
|
187
189
|
new_content.gsub!(%r{^.{.4}/?merge *.{,4}\n}, '') if new_content =~ /^.{.4}merge *\n/
|
188
190
|
|
data/lib/planter/prompt.rb
CHANGED
@@ -23,6 +23,7 @@ module Planter
|
|
23
23
|
@prompt = question[:prompt] || nil
|
24
24
|
@default = question[:default]
|
25
25
|
@value = question[:value]
|
26
|
+
@choices = question[:choices] || []
|
26
27
|
@gum = false # TTY::Which.exist?('gum')
|
27
28
|
end
|
28
29
|
|
@@ -37,6 +38,8 @@ module Planter
|
|
37
38
|
return @value.to_s.apply_variables.apply_regexes.coerce(@type) if @value && @type != :date
|
38
39
|
|
39
40
|
res = case @type
|
41
|
+
when :choice
|
42
|
+
Prompt.choice(@choices, @prompt, default_response: @default)
|
40
43
|
when :integer
|
41
44
|
read_number(integer: true)
|
42
45
|
when :float
|
@@ -54,10 +57,10 @@ module Planter
|
|
54
57
|
else
|
55
58
|
read_line
|
56
59
|
end
|
57
|
-
Planter.notify("{dw}#{prompt}
|
60
|
+
Planter.notify("{dw}#{prompt} => {dy}#{res}{x}", :debug, newline: false)
|
58
61
|
res
|
59
62
|
rescue TTY::Reader::InputInterrupt
|
60
|
-
raise Errors::InputError('Canceled')
|
63
|
+
raise Errors::InputError.new('Canceled')
|
61
64
|
end
|
62
65
|
|
63
66
|
private
|
@@ -116,7 +119,7 @@ module Planter
|
|
116
119
|
default = date_default
|
117
120
|
|
118
121
|
default = default ? " {bw}[#{default}]" : ''
|
119
|
-
Planter.notify("{by}#{prompt} (natural language)#{default}")
|
122
|
+
Planter.notify("{by}#{prompt} (natural language)#{default}", newline: false)
|
120
123
|
line = @gum ? read_line_gum : read_line_tty
|
121
124
|
return default unless line
|
122
125
|
|
@@ -135,7 +138,7 @@ module Planter
|
|
135
138
|
def read_line(prompt: nil)
|
136
139
|
prompt ||= @prompt
|
137
140
|
default = @default ? " {bw}[#{@default}]" : ''
|
138
|
-
Planter.notify("{by}#{prompt}#{default}")
|
141
|
+
Planter.notify("{by}#{prompt}#{default}", newline: false)
|
139
142
|
|
140
143
|
res = @gum ? read_line_gum : read_line_tty
|
141
144
|
|
@@ -156,7 +159,7 @@ module Planter
|
|
156
159
|
def read_lines(prompt: nil)
|
157
160
|
prompt ||= @prompt
|
158
161
|
save = @gum ? 'Ctrl-J for newline, Enter' : 'Ctrl-D'
|
159
|
-
Planter.notify("{by}#{prompt} {xc}({bw}#{save}{xc} to save)'")
|
162
|
+
Planter.notify("{by}#{prompt} {xc}({bw}#{save}{xc} to save)'", newline: false)
|
160
163
|
res = @gum ? read_multiline_gum(prompt) : read_mutliline_tty
|
161
164
|
|
162
165
|
return @default unless res
|
@@ -238,18 +241,36 @@ module Planter
|
|
238
241
|
## @param default_response [String] The character of the default
|
239
242
|
## response
|
240
243
|
##
|
241
|
-
## @return [String]
|
244
|
+
## @return [String] string of selected response with parenthesis removed
|
242
245
|
##
|
243
246
|
def self.choice(choices, prompt = 'Make a selection', default_response: nil)
|
244
247
|
$stdin.reopen('/dev/tty')
|
245
248
|
|
246
|
-
|
249
|
+
choices = choices.choices_to_hash if choices.is_a?(Array) && choices.first.is_a?(Hash)
|
247
250
|
|
248
|
-
|
249
|
-
|
251
|
+
if choices.is_a?(Hash)
|
252
|
+
choices.stringify!
|
253
|
+
numeric = choices.keys.first =~ /^\(?\d+\.?\)? /
|
254
|
+
keys = choices.keys.to_options(numeric)
|
255
|
+
values = choices.values.map(&:clean_value)
|
256
|
+
choices = choices.keys
|
257
|
+
else
|
258
|
+
numeric = choices.first =~ /^\(?\d+\.?\)? /
|
259
|
+
keys = choices.to_options(numeric)
|
260
|
+
values = choices.to_values.map(&:clean_value)
|
261
|
+
end
|
250
262
|
|
251
|
-
|
252
|
-
|
263
|
+
default = case default_response.to_s
|
264
|
+
when /^\d+$/
|
265
|
+
values[default.to_i]
|
266
|
+
when /^[a-z]$/i
|
267
|
+
keys.include?(default_response) ? values[keys.index(default_response)] : nil
|
268
|
+
end
|
269
|
+
|
270
|
+
# If --defaults is set or not an interactive shell, return default
|
271
|
+
return default if Planter.accept_defaults || ENV['PLANTER_DEBUG'] || !$stdout.isatty
|
272
|
+
|
273
|
+
default = default_response.to_s if default_response
|
253
274
|
|
254
275
|
# clear the buffer
|
255
276
|
if ARGV&.length
|
@@ -259,9 +280,10 @@ module Planter
|
|
259
280
|
end
|
260
281
|
system 'stty cbreak'
|
261
282
|
|
262
|
-
vertical = choices.join(' ').length + 4 > TTY::Screen.cols
|
263
|
-
|
264
|
-
|
283
|
+
vertical = numeric || choices.join(', ').length + 4 > TTY::Screen.cols
|
284
|
+
|
285
|
+
desc = keys.map { |c| c.highlight_character(default: default) }
|
286
|
+
abbr = keys.abbr_choices(default: default)
|
265
287
|
|
266
288
|
options = if vertical
|
267
289
|
"{x}#{desc.join("\n")}\n{by}#{prompt}{x} #{abbr}{bw}? "
|
@@ -270,16 +292,34 @@ module Planter
|
|
270
292
|
end
|
271
293
|
|
272
294
|
$stdout.syswrite options.x
|
273
|
-
|
295
|
+
|
296
|
+
res = if numeric && choices.length > 9
|
297
|
+
$stdin.sysread choices.length.to_s.length
|
298
|
+
else
|
299
|
+
$stdin.sysread 1
|
300
|
+
end
|
301
|
+
|
274
302
|
puts
|
275
303
|
system 'stty cooked'
|
276
304
|
|
277
305
|
res.chomp!
|
278
306
|
res.downcase!
|
279
307
|
|
280
|
-
res.empty? ? default : res
|
308
|
+
res = res.empty? ? default : res
|
309
|
+
|
310
|
+
if res.to_i.positive?
|
311
|
+
values[res.to_i - 1]
|
312
|
+
elsif res =~ /^[a-z]/ && keys&.option_index(res)
|
313
|
+
values[keys.option_index(res)]
|
314
|
+
end
|
281
315
|
end
|
282
316
|
|
317
|
+
## Determine what to do with a file
|
318
|
+
##
|
319
|
+
## @param entry [FileEntry] The file entry
|
320
|
+
##
|
321
|
+
## @return [Symbol] :merge, :overwrite, :copy, :ignore
|
322
|
+
##
|
283
323
|
def self.file_what?(entry)
|
284
324
|
options = %w[(o)vewrite (m)erge]
|
285
325
|
options << '(c)opy' unless File.exist?(entry.target)
|