cmdline-sub 0.1.1 → 0.1.2

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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README +11 -3
  3. data/Rakefile +1 -0
  4. data/bin/sub +65 -75
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2fd227736fa0bc8d59c84b1909f3c7abfd63ec86325a855ae5e4e2302693f35b
4
- data.tar.gz: 84c336782e6d58eddba82d06874809d22074c968fd94a82c61a88043d922bb52
3
+ metadata.gz: f8333cc1f6aa8e4eb3b47299c6038d0c04d26b9b0b8e4b2292e54906fc9e766d
4
+ data.tar.gz: 2b6fa1a2ef48f3ff9fec5aa017c7e4ef94e977085f424e64a4c9378822dc0a4b
5
5
  SHA512:
6
- metadata.gz: e1955cee9482f5b650924d6302185519553bc82dc9959b28449e57c5bb2f5527e2553eb18be60fe5a7f8cb9d752d5baf68709bab3448b66dfda3d196b2ad51e5
7
- data.tar.gz: 9435447e39679f02f4e2365faa2c01cd2b7e9fb3ca88388e5d894b913c6edf5885fde6a32504e85cd4da29d75a8c0395ae265dbdd3d5917265ca4fc3dd4116e8
6
+ metadata.gz: 3b162147e9a995230fdb3744963af0fa237ec96fe9f6088b561ce82de7a7a6d338096715dda296f2ad5c6060d2d3e826017aa346c283cb79662723884acd64c6
7
+ data.tar.gz: 2bb7d2a20e123d67ddb0ee09e8c2de7b7e0e46d6a39d31b3364df381b9f9481d15020df0096a0edc0b140b5a3d8ebae97926717f8cb2609fa5f7ea9861f40a41
data/README CHANGED
@@ -1,8 +1,8 @@
1
1
  Sub
2
2
  ===
3
3
 
4
- sub v0.1.0
5
- Usage: sub COMMANDLINE -- (PATTERN/SUBSTITUTION[/SUB_OPTIONS])+ (/GLOBAL_OPTIONS)?
4
+ sub v0.1.2
5
+ Usage: sub COMMANDLINE -- (PATTERN/SUBSTITUTION[/SUB_FLAGS])+ (/GLOBAL_FLAGS)?
6
6
 
7
7
  sub substitutes the matching pattern in every word in the command line with the
8
8
  substitution. Only the first matched pattern in the word is substituted unless
@@ -56,13 +56,19 @@ Substitution flags:
56
56
  -e: Expand * in commandline after replacements are made
