hsume2-aka 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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +8 -0
  6. data/Guardfile +9 -0
  7. data/LICENSE.txt +7 -0
  8. data/README.md +91 -0
  9. data/Rakefile +98 -0
  10. data/aka.gemspec +28 -0
  11. data/bin/aka +5 -0
  12. data/features/aka/add.feature +183 -0
  13. data/features/aka/edit.feature +91 -0
  14. data/features/aka/generate.feature +117 -0
  15. data/features/aka/help.feature +80 -0
  16. data/features/aka/list.feature +62 -0
  17. data/features/aka/remove.feature +48 -0
  18. data/features/aka/show.feature +38 -0
  19. data/features/step_definitions/aka_steps.rb +3 -0
  20. data/features/support/env.rb +80 -0
  21. data/lib/aka/app.rb +66 -0
  22. data/lib/aka/man/aka-add.1 +34 -0
  23. data/lib/aka/man/aka-add.1.txt +31 -0
  24. data/lib/aka/man/aka-edit.1 +96 -0
  25. data/lib/aka/man/aka-edit.1.txt +75 -0
  26. data/lib/aka/man/aka-generate.1 +81 -0
  27. data/lib/aka/man/aka-generate.1.txt +70 -0
  28. data/lib/aka/man/aka-list.1 +71 -0
  29. data/lib/aka/man/aka-list.1.txt +63 -0
  30. data/lib/aka/man/aka-remove.1 +30 -0
  31. data/lib/aka/man/aka-remove.1.txt +29 -0
  32. data/lib/aka/man/aka-show.1 +33 -0
  33. data/lib/aka/man/aka-show.1.txt +31 -0
  34. data/lib/aka/man/aka.7 +169 -0
  35. data/lib/aka/man/aka.7.txt +121 -0
  36. data/lib/aka/store.rb +372 -0
  37. data/lib/aka/version.rb +3 -0
  38. data/lib/aka.rb +6 -0
  39. data/man/aka-add.1.ronn +32 -0
  40. data/man/aka-edit.1.ronn +67 -0
  41. data/man/aka-generate.1.ronn +51 -0
  42. data/man/aka-list.1.ronn +51 -0
  43. data/man/aka-remove.1.ronn +21 -0
  44. data/man/aka-show.1.ronn +27 -0
  45. data/man/aka.7.ronn +85 -0
  46. data/test/tc_something.rb +7 -0
  47. metadata +184 -0
