codestock 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 (57) hide show
  1. data/.document +5 -0
  2. data/Gemfile +12 -0
  3. data/Gemfile.lock +18 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.rdoc +19 -0
  6. data/Rakefile +63 -0
  7. data/VERSION +1 -0
  8. data/bin/cdstk +12 -0
  9. data/bin/cdv +11 -0
  10. data/bin/cdview +11 -0
  11. data/bin/cdweb +11 -0
  12. data/codestock.gemspec +131 -0
  13. data/lib/codestock.rb +0 -0
  14. data/lib/common/dbdir.rb +37 -0
  15. data/lib/common/display_util.rb +62 -0
  16. data/lib/common/grenfiletest.rb +19 -0
  17. data/lib/common/grensnip.rb +37 -0
  18. data/lib/common/platform.rb +17 -0
  19. data/lib/common/string_snip.rb +61 -0
  20. data/lib/common/util.rb +98 -0
  21. data/lib/findgrep/findgrep.rb +408 -0
  22. data/lib/findgrep/result.rb +43 -0
  23. data/lib/gren/cli.rb +65 -0
  24. data/lib/gren.rb +6 -0
  25. data/lib/grendb/cli.rb +43 -0
  26. data/lib/grenweb/cli.rb +54 -0
  27. data/lib/grenweb/database.rb +182 -0
  28. data/lib/grenweb/grenweb.ru +35 -0
  29. data/lib/grenweb/grep.rb +52 -0
  30. data/lib/grenweb/help.rb +40 -0
  31. data/lib/grenweb/home.rb +40 -0
  32. data/lib/grenweb/html_renderer.rb +244 -0
  33. data/lib/grenweb/public/css/gren.css +63 -0
  34. data/lib/grenweb/public/images/gren-icon-mini.png +0 -0
  35. data/lib/grenweb/public/images/gren-icon.png +0 -0
  36. data/lib/grenweb/query.rb +82 -0
  37. data/lib/grenweb/searcher.rb +130 -0
  38. data/lib/grenweb/viewer.rb +52 -0
  39. data/lib/mkgrendb/cli.rb +89 -0
  40. data/lib/mkgrendb/cli_old.rb +49 -0
  41. data/lib/mkgrendb/grendbyaml.rb +76 -0
  42. data/lib/mkgrendb/mkgrendb.rb +296 -0
  43. data/test/file_test_utils.rb +59 -0
  44. data/test/runner.rb +11 -0
  45. data/test/test_dbdir.rb +59 -0
  46. data/test/test_gren.rb +10 -0
  47. data/test/test_gren_util.rb +34 -0
  48. data/test/test_grendbyaml.rb +109 -0
  49. data/test/test_grenweb_cli.rb +10 -0
  50. data/test/test_grenweb_database.rb +37 -0
  51. data/test/test_grenweb_html_renderer.rb +41 -0
  52. data/test/test_grenweb_query.rb +54 -0
  53. data/test/test_grenweb_searcher.rb +35 -0
  54. data/test/test_helper.rb +2 -0
  55. data/test/test_mkgrendb.rb +163 -0
  56. data/test/test_string_snip.rb +31 -0
  57. metadata +229 -0