57
57
  ex: sub ls mydir -- mydir/*/e #=> ls bin README
58
58
  Global flags:
59
- -p: Print the command instead of executing it
59
+ -p: Print the command instead of executing it (adds newline)
60
+ -P: Print the command instead of executing it (doesn't add newline)
60
61
  -c: Copy the command to clipboard instead of executing it
61
62
  -I: Set interactive mode: shows the command and asks if you want to execute it
62
63
  -v: Set verbose mode
63
64
  -D: Set debug mode
65
+ Other flags:
66
+ -h,--help: Show help (-h shows short help, --help shows full)
67
+ -v,--version: Show version followed by a newline
64
68
 
65
69
  Install:
70
+ gem install cmdline-sub
71
+ or:
66
72
  cd $HOME
67
73
  git clone git@github.com:luke-gru/sub.git
68
74
  cd sub
@@ -71,6 +77,8 @@ Install:
71
77
  # INSTALL_PREFIX="/bin" sudo rake install
72
78
 
73
79
  Uninstall:
80
+ gem uninstall cmdline-sub
81
+ or:
74
82
  cd $HOME/sub
75
83
  sudo rake uninstall # removes /usr/local/bin/sub
76
84
  # or
data/Rakefile CHANGED
@@ -57,6 +57,7 @@ end
57
57
 
58
58
  desc "Uninstall (removes /usr/local/bin/sub or $(INSTALL_PREFIX)/sub). Use sudo if necessary."
59
59
  task :uninstall do
60
+ require "fileutils"
60
61
  install_dir = ENV["INSTALL_PREFIX"] || "/usr/local/bin"
61
62
  unless File.directory?(install_dir)
62
63
  $stderr.puts "Directory #{install_dir} does not exist. Uninstall failed."
data/bin/sub CHANGED
@@ -2,10 +2,14 @@
2
2
  # vim: set ft=ruby
3
3
  # frozen_string_literal: true
4
4
 
5
- VERSION = "0.1.1"
5
+ if ENV["TESTING_SUB_CMD"] == "1" && ENV["DEBUGGING_SUB_CMD"] == "1"
6
+ require "debug"
7
+ end
8
+
9
+ VERSION = "0.1.2"
6
10
 
7
11
  USAGE = <<EOF
8
- Usage: sub COMMANDLINE -- (PATTERN/SUBSTITUTION[/SUB_OPTIONS])+ (/GLOBAL_OPTIONS)?
12
+ Usage: sub COMMANDLINE -- (PATTERN/SUBSTITUTION[/SUB_FLAGS])+ (/GLOBAL_FLAGS)?
9
13
 
10
14
  sub substitutes the matching pattern in every word in the command line with the
11
15
  substitution. Only the first matched pattern in the word is substituted unless
@@ -46,6 +50,8 @@ EOF
46
50
 
47
51
  INSTALLATION = <<EOF
48
52
  Install:
53
+ \t gem install cmdline-sub
54
+ or:
49
55
  \tcd $HOME
50
56
  \tgit clone git@github.com:luke-gru/sub.git
51
57
  \tcd sub
@@ -56,6 +62,8 @@ EOF
56
62
 
57
63
  UNINSTALLATION = <<EOF
58
64
  Uninstall:
65
+ \t gem uninstall cmdline-sub
66
+ or:
59
67
  \tcd $HOME/sub
60
68
  \tsudo rake uninstall # removes /usr/local/bin/sub
61
69
  \t# or
@@ -64,7 +72,7 @@ EOF
64
72
 
65
73
  LICENSE = "License: MIT"
66
74
 
67
- FLAGS = [
75
+ SUB_FLAGS = [
68
76
  # per substitution flags
69
77
  { flag: 'f', name: :first_match, desc: "Substitute first matching word only.",
70
78
  example: "sub wget https://wget.com -- wget/curl/f #=> curl https://wget.com",
@@ -84,7 +92,8 @@ FLAGS = [
84
92
  { flag: 'e', name: :expand_star, desc: "Expand * in commandline after replacements are made",
85
93
  example: [ "sub ls mydir -- mydir/*/e #=> ls bin README" ]
86
94
  },