data/lib/aka/store.rb ADDED
@@ -0,0 +1,372 @@
1
+ require 'yaml'
2
+ require 'ostruct'
3
+ require 'tempfile'
4
+ require 'methadone'
5
+
6
+ module Aka
7
+ class Store
8
+ include Methadone::CLILogging
9
+
10
+ def help(command, options)
11
+ case command
12
+ when nil then command = "aka.7"
13
+ else command = "aka-#{command}.1"
14
+ end
15
+
16
+ manpages = %w(
17
+ aka-add.1
18
+ aka-edit.1
19
+ aka-generate.1
20
+ aka-list.1
21
+ aka-remove.1
22
+ aka-show.1
23
+ aka.7)
24
+
25
+ exit unless manpages.include?(command)
26
+
27
+ root = File.expand_path("../man", __FILE__)
28
+
29
+ if !ENV['NO_MAN'] && Aka::App.which("man") && root !~ %r{^file:/.+!/META-INF/jruby.home/.+}
30
+ Kernel.exec "man #{root}/#{command}"
31
+ else
32
+ puts File.read("#{root}/#{command}.txt")
33
+ exit
34
+ end
35
+ end
36
+
37
+ def add(options)
38
+ found = find(options)
39
+
40
+ if found.length > 0
41
+ unless options[:force]
42
+ abort %{Shortcut "#{options[:shortcut]}" exists. Pass --force to overwrite. Or provide a new --tag.}
43
+ else
44
+ found.each do |n, row|
45
+ replace(n, options)
46
+ end
47
+ save
48
+ puts "Overwrote shortcut."
49
+ end
50
+ else
51
+ append(options)
52
+ save
53
+ puts "Created shortcut."
54
+ end
55
+ end
56
+
57
+ def list(options)
58
+ excluded = match_shortcuts_by_tag(options[:tag] || []) do |tag, rows|
59
+ puts %{##{tag}}
60
+ puts ''.ljust(tag.length + 1, '=')
61
+ rows.each do |row|
62
+ list_output(row)
63
+ end
64
+ puts
65
+ end
66
+
67
+ excluded_output(excluded)
68
+ end
69
+
70
+ def remove(options)
71
+ found = find(options)
72
+
73
+ if found.length > 0
74
+ found.each do |n, row|
75
+ delete(n)
76
+ end
77
+
78
+ save
79
+
80
+ puts "Removed shortcut."
81
+ else
82
+ abort %{No shortcut "#{options[:shortcut]}". Aborting.}
83
+ end
84
+ end
85
+
86
+ def matches_tag?(row, tag)
87
+ return true unless row.tag
88
+
89
+ if tag =~ /^~(.+)/
90
+ !row.tag.include?($1)
91
+ else
92
+ row.tag && row.tag.include?(tag)
93
+ end
94
+ end
95
+
96
+ def generate(options)
97
+ scripts = []
98
+ functions = []
99
+
100
+ excluded = match_shortcuts_by_tag(options[:tag] || []) do |tag, rows|
101
+ rows.each do |row|
102
+ unless row.function
103
+ scripts << generate_output(row)
104
+ else
105
+ functions << generate_output(row)
106
+ end
107
+ end
108
+ end
109
+
110
+ if options[:output]
111
+ File.open(options[:output], 'w+') do |f|
112
+ scripts.each do |script|
113
+ f.puts script
114
+ end
115
+
116
+ functions.each do |function|
117
+ f.puts function
118
+ end
119
+ end
120
+
121
+ puts "Generated #{options[:output]}."
122
+ else
123
+ scripts.each do |script|
124
+ puts script
125
+ end
126
+
127
+ functions.each do |function|
128
+ puts function
129
+ end
130
+ end
131
+
132
+ excluded_output(excluded)
133
+ end
134
+
135
+ def edit(options)
136
+ result = nil
137
+
138
+ found = find(options)
139
+
140
+ index, row = found.first
141
+
142
+ unless row
143
+ abort "Shortcut not found."
144
+ end
145
+
146
+ if options[:input]
147
+ result = File.read(options[:input])
148
+ else
149
+ file = Tempfile.new('shortcut')
150
+ begin
151
+ file.open
152
+ if row.tag
153
+ tags = %{ #{row.tag.join(', ')}}
154
+ else
155
+ tags = ''
156
+ end
157
+ file.write(<<-EOS.gsub(/^ /, '')
158
+ Keyword: #{row.shortcut}
159
+ Description:
160
+ #{row.description}
161
+ Function (y/n): #{row.function ? 'y' : 'n'}
162
+ Tags:#{tags}
163
+ Command:
164
+ #{row.command}
165
+ EOS
166
+ )
167
+ file.close
168
+ editor = ENV['EDITOR'] || 'vim'
169
+ system(%[#{editor} #{file.path}])
170
+ debug("Editing exited with code: #{$?.exitstatus}.")
171
+ if $?.exitstatus == 0
172
+ file.open
173
+ file.rewind
174
+ result = file.read.strip
175
+ end
176
+ ensure
177
+ file.unlink
178
+ end
179
+ end
180
+
181
+ if result
182
+ parse_row_txt(row, result)
183
+ shortcuts[index] = row
184
+ save
185
+ puts "Saved shortcut."
186
+ else
187
+ end
188
+ end
189
+
190
+ def show(options)
191
+ found = find(options)
192
+
193
+ _, row = found.first
194
+
195
+ if row
196
+ puts show_output(row)
197
+ else
198
+ abort "Shortcut not found."
199
+ end
200
+ end
201
+
202
+ private
203
+
204
+ def shortcuts
205
+ @shortcuts ||= begin
206
+ if File.exist?(aka_yml)
207
+ YAML::load_file(aka_yml)
208
+ else
209
+ {}
210
+ end
211
+ end
212
+ end
213
+
214
+ def find(options)
215
+ if options[:tag]
216
+ shortcuts.select do |_, row|
217
+ next unless row.shortcut == options[:shortcut]
218
+
219
+ options[:tag].find do |tag|
220
+ row.tag && row.tag.include?(tag)
221
+ end
222
+ end
223
+ else
224
+ shortcuts.select do |_, row|
225
+ row.shortcut == options[:shortcut]
226
+ end
227
+ end
228
+ end
229
+
230
+ def append(options)
231
+ shortcuts[count + 1] = row(options)
232
+ end
233
+
234
+ def replace(index, options)
235
+ shortcuts[index] = row(options)
236
+ end
237
+
238
+ def delete(index)
239
+ shortcuts.delete(index)
240
+ end
241
+
242
+ def count
243
+ result, _ = shortcuts.max { |(n, _)| n }
244
+ result || 0
245
+ end
246
+
247
+ def row(options)
248
+ OpenStruct.new.tap do |row|
249
+ row.shortcut = options['shortcut']
250
+ row.command = options['command']
251
+ row.tag = options['tag'] if options['tag']
252
+ row.description = options['description'] if options['description']
253
+ row.function = options['function'] if options['function']
254
+ end
255
+ end
256
+
257
+ def save
258
+ File.open(aka_yml, 'w+') do |f|
259
+ f.write shortcuts.to_yaml
260
+ end
261
+ end
262
+
263
+ def aka_yml
264
+ ENV['AKA'] || File.expand_path('~/.aka.yml')
265
+ end
266
+
267
+ def shortcuts_by_tag
268
+ shortcuts.inject({ :default => [] }) do |acc, (_, row)|
269
+ if row.tag
270
+ row.tag.each do |tag|
271
+ acc[tag] ||= []
272
+ acc[tag] << row
273
+ end
274
+ else
275
+ acc[:default] << row
276
+ end
277
+ acc
278
+ end
279
+ end
280
+
281
+ def match_shortcuts_by_tag(tags, &blk)
282
+ excluded = { :tags => [], :shortcuts => 0 }
283
+
284
+ shortcuts_by_tag.each do |tag, rows|
285
+ next if rows.empty?
286
+ unless tag == :default || tags.empty? || tags.include?(tag)
287
+ excluded[:tags] << tag
288
+ excluded[:shortcuts] += rows.length
289
+ next
290
+ end
291
+
292
+ yield(tag, rows)
293
+ end
294
+
295
+ excluded
296
+ end
297
+
298
+ def excluded_output(excluded)
299
+ return if excluded[:tags].empty?
300
+
301
+ tags = excluded[:tags].map { |t| '#' + t }.join(', ')
302
+ $stderr.puts "#{excluded[:shortcuts]} shortcut(s) excluded (#{tags})."
303
+ end
304
+
305
+ def list_output(row)
306
+ if row.function
307
+ description = row.description || row.command
308
+ else
309
+ description = row.command
310
+ end
311
+
312
+ if description
313
+ description = description.split("\n").map(&:strip).join("; ")
314
+
315
+ if description.length > 70
316
+ description = description[0...66] + ' ...'
317
+ end
318
+ end
319
+
320
+ puts "#{row.shortcut.ljust(20)} #{description.ljust(70).strip}"
321
+ end
322
+
323
+ def generate_output(row)
324
+ string = if row.function
325
+ <<-EOS.gsub(/^ /, '')
326
+ function #{row.shortcut} {
327
+ #{row.command}
328
+ }
329
+ EOS
330
+ else
331
+ %{alias #{row.shortcut}="#{row.command.gsub(%{"}, %{\\"})}"}
332
+ end
333
+
334
+ string
335
+ end
336
+
337
+ def parse_row_txt(row, txt)
338
+ if txt =~ /^Shortcut:(.+)$/
339
+ row.shortcut = $1.strip
340
+ end
341
+ if txt =~ %r{^Description:(.+)\nFunction \(y/n\)}m
342
+ row.description = $1.strip if $1.strip.length > 0
343
+ end
344
+ if txt =~ %r{^Function \(y/n\):\s*(y|n)}m
345
+ row.function = ($1.strip == 'y')
346
+ end
347
+ if txt =~ /^Tags:(.+)$/
348
+ row.tag = $1.strip.split(',').map(&:strip)
349
+ end
350
+ if txt =~ /^Command:(.+)$/m
351
+ row.command = $1.strip
352
+ end
353
+ end
354
+
355
+ def show_output(row)
356
+ if row.tag
357
+ tags = %{ #{row.tag.map { |t| "##{t}"}.join(', ')}}
358
+ else
359
+ tags = ''
360
+ end
361
+ <<-EOS.gsub(/^ /, '')
362
+ Shortcut: #{row.shortcut}
363
+ Description:
364
+ #{row.description}
365
+ Function: #{row.function ? 'y' : 'n'}
366
+ Tags:#{tags}
367
+ Command:
368
+ #{row.command}
369
+ EOS
370
+ end
371
+ end
372
+ end
@@ -0,0 +1,3 @@
1
+ module Aka
2
+ VERSION = "0.1.0"
3
+ end
data/lib/aka.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "aka/store"
2
+ require "aka/version"
3
+ require "aka/app"
4
+
5
+ module Aka
6
+ end
@@ -0,0 +1,32 @@
1
+ aka-add(1) -- Add keyboard shortcuts
2
+ ====================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `aka add` <shortcut> <command>
7
+ [`-d` <description>]
8
+ [`-t` <tag1>[,<tag2>...]]
9
+ [`-F`]
10
+ [`-f`]
11
+
12
+ ## DESCRIPTION
13
+
14
+ This command adds a keyboard shortcut to `aka(7)`.
15
+
16
+ ## OPTIONS
17
+
18
+ * `-d <description>`:
19
+ Provide a description for the shortcut.
20
+
21
+ * `-t` <tag1>[,<tag2>...]:
22
+ A comma-separated list of tags for the shortcut.
23
+
24
+ * `-F`:
25
+ Create the shortcut as a shell function.
26
+
27
+ * `-f`:
28
+ Ovewrite an existing shortcut if a shortcut exists with the same <shortcut>.
29
+
30
+ ## SEE ALSO
31
+
32
+ `aka(7)`, `aka-show(1)`
@@ -0,0 +1,67 @@
1
+ aka-edit(1) -- Edit keyboard shortcuts
2
+ ======================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `aka edit` <shortcut>
7
+ [`-i` input]
8
+
9
+ ## DESCRIPTION
10
+
11
+ This command edits a keyboard shortcut in `aka(7)`.
12
+
13
+ The command can be performed interactively or via an input file.
14
+
15
+ ## OPTIONS
16
+
17
+ * `-i <input>`:
18
+ Update the shortcut with an input file. See the "FORMAT" section for more details.
19
+
20
+ ## FORMAT
21
+
22
+ The format should include the following sections (in order):
23
+
24
+ * `Shortcut: <shortcut>`<br>
25
+ Where <shortcut> is the string to change the <shortcut> cut.
26
+
27
+ * `Description: <description>`<br>
28
+ Where <description> is one or more lines of text.
29
+
30
+ * `Function (y/n): <y|n>`<br>
31
+ Where <y|n> is either `y` or `n`.
32
+
33
+ * `Tags: <tags>`<br>
34
+ Where <tags> is a comma-separated list of tags for the shortcut.
35
+
36
+ * `Command: <command>`<br>
37
+ Where <command> is one or more lines of text.
38
+
39
+ ## INTERACTIVE MODE
40
+
41
+ When the command enters the interactive mode, it shows the <shortcut> in the expected `FORMAT` in an interactive editor.
42
+
43
+ ## EXAMPLES
44
+
45
+ Edit a shortcut where `input.txt` is:
46
+
47
+ Shortcut: lsf
48
+ Description:
49
+ 1
50
+ 2
51
+ 3
52
+ Function (y/n): y
53
+ Tags: zsh, bash
54
+ Command:
55
+ ls -F
56
+
57
+ $ aka edit lsf -i input.txt
58
+ Saved shortcut.
59
+
60
+ ## ENVIRONMENT
61
+
62
+ * `EDITOR`:<br>
63
+ The editor **aka** will use in interactive mode. Default: vim
64
+
65
+ ## SEE ALSO
66
+
67
+ `aka(7)`, `aka-show(1)`
@@ -0,0 +1,51 @@
1
+ aka-generate(1) -- Generate commands for loading keyboard shortcuts into your shell
2
+ ===================================================================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `aka generate` [`-t` <tag1>[,<tag2>...]]
7
+ [`-o` <output>]
8
+
9
+ ## DESCRIPTION
10
+
11
+ This command generates commands for loading keyboard shortcuts in `aka(7)` into your shell.
12
+
13
+ This command can be performed with or without tag filtering.
14
+
15
+ By default, the commands are generated to `STDOUT`.
16
+
17
+ ## OPTIONS
18
+
19
+ * `-t` <tag1>[,<tag2>...]:
20
+ A comma-separated list of tags to filter with. Shortcuts tagged with <tag1>[,<tag2>...] will be included. Shortcuts tagged with other tags are excluded. Shortcuts with no tags are always included.
21
+
22
+ * `-o <output>`:
23
+ The location to generate the commands to.
24
+
25
+ ## EXAMPLES
26
+
27
+ Generate for all shortcuts:
28
+
29
+ $ aka generate
30
+ alias ..="cd .."
31
+ alias ls="ls -FG"
32
+ function ls {
33
+ ls -F --color=auto
34
+ }
35
+
36
+ Generate for shortcuts matching `--tag os:darwin`:
37
+
38
+ $ aka generate -t os:darwin
39
+ alias ..="cd .."
40
+ alias ls="ls -FG"
41
+
42
+ 2 shortcut(s) excluded (#os:linux, #os:windows).
43
+
44
+ Generate to file:
45
+
46
+ $ aka generate -o ~/.aka.zsh
47
+ Generated ~/.aka.zsh.
48
+
49
+ ## SEE ALSO
50
+
51
+ `aka(7)`, `aka-show(1)`
@@ -0,0 +1,51 @@
1
+ aka-list(1) -- List keyboard shortcuts
2
+ ======================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `aka list` [`-t` <tag1>[,<tag2>...]]
7
+
8
+ ## DESCRIPTION
9
+
10
+ This command lists keyboard shortcuts in `aka(7)`.
11
+
12
+ This command can be performed with or without tag filtering.
13
+
14
+ ## OPTIONS
15
+
16
+ * `-t` <tag1>[,<tag2>...]:
17
+ A comma-separated list of tags to filter with. Shortcuts tagged with <tag1>[,<tag2>...] will be included. Shortcuts tagged with other tags are excluded. Shortcuts with no tags are always included.
18
+
19
+ ## EXAMPLES
20
+
21
+ List all shortcuts:
22
+
23
+ $ aka list
24
+ #default
25
+ ========
26
+ .. cd ..
27
+
28
+ #os:linux
29
+ =========
30
+ ls ls; ls; ls
31
+
32
+ #os:darwin
33
+ ==========
34
+ ls ls -FG
35
+
36
+ List shortcuts matching `--tag os:darwin`:
37
+
38
+ $ aka list -t os:darwin
39
+ #default
40
+ ========
41
+ .. cd ..
42
+
43
+ #os:darwin
44
+ ==========
45
+ ls ls -FG
46
+
47
+ 2 shortcut(s) excluded (#os:linux, #os:windows).
48
+
49
+ ## SEE ALSO
50
+
51
+ `aka(7)`, `aka-show(1)`
@@ -0,0 +1,21 @@
1
+ aka-remove(1) -- Remove keyboard shortcuts
2
+ ==========================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `aka remove` <shortcut>
7
+
8
+ ## DESCRIPTION
9
+
10
+ This command removes a keyboard shortcut from `aka(7)`.
11
+
12
+ ## EXAMPLES
13
+
14
+ Remove a shortcut:
15
+
16
+ $ aka remove ls
17
+ Removed shortcut.
18
+
19
+ ## SEE ALSO
20
+
21
+ `aka(7)`, `aka-show(1)`
@@ -0,0 +1,27 @@
1
+ aka-show(1) -- Show keyboard shortcuts
2
+ =====================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `aka show` <shortcut>
7
+
8
+ ## DESCRIPTION
9
+
10
+ This command show a keyboard shortcut in `aka(7)`.
11
+
12
+ ## EXAMPLES
13
+
14
+ $ aka add psf "ps aux | grep $@" --function
15
+ Created shortcut.
16
+ $ aka show psf
17
+ Keyword: psf
18
+ Description:
19
+
20
+ Function: y
21
+ Tags:
22
+ Script:
23
+ ps aux | grep $@
24
+
25
+ ## SEE ALSO
26
+
27
+ `aka(7)`, `aka-add(1)`