hsume2-aka 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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)`