87
- nil, # separator
95
+ ]
96
+ GLOBAL_FLAGS = [
88
97
  # global flags
89
98
  { flag: 'p', name: :print_only, desc: "Print the command instead of executing it (adds newline)" },
90
99
  { flag: 'P', name: :print_only_no_newline, desc: "Print the command instead of executing it (doesn't add newline)" },
@@ -93,28 +102,26 @@ FLAGS = [
93
102
  { flag: 'v', name: :verbose, desc: "Set verbose mode" },
94
103
  { flag: 'D', name: :debug, desc: "Set debug mode" },
95
104
  ]
96
- GLOBAL_FLAGS_MAP = {
97
- print_only: 'p',
98
- print_only_no_newline: 'P',
99
- copy_to_clipboard: 'c',
100
- interactive: 'I',
101
- verbose: 'v',
102
- debug: 'D',
103
- }
104
- GLOBAL_FLAGS = GLOBAL_FLAGS_MAP.values
105
+ OTHER_FLAGS = [
106
+ { flag: ['h', '--help'], name: :help, desc: "Show help (-h shows short help, --help shows full)", },
107
+ { flag: ['v', '--version'], name: :version, desc: "Show version followed by a newline" },
108
+ ]
109
+ FLAGS = SUB_FLAGS + GLOBAL_FLAGS + OTHER_FLAGS
110
+ FLAGS_BY_NAME = FLAGS.map do |f|
111
+ { f[:name] => f[:flag] }
112
+ end.inject(Hash.new) { |memo, h| memo.merge(h) }
113
+ GLOBAL_FLAGS_BY_NAME = GLOBAL_FLAGS.map do |f|
114
+ { f[:name] => f[:flag] }
115
+ end.inject(Hash.new) { |memo, h| memo.merge(h) }
116
+ RAW_GLOBAL_FLAGS = GLOBAL_FLAGS_BY_NAME.values
105
117
 
106
118
  def print_help(full: true)
107
119
  output = String.new
108
120
  output << "sub v#{VERSION}" << "\n"
109
121
  output << USAGE << "\n"
110
- output << "Flags:\n\n"
111
- output << "Substitution flags:\n"
112
- FLAGS.each do |fhash|
113
- if fhash.nil?
114
- output << "Global flags:\n"
115
- next
116
- end
117
- output << "-#{fhash[:flag]}:\t#{fhash[:desc]}\n"
122
+ output_flag_info = lambda do |fhash|
123
+ flags = Array(fhash[:flag])
124
+ output << "-#{flags.join(',')}:\t#{fhash[:desc]}\n"
118
125
  if ex = fhash[:example]
119
126
  case ex
120
127
  when String
@@ -126,6 +133,13 @@ def print_help(full: true)
126
133
  end
127
134
  end
128
135
  end
136
+ output << "Flags:\n\n"
137
+ output << "Substitution flags:\n"
138
+ SUB_FLAGS.each(&output_flag_info)
139
+ output << "Global flags:\n"
140
+ GLOBAL_FLAGS.each(&output_flag_info)
141
+ output << "Other flags:\n"
142
+ OTHER_FLAGS.each(&output_flag_info)
129
143
  if full
130
144
  output << "\n" << INSTALLATION
131
145
  output << "\n" << UNINSTALLATION
@@ -142,11 +156,8 @@ def parse_argv_and_sub_strs(argv)
142
156
  ret_argv = []
143
157
  sub_strs = []
144
158
  if argv.size == 0
145
- require "readline"
146
- line = Readline.readline "cmd: ", true
147
- ret_argv.replace line.strip.split(/\s+/)
148
- line = Readline.readline "pat/sub[/options]: ", true
149
- sub_strs << line.strip
159
+ print_help(full: true)
160
+ exit 1
150
161
  else
151
162
  last_dashdash_idx = argv.rindex('--')
152
163
  argv.each_with_index do |arg, i|
@@ -178,26 +189,28 @@ end
178
189
 
179
190
  argv, sub_strs = parse_argv_and_sub_strs(ARGV)
180
191
 
181
- def flag(flags_str, char)
192
+ def parse_simple_flag!(flags_str, char)
182
193
  flag = flags_str.include?(char)
183
194
  flags_str.delete!(char)
184
195
  flag
185
196
  end
186
197
 
187
198
  def flag_by_name(name)
188
- FLAGS.each do |fhash|
189
- next if fhash.nil?
190
- if fhash[:name] == name
191
- return fhash[:flag]
192
- end
193
- end
194
- raise ArgumentError, "bad flag: #{name}"
199
+ FLAGS_BY_NAME.fetch(name)
195
200
  end
196
201
 
197
- def raw_global_options?(raw_flags)
202
+ def raw_global_flags?(raw_flags)
198
203
  raw_flags = raw_flags.strip
199
204
  return false if raw_flags.empty?
200
- raw_flags.gsub(Regexp.new(GLOBAL_FLAGS.join('|')), '').empty?
205
+ raw_flags.gsub(Regexp.new(RAW_GLOBAL_FLAGS.join('|')), '').empty?
206
+ end
207
+
208
+ def parse_global_flag!(name, flags, global_flags)
209
+ if global_flags[name]
210
+ flags.delete!(GLOBAL_FLAGS_BY_NAME[name])
211
+ else
212
+ global_flags[name] = parse_simple_flag!(flags, flag_by_name(name))
213
+ end
201
214
  end
202
215
 
203
216
  def parse_sub_strs(sub_strs)
@@ -205,11 +218,11 @@ def parse_sub_strs(sub_strs)
205
218
  pats = []
206
219
  subs = []
207
220
  match_flags = []
208
- global_flags = GLOBAL_FLAGS_MAP.transform_values { nil }
221
+ global_flags = GLOBAL_FLAGS_BY_NAME.transform_values { nil }
209
222
  raw_flags = []
210
223
  sub_strs.each_with_index do |sub_str, sub_i|
211
224
  # global flags at end of substitutions list, starts with /, ex: /o
212
- if sub_strs[sub_i+1].nil? && sub_str[0] == '/' && raw_global_options?(sub_str[1..-1])
225
+ if sub_strs[sub_i+1].nil? && sub_str[0] == '/' && raw_global_flags?(sub_str[1..-1])
213
226
  flags = sub_str[1..-1]
214
227
  else
215
228
  pat, sub, flags = sub_str.split(/(?<!\\)\//)
@@ -219,48 +232,24 @@ def parse_sub_strs(sub_strs)
219
232
  flags.strip!
220
233
  raw_flags << flags.dup
221
234
  flags_hash = {
222
- first_match: flag(flags, flag_by_name(:first_match)),
223
- last_match: flag(flags, flag_by_name(:last_match)),
224
- expand_star: flag(flags, flag_by_name(:expand_star)),
225
- literal: flag(flags, flag_by_name(:literal)),
226
- ignorecase: flag(flags, flag_by_name(:ignorecase)),
227
- general: flag(flags, flag_by_name(:general)),
235
+ first_match: parse_simple_flag!(flags, flag_by_name(:first_match)),
236
+ last_match: parse_simple_flag!(flags, flag_by_name(:last_match)),
237
+ expand_star: parse_simple_flag!(flags, flag_by_name(:expand_star)),
238
+ literal: parse_simple_flag!(flags, flag_by_name(:literal)),
239
+ ignorecase: parse_simple_flag!(flags, flag_by_name(:ignorecase)),
240
+ general: parse_simple_flag!(flags, flag_by_name(:general)),
228
241
  }
229
242
  pats << pat
230
243
  subs << sub
231
244
  match_flags << flags_hash
232
245
  end
233
246
 
234
- if global_flags[:interactive]
235
- flags.delete!(GLOBAL_FLAGS_MAP[:interactive])
236
- else
237
- global_flags[:interactive] = flag(flags, flag_by_name(:interactive)) || ARGV.size == 0
238
- end
239
- if global_flags[:print_only]
240
- flags.delete!(GLOBAL_FLAGS_MAP[:print_only])
241
- else
242
- global_flags[:print_only] = flag(flags, flag_by_name(:print_only))
243
- end
244
- if global_flags[:print_only_no_newline]
245
- flags.delete!(GLOBAL_FLAGS_MAP[:print_only_no_newline])
246
- else
247
- global_flags[:print_only_no_newline] = flag(flags, flag_by_name(:print_only_no_newline))
248
- end
249
- if global_flags[:copy_to_clipboard]
250
- flags.delete!(GLOBAL_FLAGS_MAP[:copy_to_clipboard])
251
- else
252
- global_flags[:copy_to_clipboard] = flag(flags, flag_by_name(:copy_to_clipboard))
253
- end
254
- if global_flags[:verbose]
255
- flags.delete!(GLOBAL_FLAGS_MAP[:verbose])
256
- else
257
- global_flags[:verbose] = flag(flags, flag_by_name(:verbose))
258
- end
259
- if global_flags[:debug]
260
- flags.delete!(GLOBAL_FLAGS_MAP[:debug])
261
- else
262
- global_flags[:debug] = flag(flags, flag_by_name(:debug))
263
- end
247
+ parse_global_flag!(:interactive, flags, global_flags)
248
+ parse_global_flag!(:print_only, flags, global_flags)
249
+ parse_global_flag!(:print_only_no_newline, flags, global_flags)
250
+ parse_global_flag!(:copy_to_clipboard, flags, global_flags)
251
+ parse_global_flag!(:verbose, flags, global_flags)
252
+ parse_global_flag!(:debug, flags, global_flags)
264
253
  unless flags.empty?
265
254
  $stderr.puts "Warning: unknown flag#{'s' if flags.size != 1}: #{flags}"
266
255
  end
@@ -272,7 +261,7 @@ end
272
261
  pats, subs, flags_hashes, raw_flags, global_flags = parse_sub_strs(sub_strs)
273
262
 
274
263
  if pats.empty? && flags_hashes.empty? && global_flags.empty?
275
- $stderr.puts "Incorrect substitution, format is: pattern/substitution[/options]"
264
+ $stderr.puts "Incorrect substitution, format is: pattern/substitution[/flags]"
276
265
  exit 1
277
266
  end
278
267
 
@@ -398,6 +387,7 @@ def exec_cmd(argv, regexps, subs, raw_flags, num_replacements, global_flags)
398
387
  if global_flags.fetch(:interactive) && !global_flags.fetch(:print_only)
399
388
  $stdout.puts "Would you like to #{action} the following command? [y(es),n(o)]"
400
389
  $stdout.puts cmd_line
390
+ $stdout.flush
401
391
  ans = $stdin.gets().strip
402
392
  if ans !~ /y(es)?/i # treat as no
403
393
  exit 1
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cmdline-sub
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luke Gruber
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-20 00:00:00.000000000 Z
11
+ date: 2024-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: debug