cmdline-fu 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 (8) hide show
  1. data/LICENSE.txt +20 -0
  2. data/Manifest +6 -0
  3. data/README.md +49 -0
  4. data/Rakefile +14 -0
  5. data/VERSION +1 -0
  6. data/bin/cmdline-fu +267 -0
  7. data/cmdline-fu.gemspec +37 -0
  8. metadata +110 -0
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 t9md
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,6 @@
1
+ LICENSE.txt
2
+ Manifest
3
+ README.md
4
+ Rakefile
5
+ VERSION
6
+ bin/cmdline-fu
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ cmdline-fu
2
+ ====================
3
+ CLI based front end for [ commandlinefu ]( http://www.commandlinefu.com/ ).
4
+ commandlinefu is community based repository for usefull commandline such as one-liner or complex `find`, `openssl`, `mysql`... command.
5
+
6
+ This script scrape available TAG from site's top page with `hpricot` for supporting query based on TAG.
7
+ TAGS file are stored to `~/.fu_tags`.
8
+
9
+ `o` option depends on `open` command of OSX(means supported only on MacOS).
10
+
11
+ ## Install:
12
+
13
+ gem install cmdline-fu
14
+
15
+ ## Usage
16
+
17
+ cmdline-fu COMMAND [PAGE] [o]
18
+
19
+ COMMAND: list_tag [MATCHER], browse, using WORD, by USER, tagged TAG, matching WORD
20
+ PAGE: 1-999 (defaut: 1)
21
+ o: 'o'pen in browser
22
+
23
+ ## Example
24
+
25
+ cmdline-fu list_tag
26
+ cmdline-fu list_tag vm
27
+ cmdline-fu browse
28
+ cmdline-fu browse o
29
+ cmdline-fu using find
30
+ cmdline-fu by t9md
31
+ cmdline-fu tagged install
32
+ cmdline-fu matching find
33
+
34
+ ## Abbreviation
35
+ Unique abbreviation for command is supported.
36
+
37
+ cmdline-fu l
38
+ cmdline-fu l vm
39
+ cmdline-fu br
40
+ cmdline-fu u find 2
41
+ cmdline-fu u find 2 o
42
+ cmdline-fu by t9md
43
+ cmdline-fu t install
44
+ cmdline-fu m find
45
+
46
+ Copyright
47
+ ====================
48
+ Copyright (c) 2010 t9md. See LICENSE.txt for
49
+ further details.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new "cmdline-fu", File.read("./VERSION").chomp do |p|
6
+ p.author = "t9md"
7
+ p.email = "taqumd@gmail.com"
8
+ p.summary = %Q{CLI frontend for http://www.commandlinefu.com/ }
9
+ p.project = nil
10
+ p.rubyforge_name = nil
11
+ p.url = "http://github.com/t9md/cmdline-fu"
12
+ p.runtime_dependencies << 'colored'
13
+ p.runtime_dependencies << 'hpricot >=0.8.2'
14
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/cmdline-fu ADDED
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require 'net/http'
5
+ require "ostruct"
6
+ require "abbrev"
7
+
8
+ begin
9
+ require "colored"
10
+ rescue LoadError
11
+ end
12
+
13
+ # Example
14
+ # browse/sort-by-votes - All commands sorted by votes
15
+ # tagged/163/grep - Commands tagged with 'grep', sorted by date (the default sort order)
16
+ # matching/ssh/c3No - Search results for the query 'ssh' (note that the final segment is a base64-encoding of the search query)
17
+
18
+ # api_comand_set = [ :browse, :tagged, :matching ]
19
+ # api_format = [ :plaintext, :json, :rss ]
20
+ # api_url = "http://www.commandlinefu.com/commands/<command-set>/<format>/"
21
+
22
+ class CommandLineFu
23
+ API_URL = 'http://www.commandlinefu.com/commands'
24
+
25
+ # attr_reader :api_url
26
+
27
+ def initialize user_opt
28
+ @opt = OpenStruct.new($default_opt.update(user_opt))
29
+ @command = @opt.command
30
+ @format = @opt.format
31
+ @sort_order = @opt.sort_order
32
+ unless @command == "list_tag"
33
+ build_url
34
+ end
35
+ end
36
+
37
+ def result
38
+ return list_tag if @command == "list_tag"
39
+
40
+
41
+ page_idx = (@opt.page - 1) * 25
42
+ url = @api_url + "/#{page_idx}"
43
+
44
+ if @opt.open_browser
45
+ system("open '#{url}'")
46
+ return
47
+ end
48
+ result = open_url(url)
49
+ return "#{@opt.search} NOT FOUND" if result.code != "200"
50
+
51
+ # each entry is separated by blank line , and we need to -1 for page headers.
52
+ b = result.body.split("\n\n")
53
+ header = b.shift
54
+ num_of_entries = b.size
55
+ body = b.join("\n\n")
56
+ unless num_of_entries.zero?
57
+ body = (defined?(Colored) ? colorize(body) : body)
58
+ body << "\n\n## Page(#{@opt.page}):#{page_idx}-#{page_idx+num_of_entries} #{url}".green
59
+ body << "\n##{header}".green
60
+ end
61
+ body
62
+ end
63
+
64
+ def open_url(url)
65
+ uri = URI.parse(url)
66
+ http = Net::HTTP.new(uri.host, uri.port)
67
+ request = Net::HTTP::Get.new(uri.request_uri)
68
+ http.request(request)
69
+ end
70
+
71
+ private
72
+ def build_url
73
+ command_part = send("setup_#{@command}")
74
+ @api_url = "#{API_URL}/%s/%s" % [command_part, @sort_order ]
75
+ @api_url += "/#{@format}" if @format
76
+ end
77
+
78
+ def setup_browse
79
+ "#{@command}"
80
+ end
81
+
82
+ def setup_using
83
+ "#{@command}/#{@opt.search}"
84
+ end
85
+ alias_method :setup_by, :setup_using
86
+
87
+ def setup_matching
88
+ b64text = [@opt.search].pack("m").chomp
89
+ search = @opt.search.tr(' ','-')
90
+ "#{@command}/#{search}/#{b64text}"
91
+ end
92
+
93
+ def setup_tagged
94
+ tag = @opt.search
95
+ tag_id = tags[tag]
96
+ raise "Tag not found" unless tag_id
97
+ "#{@command}/#{tag_id}/#{tag}"
98
+ end
99
+
100
+ def colorize(string)
101
+ string.split("\n").map do |e|
102
+ e.chomp!
103
+ (e =~ /^#/) ? e.blue : e.gsub(/#{@opt.search}/){|m| Colored.colorize m, :foreground => 'magenta' }
104
+ end.join("\n")
105
+ end
106
+
107
+ def tag_file_is_too_old?
108
+ tag_file = File.expand_path @opt.tag_file
109
+ expire_limit = (60 * 60 * 24) * @opt.tag_expire_days
110
+ expire_limit < (Time.now - File.stat(tag_file).mtime)
111
+ end
112
+
113
+ def list_tag
114
+ candidate = tags.keys.grep(/#{@opt.search}/)
115
+ result = if candidate.size >= 1
116
+ colorize(candidate.join("\n"))
117
+ elsif candidate.size == 0
118
+ tags.keys
119
+ end
120
+ result
121
+ end
122
+
123
+ def tags
124
+ @tags ||= load_tags
125
+ end
126
+
127
+ def build_tag_file
128
+ tag_file = File.expand_path @opt.tag_file
129
+ h = extract_tag
130
+ File.open(tag_file, "wb"){ |f| Marshal.dump(h, f) }
131
+ end
132
+
133
+ # def extract_tag_nokogiri
134
+ # require 'nokogiri'
135
+ # h = {}
136
+ # url = 'http://www.commandlinefu.com/commands/browse'
137
+ # Nokogiri::HTML(open_url(url).body).xpath('//div//ul/li/a').map { |link|
138
+ # link['href']
139
+ # }.grep(%r|commands\/tagged|).each { |e|
140
+ # e.scan(%r|/commands/tagged/(\d+)/(.*)|) do |id, name|
141
+ # h[name] = id
142
+ # end
143
+ # }
144
+ # h
145
+ # end
146
+
147
+ def extract_tag
148
+ require "hpricot"
149
+ h = {}
150
+ url = 'http://www.commandlinefu.com/commands/browse'
151
+ Hpricot(open_url(url).body).
152
+ search("div ul li a").map {|e|
153
+ e.attributes['href']
154
+ }.each{ |e|
155
+ e.scan(%r|/commands/tagged/(\d+)/(.*)|) do |id, name|
156
+ h[name] = id
157
+ end
158
+ }
159
+ h
160
+ end
161
+
162
+ def load_tags
163
+ tag_file = File.expand_path @opt.tag_file
164
+ if not File.exist?(tag_file) or tag_file_is_too_old? or $NOCACHE
165
+ build_tag_file
166
+ end
167
+ File.open(tag_file, "rb"){ |f| Marshal.load f }
168
+ end
169
+
170
+ end
171
+ # $NOCACHE = true
172
+
173
+ # TEST
174
+ # [
175
+ # {:command => "browse"},
176
+ # {:command => "using", :search =>'find'},
177
+ # {:command => "by", :search =>'atoponce'},
178
+ # {:command => "matching", :search =>'find'},
179
+ # ].each do |opt|
180
+ # puts "#### #{opt[:command]}"
181
+ # puts CommandLineFu.new(opt).api_url
182
+ # end
183
+
184
+ $default_opt = {
185
+ :page => 1,
186
+ :command => "browse",
187
+ :format => "plaintext",
188
+ :sort_order => "sort-by-votes",
189
+ :tag_file => "~/.fu_tags",
190
+ :tag_expire_days => 3,
191
+ :open_browser => false,
192
+ }
193
+
194
+ command_table = Abbrev.abbrev(%w(list_tag browse using by tagged matching))
195
+
196
+ # user_opt = {}
197
+ # ARGV = %w(browse)
198
+ # ARGV = %w(using find)
199
+ # ARGV = %w(by atoponce)
200
+ # ARGV = %w(matching find)
201
+
202
+
203
+ user_opt = {}
204
+ user_opt[:command] = command_table[ARGV.shift]
205
+
206
+ if ARGV.last == 'o'
207
+ user_opt[:open_browser] = true
208
+ user_opt[:format] = false
209
+ ARGV.pop
210
+ end
211
+
212
+ page = ARGV.last.to_i
213
+ user_opt[:page] = page.zero? ? 1 : page
214
+ user_opt[:search] = ARGV.shift
215
+
216
+
217
+ PROGRAM_NAME = File.basename $0
218
+ if user_opt[:command].nil?
219
+ puts <<-EOS
220
+
221
+ #{"Usage".bold}
222
+
223
+ #{PROGRAM_NAME} COMMAND [PAGE] [o]
224
+
225
+ COMMAND: list_tag [MATCHER], browse, using WORD, by USER, tagged TAG, matching WORD
226
+ PAGE: 1-999 (defaut: 1)
227
+ o: 'o'pen in browser
228
+
229
+ #{"Example".bold}
230
+
231
+ #{PROGRAM_NAME} list_tag
232
+ #{PROGRAM_NAME} list_tag vm
233
+ #{PROGRAM_NAME} browse
234
+ #{PROGRAM_NAME} browse o
235
+ #{PROGRAM_NAME} using find
236
+ #{PROGRAM_NAME} by t9md
237
+ #{PROGRAM_NAME} tagged install
238
+ #{PROGRAM_NAME} matching find
239
+
240
+ #{"Abbreviation".bold}
241
+ Unique abbreviation for command is supported.
242
+
243
+ #{PROGRAM_NAME} l
244
+ #{PROGRAM_NAME} l vm
245
+ #{PROGRAM_NAME} br
246
+ #{PROGRAM_NAME} u find 2
247
+ #{PROGRAM_NAME} u find 2 o
248
+ #{PROGRAM_NAME} by t9md
249
+ #{PROGRAM_NAME} t install
250
+ #{PROGRAM_NAME} m find
251
+
252
+ EOS
253
+ exit
254
+ end
255
+
256
+ # opts = OptionParser.new
257
+ # opts.on( "-l", "--limit NUM", Integer, "upper limit page to get entries."){ |user_opt[:page]| }
258
+ # opts.parse!
259
+
260
+ begin
261
+ fu = CommandLineFu.new user_opt
262
+ ret = fu.result
263
+ puts ret if ret
264
+ rescue => e
265
+ puts e
266
+ exit
267
+ end
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{cmdline-fu}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["t9md"]
9
+ s.date = %q{2010-12-29}
10
+ s.default_executable = %q{cmdline-fu}
11
+ s.description = %q{CLI frontend for http://www.commandlinefu.com/ }
12
+ s.email = %q{taqumd@gmail.com}
13
+ s.executables = ["cmdline-fu"]
14
+ s.extra_rdoc_files = ["LICENSE.txt", "README.md", "bin/cmdline-fu"]
15
+ s.files = ["LICENSE.txt", "Manifest", "README.md", "Rakefile", "VERSION", "bin/cmdline-fu", "cmdline-fu.gemspec"]
16
+ s.homepage = %q{http://github.com/t9md/cmdline-fu}
17
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cmdline-fu", "--main", "README.md"]
18
+ s.require_paths = ["lib"]
19
+ s.rubygems_version = %q{1.3.7}
20
+ s.summary = %q{CLI frontend for http://www.commandlinefu.com/}
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
27
+ s.add_runtime_dependency(%q<colored>, [">= 0"])
28
+ s.add_runtime_dependency(%q<hpricot>, [">= 0.8.2"])
29
+ else
30
+ s.add_dependency(%q<colored>, [">= 0"])
31
+ s.add_dependency(%q<hpricot>, [">= 0.8.2"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<colored>, [">= 0"])
35
+ s.add_dependency(%q<hpricot>, [">= 0.8.2"])
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cmdline-fu
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - t9md
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-29 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: colored
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: hpricot
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 59
44
+ segments:
45
+ - 0
46
+ - 8
47
+ - 2
48
+ version: 0.8.2
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ description: "CLI frontend for http://www.commandlinefu.com/ "
52
+ email: taqumd@gmail.com
53
+ executables:
54
+ - cmdline-fu
55
+ extensions: []
56
+
57
+ extra_rdoc_files:
58
+ - LICENSE.txt
59
+ - README.md
60
+ - bin/cmdline-fu
61
+ files:
62
+ - LICENSE.txt
63
+ - Manifest
64
+ - README.md
65
+ - Rakefile
66
+ - VERSION
67
+ - bin/cmdline-fu
68
+ - cmdline-fu.gemspec
69
+ has_rdoc: true
70
+ homepage: http://github.com/t9md/cmdline-fu
71
+ licenses: []
72
+
73
+ post_install_message:
74
+ rdoc_options:
75
+ - --line-numbers
76
+ - --inline-source
77
+ - --title
78
+ - Cmdline-fu
79
+ - --main
80
+ - README.md
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 11
98
+ segments:
99
+ - 1
100
+ - 2
101
+ version: "1.2"
102
+ requirements: []
103
+
104
+ rubyforge_project:
105
+ rubygems_version: 1.3.7
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: CLI frontend for http://www.commandlinefu.com/
109
+ test_files: []
110
+