@@ -0,0 +1,82 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief クエリーの解析
5
+ # @author ongaeshi
6
+ # @date 2010/10/21
7
+
8
+ require 'rubygems'
9
+ require 'rack'
10
+
11
+ module Grenweb
12
+ class Query
13
+ include Rack::Utils
14
+ attr_reader :query_string
15
+
16
+ OPTIONS = [
17
+ ['package', 'p'],
18
+ ['filepath', 'fpath', 'f'],
19
+ ['suffix', 's'],
20
+ ]
21
+
22
+ def initialize(request)
23
+ @query_string = unescape(request.path_info.gsub(/\A\/|\/\z/, ''))
24
+ init_hash
25
+ parse
26
+ end
27
+
28
+ def escape_html
29
+ Rack::Utils::escape_html(@query_string)
30
+ end
31
+
32
+ def empty?
33
+ keywords.size == 0 && packages.size == 0 && fpaths.size == 0 && suffixs.size == 0
34
+ end
35
+
36
+ def keywords
37
+ @hash['keywords']
38
+ end
39
+
40
+ def packages
41
+ calc_param(0)
42
+ end
43
+
44
+ def fpaths
45
+ calc_param(1)
46
+ end
47
+
48
+ def suffixs
49
+ calc_param(2)
50
+ end
51
+
52
+ private
53
+
54
+ def calc_param(index)
55
+ OPTIONS[index].inject([]){|result, item| result.concat @hash[item] }
56
+ end
57
+
58
+ def init_hash
59
+ @hash = {}
60
+ @hash['keywords'] = []
61
+
62
+ OPTIONS.flatten.each do |key|
63
+ @hash[key] = []
64
+ end
65
+ end
66
+
67
+ def parse
68
+ kp = OPTIONS.flatten.join('|')
69
+ parts = @query_string.scan(/(?:(#{kp}):)?(?:"(.+)"|(\S+))/)
70
+
71
+ parts.each do |key, quoted_value, value|
72
+ text = quoted_value || value
73
+ unless (key)
74
+ @hash['keywords'] << text
75
+ else
76
+ @hash[key] << text
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+
@@ -0,0 +1,130 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief 検索処理本体
5
+ # @author ongaeshi
6
+ # @date 2010/10/13
7
+
8
+ require 'rubygems'
9
+ require 'rack'
10
+ require File.join(File.dirname(__FILE__), 'database')
11
+ require File.join(File.dirname(__FILE__), 'html_renderer')
12
+ require File.join(File.dirname(__FILE__), 'query')
13
+
14
+ module Grenweb
15
+ class Searcher
16
+ include Rack::Utils
17
+
18
+ def initialize
19
+ end
20
+
21
+ def call(env)
22
+ @request = Rack::Request.new(env)
23
+ @query = Query.new(@request)
24
+
25
+ @response = Rack::Response.new
26
+ @response["Content-Type"] = "text/html; charset=UTF-8"
27
+
28
+ @nth = 3 # マッチした行の前後何行を表示するか
29
+
30
+ @rendeler = HTMLRendeler.new(@request.script_name + '/..')
31
+
32
+ if @request.post? or @request['query']
33
+ post_request
34
+ else
35
+ search
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def post_request
42
+ query = @request['query'] || ''
43
+ if query.empty?
44
+ @request.path_info = "/"
45
+ else
46
+ @request.path_info = "/#{escape(query)}/"
47
+ end
48
+ @response.redirect(@request.url.split(/\?/, 2)[0])
49
+ @response.to_a
50
+ end
51
+
52
+ def search
53
+ render_header
54
+ render_search_box
55
+ render_search_result
56
+ render_footer
57
+ @response.to_a
58
+ end
59
+
60
+ def render_header
61
+ @response.write @rendeler.header("gren : #{@query.escape_html}", "gren")
62
+ end
63
+
64
+ def render_search_box
65
+ @response.write @rendeler.search_box(@query.escape_html)
66
+ end
67
+
68
+ def render_search_result
69
+ if @query.empty?
70
+ @response.write @rendeler.empty_summary
71
+ else
72
+ records, total_records, elapsed = Database.instance.search(@query.keywords, @query.packages, @query.fpaths, @query.suffixs, calcPage, calcLimit)
73
+ render_search_summary(records, total_records, elapsed)
74
+ records.each { |record| @response.write(@rendeler.result_record(record, @query.keywords, @nth)) }
75
+ render_pagination(calcPage, total_records)
76
+ end
77
+ end
78
+
79
+ def render_search_summary(records, total_records, elapsed)
80
+ pageStart = calcPage * calcLimit
81
+ @response.write @rendeler.search_summary(@query.query_string,
82
+ total_records,
83
+ (total_records.zero? ? 0 : pageStart + 1)..(pageStart + records.size),
84
+ elapsed)
85
+ end
86
+
87
+ def render_pagination(page, total_records)
88
+ return if @query.empty?
89
+ return if total_records < calcLimit
90
+
91
+ last_page = (total_records / calcLimit.to_f).ceil
92
+ @response.write("<div class='pagination'>\n")
93
+ if page > 0
94
+ @response.write(@rendeler.pagination_link(page - 1, "<<"))
95
+ end
96
+ last_page.times do |i|
97
+ if i == page
98
+ @response.write(@rendeler.pagination_span(i))
99
+ else
100
+ @response.write(@rendeler.pagination_link(i, i))
101
+ end
102
+ end
103
+ if page < (last_page - 1)
104
+ @response.write(@rendeler.pagination_link(page + 1, ">>"))
105
+ end
106
+ @response.write("</div>\n")
107
+ end
108
+
109
+ def render_footer
110
+ @response.write @rendeler.footer
111
+ end
112
+
113
+ private
114
+
115
+ # 1ページに表示する最大レコードを計算
116
+ def calcLimit
117
+ if @query.keywords.size == 0
118
+ 100
119
+ else
120
+ 20
121
+ end
122
+ end
123
+
124
+ # 現在ページを計算
125
+ def calcPage
126
+ (@request['page'] || 0).to_i
127
+ end
128
+ end
129
+ end
130
+
@@ -0,0 +1,52 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief ソースコードを表示する
5
+ # @author ongaeshi
6
+ # @date 2010/10/13
7
+
8
+ require 'rubygems'
9
+ require 'rack'
10
+ require File.join(File.dirname(__FILE__), 'database')
11
+ require File.join(File.dirname(__FILE__), 'html_renderer')
12
+
13
+ module Grenweb
14
+ class Viewer
15
+ include Rack::Utils
16
+
17
+ def initialize
18
+ end
19
+
20
+ def call(env)
21
+ @request = Rack::Request.new(env)
22
+ @response = Rack::Response.new
23
+ @response["Content-Type"] = "text/html; charset=UTF-8"
24
+
25
+ record, elapsed = Database.instance.record(req2query)
26
+
27
+ @rendeler = HTMLRendeler.new(@request.script_name + '/..')
28
+
29
+ if (record)
30
+ @response.write @rendeler.header("gren : #{record.shortpath}", "gren")
31
+ @response.write @rendeler.search_box("")
32
+ @response.write @rendeler.view_summary(record.shortpath, elapsed)
33
+ @response.write @rendeler.record_content(record)
34
+ else
35
+ @response.write @rendeler.header("gren : not found.", "gren")
36
+ @response.write @rendeler.search_box("")
37
+ @response.write @rendeler.empty_summary
38
+ end
39
+ @response.write @rendeler.footer
40
+
41
+ @response.to_a
42
+ end
43
+
44
+ private
45
+
46
+ def req2query
47
+ p @request.path_info
48
+ unescape(@request.path_info.gsub(/\A\/|\/z/, ''))
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,89 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'optparse'
3
+ require File.join(File.dirname(__FILE__), 'mkgrendb')
4
+ require File.join(File.dirname(__FILE__), '../common/dbdir.rb')
5
+ include CodeStock
6
+
7
+ module Mkgrendb
8
+ class CLI
9
+ def self.execute(stdout, arguments=[])
10
+ opt = OptionParser.new <<EOF
11
+ #{File.basename($0)} COMMAND [ARGS]
12
+
13
+ The most commonly used mkgrendb are:
14
+ init Init db.
15
+ update Update db.
16
+ add Add contents. (ex. ~/Documents/gren, git://github.com/ongaeshi/gren.git)
17
+ remove Remove contents.
18
+ list List all contents.
19
+ rebuild Rebuild db.
20
+ dump Dump database contents.
21
+ EOF
22
+
23
+ subopt = Hash.new
24
+
25
+ init_default = false
26
+ subopt['init'] = OptionParser.new("#{File.basename($0)} init")
27
+ subopt['init'].on('--default', 'Init db default path. (Maybe ~/.codestock)') { init_default = true }
28
+
29
+ subopt['update'] = OptionParser.new("#{File.basename($0)} update")
30
+ subopt['add'] = OptionParser.new("#{File.basename($0)} add content1 [content2 ...]")
31
+ subopt['remove'] = OptionParser.new("#{File.basename($0)} remove content1 [content2 ...]")
32
+ subopt['list'] = OptionParser.new("#{File.basename($0)} list")
33
+ subopt['rebuild'] = OptionParser.new("#{File.basename($0)} rebuild")
34
+ subopt['dump'] = OptionParser.new("#{File.basename($0)} dump")
35
+
36
+ opt.order!(arguments)
37
+ subcommand = arguments.shift
38
+
39
+ if (subopt[subcommand])
40
+ subopt[subcommand].parse!(arguments) unless arguments.empty?
41
+
42
+ db_dir = select_dbdir(subcommand, init_default)
43
+ obj = Mkgrendb.new(stdout, db_dir)
44
+
45
+ case subcommand
46
+ when 'init'
47
+ FileUtils.mkdir_p db_dir if (init_default)
48
+ obj.init
49
+ when 'update'
50
+ obj.update
51
+ when 'add'
52
+ obj.add *arguments
53
+ when 'remove'
54
+ obj.remove *arguments
55
+ when 'list'
56
+ obj.list
57
+ when 'rebuild'
58
+ obj.rebuild
59
+ when 'dump'
60
+ obj.dump
61
+ end
62
+ else
63
+ if subcommand
64
+ $stderr.puts "mkgrendb: '#{subcommand}' is not a mkgrendb command. See 'mkgrendb --help'"
65
+ else
66
+ stdout.puts opt.help
67
+ end
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def self.select_dbdir(subcommand, init_default)
74
+ if (subcommand == 'init')
75
+ if (init_default)
76
+ db_default_dir
77
+ else
78
+ '.'
79
+ end
80
+ else
81
+ if (dbdir?('.') || !dbdir?(db_default_dir))
82
+ '.'
83
+ else
84
+ db_default_dir
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,49 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'optparse'
3
+ require File.join(File.dirname(__FILE__), 'mkgrendb')
4
+
5
+ module Mkgrendb
6
+ class CLI
7
+ def self.execute(stdout, arguments=[])
8
+ input_yamls = []
9
+ isDump = false
10
+ isFull = false
11
+ isDelete = false
12
+ isReport = false
13
+
14
+ opt = OptionParser.new "#{File.basename($0)} INPUT_YAML1 [INPUT_YAML2 ...]"
15
+ opt.on('--ddb', "--default-db", "Create or Update default DB. (Plase set ENV['GRENDB_DEFAULT_DB'])") {|v| input_yamls << ENV['GRENDB_DEFAULT_DB']}
16
+ opt.on('--full', "Full update DB. (Delete and create)") {|v| isFull = true }
17
+ opt.on('--delete', "Delete DB. (Not delete yaml)") {|v| isDelete = true }
18
+ opt.on('--dump', "Dump DB.") {|v| isDump = true }
19
+ opt.on('--report', "Database Report.") {|v| isReport = true }
20
+ opt.parse!(arguments)
21
+
22
+ input_yamls.concat arguments
23
+
24
+ if (input_yamls.size >= 1)
25
+ input_yamls.each do |input_yaml|
26
+ obj = Mkgrendb.new(input_yaml)
27
+
28
+ if (isFull)
29
+ obj.full
30
+ stdout.puts
31
+ elsif (isDelete)
32
+ obj.delete
33
+ stdout.puts
34
+ elsif (isDump)
35
+ obj.dump
36
+ elsif (isReport)
37
+ obj.report
38
+ else
39
+ obj.update
40
+ stdout.puts
41
+ end
42
+
43
+ end
44
+ else
45
+ stdout.puts opt.help
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,76 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief
5
+ # @author ongaeshi
6
+ # @date 2011/02/20
7
+
8
+ require 'yaml'
9
+ require 'pathname'
10
+
11
+ module Mkgrendb
12
+ class GrendbYAML
13
+ class YAMLAlreadyExist < RuntimeError
14
+ end
15
+
16
+ class YAMLNotExist < RuntimeError
17
+ end
18
+
19
+ def self.create(path = ".")
20
+ yf = yaml_file(path)
21
+ raise YAMLAlreadyExist.new if FileTest.exist? yf
22
+ obj = GrendbYAML.new(yf, {'contents' => [], 'version' => 0.1})
23
+ obj.save
24
+ return obj
25
+ end
26
+
27
+ def self.load(path = ".")
28
+ yf = yaml_file(path)
29
+ raise YAMLNotExist.new unless FileTest.exist? yf
30
+ open(yf) do |f|
31
+ return GrendbYAML.new(yf, YAML.load(f.read()))
32
+ end
33
+ end
34
+
35
+ def add(*dirs)
36
+ contents.push(*dirs.map{|v|{"directory" => v}})
37
+ contents.uniq!
38
+ end
39
+
40
+ def remove(*dirs)
41
+ dirs.each {|f| contents.delete( {"directory" => f} ) }
42
+ end
43
+
44
+ def save
45
+ open(@yaml_file, "w") { |f| YAML.dump(@data, f) }
46
+ end
47
+
48
+ def contents
49
+ @data['contents']
50
+ end
51
+
52
+ def directorys
53
+ contents.map{|v|v["directory"]}
54
+ end
55
+
56
+ def version
57
+ @data['version']
58
+ end
59
+
60
+ def list
61
+ directorys
62
+ end
63
+
64
+ def self.yaml_file(path)
65
+ (Pathname.new(path) + 'grendb.yaml').to_s
66
+ end
67
+
68
+ private
69
+
70
+ def initialize(yaml_file, data)
71
+ @yaml_file = yaml_file
72
+ @data = data
73
+ end
74
+
75
+ end
76
+ end