prak 1.1

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.
File without changes
@@ -0,0 +1,27 @@
1
+
2
+ == 1.0 / 2009-09-27
3
+
4
+ * MinGW is a valid Windows platform type.
5
+ * Can use ~bang and ~ques in a regex and they will be turned into ! and ?
6
+ This is to get around bash.
7
+ * Added -k negative file match option (Contributed by Juozas Gaigalas')
8
+ * Added .cc and .hpp to the C++ file types
9
+ * Added Vala file types
10
+ * 20% faster on average
11
+ * Moved to Github
12
+
13
+ == 0.9 / 2008-02-03
14
+
15
+ * Added .rake to ruby files
16
+ * Colouring works on Win32 if win32console gem is installed.
17
+ * Checks that file is readable by the current user.
18
+ * Ignores socket files.
19
+ * Added .erb and .haml to Ruby filetypes.
20
+ * Added search at end-of/start-of line options
21
+ * Fixed searching up the directory tree when passed '.'
22
+
23
+ == 0.8.0 / 2007-10-30
24
+
25
+ * Initial release.
26
+
27
+
@@ -0,0 +1,12 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/prak
6
+ lib/prak.rb
7
+ lib/prak/bootstrap.rb
8
+ lib/prak/command_line.rb
9
+ lib/prak/compile_match_file.rb
10
+ lib/prak/file.rb
11
+ lib/prak/search.rb
12
+ prak.gemspec
@@ -0,0 +1,70 @@
1
+ prak
2
+
3
+ Original by:
4
+ http://rubyforge.org/projects/rak
5
+ Daniel Lucraft (http://danlucraft.com/blog/)
6
+
7
+ Modifications by Sven Winkler
8
+
9
+ == DESCRIPTION:
10
+
11
+ Replacement for grep. Recursively scans directories to match a given
12
+ Ruby regular expression. Prints highlighted results.
13
+
14
+ Based on the Perl tool 'ack' by Andy Lester.
15
+
16
+ Examples with similar grep:
17
+
18
+ $ prak pattern
19
+ $ grep pattern $(find . | grep -v .svn)
20
+
21
+ $ prak --ruby pattern
22
+ $ grep pattern $(find . -name '*.rb' | grep -v .svn)
23
+
24
+ == FEATURES/PROBLEMS:
25
+
26
+ * Ruby regular expression syntax (uses oniguruma gem if installed).
27
+ * Highlighted output.
28
+ * Automatically recurses down the current directory or any given
29
+ directories.
30
+ * Skips version control directories, backups like '~' and '#' and your
31
+ * ruby project's pkg directory.
32
+ * Allows inclusion and exclusion of files based on types.
33
+ * Many options similar to grep.
34
+
35
+ == SYNOPSIS:
36
+
37
+ See 'prak --help' for usage information.
38
+
39
+ == REQUIREMENTS:
40
+
41
+ * Ruby
42
+
43
+ == INSTALL:
44
+
45
+ * gem install prak
46
+
47
+ == LICENSE:
48
+
49
+ (The MIT License)
50
+
51
+ Original copyright (c) 2007 Daniel Lucraft
52
+
53
+ Permission is hereby granted, free of charge, to any person obtaining
54
+ a copy of this software and associated documentation files (the
55
+ 'Software'), to deal in the Software without restriction, including
56
+ without limitation the rights to use, copy, modify, merge, publish,
57
+ distribute, sublicense, and/or sell copies of the Software, and to
58
+ permit persons to whom the Software is furnished to do so, subject to
59
+ the following conditions:
60
+
61
+ The above copyright notice and this permission notice shall be
62
+ included in all copies or substantial portions of the Software.
63
+
64
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
65
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
66
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
67
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
68
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
69
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
70
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+
2
+ require 'rubygems'
3
+ require 'hoe'
4
+
5
+ $:.unshift 'lib'
6
+
7
+ require 'prak'
8
+
9
+ Hoe.spec('prak') do |p|
10
+ p.author = 'Sven Winkler'
11
+ p.email = 'sven@q-logix.de'
12
+ p.version = Prak::VERSION
13
+ p.summary = 'A grep replacement in Ruby, type "$prak pattern".'
14
+ p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
15
+ p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
16
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
17
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require "prak"
6
+
7
+ Prak.search
@@ -0,0 +1,9 @@
1
+ class Prak
2
+ VERSION = "1.1"
3
+ end
4
+
5
+ require "prak/bootstrap"
6
+ require "prak/command_line"
7
+ require "prak/compile_match_file"
8
+ require "prak/file"
9
+ require "prak/search"
@@ -0,0 +1,22 @@
1
+ require 'getoptlong'
2
+
3
+ begin
4
+ require 'oniguruma'
5
+ require 'inline'
6
+ $use_onig = true
7
+ rescue LoadError
8
+ $use_onig = false
9
+ end
10
+
11
+ class String
12
+ def expand_tabs(shift=0)
13
+ expanded = dup
14
+ 1 while expanded.sub!(/\t+/){ " "*($&.size*8 - ($`.size+shift)%8) }
15
+ expanded
16
+ end
17
+ end
18
+
19
+
20
+
21
+
22
+
@@ -0,0 +1,292 @@
1
+ class Prak
2
+
3
+ FILE_COLOUR = "\033[1;31m"
4
+ MATCH_COLOUR = "\033[1;37m\033[41m"
5
+ CLEAR_COLOURS = "\033[0m"
6
+
7
+ FILE_TYPES = {
8
+ :asm => %w( .s .S ),
9
+ :cc => %w( .c .h .xs ),
10
+ :coffee => %w( .coffee.js .coffee ),
11
+ :cpp => %w( .cpp .cc .m .h .hpp .C .H ),
12
+ :csharp => %w( .cs ),
13
+ :css => %w( .css .sass .scss .less ),
14
+ :elisp => %w( .el ),
15
+ :haskell => %w( .hs .lhs ),
16
+ :hh => %w( .h ),
17
+ :html => %w( .htm .html .shtml ),
18
+ :image => %w( .bmp .gif .jpg .jpeg .png .psd ),
19
+ :lisp => %w( .lisp ),
20
+ :java => %w( .java properties ),
21
+ :js => %w( .js ),
22
+ :jsp => %w( .jsp .jspx .jhtm .jhtml ),
23
+ :make => %w( Makefile ),
24
+ :mason => %w( .mas .mhtml .mpl .mtxt ),
25
+ :ocaml => %w( .ml .mli ),
26
+ :parrot => %w( .pir .pasm .pmc .ops .pod .pg .tg ),
27
+ :perl => %w( .pl .pm .pod .t ),
28
+ :php => %w( .php .phpt .php3 .php4 .php5 ),
29
+ :prolog => %w( .pl .ecl ),
30
+ :python => %w( .py ),
31
+ :ruby => %w( .rb .rhtml .rjs .rxml Rakefile .rake .erb .haml .slim),
32
+ :scheme => %w( .scm ),
33
+ :shell => %w( .sh .bash .csh .ksh .zsh ),
34
+ :sql => %w( .sql .ctl ),
35
+ :tcl => %w( .tcl ),
36
+ :tex => %w( .tex .cls .sty ),
37
+ :text => %w( .txt .text ),
38
+ :tt => %w( .tt .tt2 .ttml ),
39
+ :vala => %w( .vala .vapi ),
40
+ :vb => %w( .bas .cls .frm .ctl .vb .resx ),
41
+ :vim => %w( .vim ),
42
+ :yaml => %w( .yaml .yml ),
43
+ :xml => %w( .xml .dtd .xslt )
44
+ }
45
+
46
+ VC_DIRS = %w(blib CVS _darcs .git .pc RCS SCCS .svn pkg)
47
+
48
+ class << self
49
+ attr_reader :opt
50
+ end
51
+
52
+ def self.unknown_type(type)
53
+ puts "rak: Unknown --type \"#{type}\""
54
+ puts "rak: See rak --help types"
55
+ exit
56
+ end
57
+
58
+ def self.parse_command_line_options options = {}
59
+
60
+ @opt = options
61
+
62
+ # file types
63
+ opt[:includes] = []
64
+ opt[:excludes] = []
65
+
66
+ FILE_TYPES.each do |type, exts|
67
+ if ARGV.delete('--'+type.to_s)
68
+ exts.each do |ext|
69
+ opt[:includes] << ext
70
+ end
71
+ end
72
+ if ARGV.delete('--no'+type.to_s)
73
+ exts.each do |ext|
74
+ opt[:excludes] << ext
75
+ end
76
+ end
77
+ end
78
+
79
+ opts = GetoptLong.new(
80
+ [ '--help', GetoptLong::OPTIONAL_ARGUMENT ],
81
+ [ '--max-count', '-m', GetoptLong::REQUIRED_ARGUMENT ],
82
+ [ '--files', '-f', GetoptLong::NO_ARGUMENT ],
83
+ [ '--output', GetoptLong::REQUIRED_ARGUMENT ],
84
+ [ '--version', GetoptLong::NO_ARGUMENT ],
85
+ [ '-c', '--count', GetoptLong::NO_ARGUMENT ],
86
+ [ '-h', '--no-filename', GetoptLong::NO_ARGUMENT ],
87
+ [ '-i', '--ignore-case', GetoptLong::NO_ARGUMENT ],
88
+ [ '-v', '--invert-match', GetoptLong::NO_ARGUMENT ],
89
+ [ '-n', GetoptLong::NO_ARGUMENT ],
90
+ [ '-Q', '--literal', GetoptLong::NO_ARGUMENT ],
91
+ [ '-o', GetoptLong::NO_ARGUMENT ],
92
+ [ '-w', '--word-regexp', GetoptLong::NO_ARGUMENT ],
93
+ [ '--group', GetoptLong::NO_ARGUMENT ],
94
+ [ '--nogroup', GetoptLong::NO_ARGUMENT ],
95
+ [ '-l', '--files-with-matches', GetoptLong::NO_ARGUMENT ],
96
+ [ '-L', '--files-without-matches', GetoptLong::NO_ARGUMENT ],
97
+ [ '--passthru', GetoptLong::NO_ARGUMENT ],
98
+ [ '-H', '--with-filename', GetoptLong::NO_ARGUMENT ],
99
+ [ '--colour', GetoptLong::NO_ARGUMENT ],
100
+ [ '--nocolour', GetoptLong::NO_ARGUMENT ],
101
+ [ '--color', GetoptLong::NO_ARGUMENT ],
102
+ [ '--nocolor', GetoptLong::NO_ARGUMENT ],
103
+ [ '-a', '--all', GetoptLong::NO_ARGUMENT ],
104
+ [ '--type', GetoptLong::REQUIRED_ARGUMENT ],
105
+ [ '--sort-files', GetoptLong::NO_ARGUMENT ],
106
+ [ '--follow', GetoptLong::NO_ARGUMENT ],
107
+ [ '--nofollow', GetoptLong::NO_ARGUMENT ],
108
+ [ '--after-context', '-A', GetoptLong::REQUIRED_ARGUMENT ],
109
+ [ '--before-context', '-B', GetoptLong::REQUIRED_ARGUMENT ],
110
+ [ '--context', '-C', GetoptLong::OPTIONAL_ARGUMENT ],
111
+ [ '-g', GetoptLong::REQUIRED_ARGUMENT ],
112
+ [ '-k', GetoptLong::REQUIRED_ARGUMENT ],
113
+ [ '-x', '--line-regexp', GetoptLong::NO_ARGUMENT ],
114
+ [ '-s', '--line-start', GetoptLong::NO_ARGUMENT ],
115
+ [ '-e', '--line-end', GetoptLong::NO_ARGUMENT ],
116
+ [ '-E', '--encoding', GetoptLong::REQUIRED_ARGUMENT ],
117
+ )
118
+
119
+ self.standard_options
120
+
121
+ # if redirected (RAK_TEST allows us to redirect in testing and still
122
+ # get the non-redirected defaults).
123
+ unless STDOUT.isatty or ENV['RAK_TEST'] == "true"
124
+ opt[:colour] = false
125
+ opt[:print_file_each_line] = true
126
+ opt[:print_filename] = false
127
+ opt[:print_line_number] = false
128
+ end
129
+
130
+ begin
131
+ opts.each do |option, arg|
132
+ case option
133
+ when '--help'
134
+ if arg == ""
135
+ # TODO: USAGE_HELP
136
+ puts USAGE_HELP
137
+ elsif arg == "types" or arg == "type"
138
+ puts TYPES_HELP
139
+ end
140
+ exit
141
+ when '--max-count'
142
+ opt[:max_count] = arg.to_i
143
+ when '--files'
144
+ opt[:only_print_filelist] = true
145
+ when '--output'
146
+ opt[:print_filename] = false
147
+ opt[:print_line_number] = false
148
+ opt[:print_output] = arg
149
+ opt[:print_highlighted] = false
150
+ when '--version'
151
+ puts VERSION_INFO
152
+ exit
153
+ when '-c'
154
+ opt[:print_num_matches] = true
155
+ opt[:print_filename] = false
156
+ opt[:print_line_number] = false
157
+ opt[:print_highlighted] = false
158
+ when '-h'
159
+ opt[:print_filename] = false
160
+ opt[:print_line_number] = false
161
+ opt[:print_file_each_line] = false
162
+ when '-i'
163
+ opt[:ignore_case] = true
164
+ when '-v'
165
+ opt[:invert_match] = true
166
+ when '-n'
167
+ opt[:descend] = false
168
+ when '-Q'
169
+ opt[:literal] = true
170
+ when '-o'
171
+ opt[:print_match] = true
172
+ opt[:print_filename] = false
173
+ opt[:print_line_number] = false
174
+ opt[:print_highlighted] = false
175
+ when '-w'
176
+ opt[:match_whole_words] = true
177
+ when '--group'
178
+ opt[:print_filename] = true
179
+ opt[:print_file_each_line] = false
180
+ when '--nogroup'
181
+ opt[:print_file_each_line] = true
182
+ opt[:print_filename] = false
183
+ opt[:print_line_number] = false
184
+ when '-l'
185
+ opt[:print_filename] = false
186
+ opt[:print_line_number] = false
187
+ opt[:print_highlighted] = false
188
+ opt[:print_file_if_match] = true
189
+ when '-L'
190
+ opt[:print_filename] = false
191
+ opt[:print_line_number] = false
192
+ opt[:print_highlighted] = false
193
+ opt[:print_file_if_no_match] = true
194
+ when '--passthru'
195
+ opt[:print_entire_line_if_no_match] = true
196
+ when '-H'
197
+ opt[:print_filename] = true
198
+ opt[:print_line_number] = true
199
+ when '--nocolour', '--nocolor'
200
+ opt[:colour] = false
201
+ when '--colour', '--color'
202
+ opt[:colour] = true
203
+ when '-a'
204
+ opt[:all_files] = true
205
+ when '--type'
206
+ if arg[0..1] == "no"
207
+ type = arg[2..-1]
208
+ arr = opt[:excludes]
209
+ else
210
+ type = arg
211
+ arr = opt[:includes]
212
+ end
213
+ exts = FILE_TYPES[type.intern]
214
+ unknown_type(type) unless exts
215
+ exts.each do |ext|
216
+ arr << ext
217
+ end
218
+ when '--sort-files'
219
+ opt[:sort_files] = true
220
+ when '--follow'
221
+ opt[:follow_symlinks] = true
222
+ when '--nofollow'
223
+ opt[:follow_symlinks] = false
224
+ when '--after-context'
225
+ opt[:use_context] = true
226
+ opt[:after_context] = arg.to_i
227
+ when '--before-context'
228
+ opt[:use_context] = true
229
+ opt[:before_context] = arg.to_i
230
+ when '--context'
231
+ opt[:use_context] = true
232
+ if arg == ""
233
+ val = 2
234
+ else
235
+ val = arg.to_i
236
+ end
237
+ opt[:before_context] = val
238
+ opt[:after_context] = val
239
+ when '-g'
240
+ opt[:filename_regex] = compile_regexp(arg)
241
+ when '-k'
242
+ opt[:neg_filename_regex] = compile_regexp(arg)
243
+ when '-x'
244
+ opt[:match_whole_lines] = true
245
+ when '-s'
246
+ opt[:match_line_starts] = true
247
+ when '-e'
248
+ opt[:match_line_ends] = true
249
+ end
250
+ end
251
+ rescue GetoptLong::InvalidOption => ex
252
+ puts "rak: see rak --help for usage."
253
+ exit
254
+ rescue SystemExit
255
+ exit
256
+ end
257
+ end
258
+
259
+ def self.standard_options
260
+ opt[:max_count] = nil
261
+ opt[:only_print_filelist] = false
262
+ opt[:print_filename] = true
263
+ opt[:print_line_number] = true
264
+ opt[:print_output] = nil
265
+ opt[:print_highlighted] = true
266
+ opt[:print_num_matches] = false
267
+ opt[:ignore_case] = false
268
+ opt[:invert_match] = false
269
+ opt[:descend] = true
270
+ opt[:literal] = false
271
+ opt[:print_match] = false
272
+ opt[:match_whole_words] = false
273
+ opt[:match_whole_lines] = false
274
+ opt[:match_line_starts] = false
275
+ opt[:match_line_ends] = false
276
+ opt[:print_file_each_line] = false
277
+ opt[:print_file_if_match] = false
278
+ opt[:print_file_if_no_match] = false
279
+ opt[:print_entire_line_if_no_match] = false
280
+ opt[:colour] = true
281
+ opt[:all_files] = false
282
+ opt[:sort_files] = false
283
+ opt[:follow_symlinks] = false
284
+ opt[:after_context] = 0
285
+ opt[:before_context] = 0
286
+ opt[:collect_context] = false
287
+ opt[:filename_regex] = nil
288
+ opt[:neg_filename_regex] = nil
289
+ opt[:standard_encoding] = "UTF-8"
290
+ end
291
+
292
+ end
@@ -0,0 +1,145 @@
1
+ class Prak
2
+ def self.compile_match_file
3
+ c = []
4
+ c << %{def match_file(re, fn, file_separator) }
5
+ c << %{ displayed_filename = false }
6
+ c << %{ count = 0 }
7
+ c << %{ i = 0 }
8
+ c << %{ matches = [] }
9
+ c << %{ print_num = 0 }
10
+
11
+ if opt[:before_context] > 0
12
+ c << %{ before_context = [] }
13
+ c << %{ before_context_size = opt[:before_context] }
14
+ end
15
+ c << %{ if fn.is_a? String }
16
+ c << %{ f = File.open(fn, "r", :encoding => opt[:standard_encoding]) }
17
+ c << %{ elsif fn.is_a? IO }
18
+ c << %{ f = fn }
19
+ c << %{ end }
20
+
21
+ c << %{ f.each_line do |line| }
22
+ c << %{ line = line.force_encoding("BINARY") unless line.valid_encoding? }
23
+ c << %{ i += 1 }
24
+ if opt[:print_output]
25
+ c << %{ line.scan(re){ matches << eval(opt[:print_output]) } }
26
+ else
27
+ c << %{ line.scan(re){ matches << $~ } }
28
+ end
29
+ if opt[:print_match]
30
+ c << %{ matches.each{|md| puts md.to_s } }
31
+ end
32
+ c << %{ count += matches.size }
33
+ if opt[:invert_match]
34
+ if opt[:print_filename]
35
+ c << %{ unless displayed_filename }
36
+ c << %{ print file_separator }
37
+ c << %{ file_separator.replace("\\n") }
38
+ c << %{ puts FILE_COLOUR + fn + CLEAR_COLOURS }
39
+ c << %{ displayed_filename = true }
40
+ c << %{ end }
41
+ end
42
+ c << %{ if matches.empty? }
43
+ if opt[:print_highlighted]
44
+ if opt[:print_line_number]
45
+ c << %{ print "\#{i.to_s.rjust(4) }|" }
46
+ end
47
+ c << %{ puts "\#{line.expand_tabs }" }
48
+ end
49
+ c << %{ end }
50
+ c << %{ matches.clear }
51
+ else
52
+ c << %{ if matches.empty? }
53
+ if opt[:print_entire_line_if_no_match]
54
+ c << %{ puts line }
55
+ end
56
+ if opt[:use_context]
57
+ if opt[:before_context] > 0
58
+ c << %{ if print_num == 0 }
59
+ c << %{ before_context << [i, line] }
60
+ c << %{ if before_context.length > before_context_size }
61
+ c << %{ before_context.shift }
62
+ c << %{ end }
63
+ c << %{ end }
64
+ end
65
+ c << %{ if print_num > 0 }
66
+ c << %{ print_num -= 1 }
67
+ if opt[:print_highlighted]
68
+ if opt[:print_line_number]
69
+ c << %{ print "\#{i.to_s.rjust(4) }|" }
70
+ end
71
+ c << %{ puts "\#{line.expand_tabs }" }
72
+ c << %{ end }
73
+ end
74
+ end
75
+ c << %{ else }
76
+ c << %{ print_num = opt[:after_context] }
77
+ if opt[:print_filename]
78
+ c << %{ unless displayed_filename }
79
+ c << %{ print file_separator }
80
+ c << %{ file_separator.replace("\\n") }
81
+ c << %{ puts FILE_COLOUR + fn + CLEAR_COLOURS }
82
+ c << %{ displayed_filename = true }
83
+ c << %{ end }
84
+ end
85
+ if opt[:before_context] > 0
86
+ c << %{ before_context.each do |before_i, before_line| }
87
+ if opt[:print_line_number]
88
+ c << %{ print "\#{before_i.to_s.rjust(4) }|" }
89
+ end
90
+ c << %{ puts before_line.expand_tabs }
91
+ c << %{ end }
92
+ c << %{ before_context = [] }
93
+ end
94
+ if opt[:print_output]
95
+ c << %{ matches.each {|m| puts m } }
96
+ end
97
+ if opt[:print_highlighted]
98
+ if opt[:print_line_number]
99
+ c << %{ prefix = "\#{i.to_s.rjust(4) }|" }
100
+ else
101
+ if opt[:print_file_each_line]
102
+ c << %{ fn_str = (fn.is_a?(String) ? FILE_COLOUR + fn + CLEAR_COLOURS + ":" : "") }
103
+ c << %{ prefix = fn_str + "\#{i.to_s }:" }
104
+ else
105
+ c << %{ prefix = "" }
106
+ end
107
+ end
108
+ c << %{ print_highlighted(prefix, line, matches) }
109
+ end
110
+ c << %{ end }
111
+ if opt[:max_count]
112
+ c << %{ if count >= opt[:max_count] }
113
+ c << %{ break }
114
+ c << %{ end }
115
+ end
116
+ c << %{ matches.clear }
117
+ end
118
+ c << %{ end }
119
+ c << %{ f.close if f === File }
120
+ if opt[:print_num_matches]
121
+ if opt[:invert_match]
122
+ c << %{ puts "\#{fn }:\#{i-count }" }
123
+ else
124
+ c << %{ if count > 0 }
125
+ c << %{ puts "\#{fn }:\#{count }" }
126
+ c << %{ end }
127
+ end
128
+ end
129
+ if opt[:print_file_if_match]
130
+ c << %{ if count > 0 }
131
+ c << %{ puts fn }
132
+ c << %{ end }
133
+ end
134
+
135
+ if opt[:print_file_if_no_match]
136
+ c << %{ if count == 0 }
137
+ c << %{ puts fn }
138
+ c << %{ end }
139
+ end
140
+ c << %{end }
141
+
142
+ Prak.instance_eval c.join("\n")
143
+
144
+ end
145
+ end
@@ -0,0 +1,142 @@
1
+ class Prak
2
+
3
+ def self.file_relevant?(fn)
4
+ # These don't change at this point
5
+ @types_rx ||= extension_regexp(FILE_TYPES.values.flatten)
6
+ @includes_rx ||= extension_regexp(opt[:includes])
7
+ @excludes_rx ||= extension_regexp(opt[:excludes])
8
+
9
+ ext = File.basename(fn)
10
+ ext = shebang_matches(fn) unless ext =~ @types_rx
11
+
12
+ return false if !opt[:all_files] and !ext or fn =~ /[~#]\z/
13
+ return false if @includes_rx and (ext||"") !~ @includes_rx
14
+ return false if @excludes_rx and (ext||"") =~ @excludes_rx
15
+ return false if opt[:filename_regex] and fn !~ opt[:filename_regex]
16
+ return false if opt[:neg_filename_regex] and fn =~ opt[:neg_filename_regex]
17
+ return true
18
+ end
19
+
20
+ def self.find_all_files(path, &blk)
21
+ return if File.socket?(path)
22
+ return unless File.readable?(path)
23
+
24
+ if File.file?(path)
25
+ return unless file_relevant?(path)
26
+ yield(path.sub(/\A\.\/+/, "").gsub(/\/+/, "/"))
27
+ elsif File.directory?(path)
28
+ Dir["#{path}/*"].each do |fn|
29
+ next if VC_DIRS.any?{|vc| vc == File.basename(fn)}
30
+ next if File.directory?(fn) and not opt[:descend]
31
+ next if File.symlink?(fn) and not opt[:follow_symlinks]
32
+ find_all_files(fn, &blk)
33
+ end
34
+ end
35
+ end
36
+
37
+ # It's really asking for Pathname...
38
+ def self.each_file(todo, &blk)
39
+ if todo.empty?
40
+ if STDIN.isatty
41
+ todo = ["."]
42
+ else
43
+ opt[:print_filename] = false
44
+ yield(STDIN)
45
+ return
46
+ end
47
+ elsif todo.size == 1 and File.file?(todo[0])
48
+ opt[:print_filename] = false
49
+ end
50
+
51
+ if opt[:sort_files]
52
+ sortme = []
53
+ todo.each do |item|
54
+ find_all_files(item) do |fn|
55
+ sortme << fn
56
+ end
57
+ end
58
+ sortme.sort_by{|fn|fn.downcase}.each(&blk)
59
+ else
60
+ todo.each do |item|
61
+ find_all_files(item, &blk)
62
+ end
63
+ end
64
+ end
65
+
66
+ def self.print_highlighted(prefix, line, matches)
67
+ print prefix
68
+ matches = matches.map{|md| md.offset(0)}
69
+ cuts = [0, matches, line.size].flatten
70
+ column = 0
71
+ 0.upto(cuts.size-2) do |i|
72
+ part = line[cuts[i]...cuts[i+1]]
73
+ part = part.expand_tabs(column)
74
+ column += part.size
75
+ print MATCH_COLOUR if i%2 == 1
76
+ print part
77
+ print CLEAR_COLOURS if i%2 == 1
78
+ end
79
+ print "\n" unless line[-1,1] == "\n"
80
+ end
81
+
82
+ def self.compile_regexp(str)
83
+ if $use_onig
84
+ Oniguruma::ORegexp.new(str)
85
+ else
86
+ Regexp.new(str)
87
+ end
88
+ end
89
+
90
+ def self.extension_regexp(extensions)
91
+ return nil if extensions.empty?
92
+ Regexp.compile('(?:' + extensions.map{|x| Regexp.escape(x)}.join("|") + ')\z')
93
+ end
94
+
95
+ def self.shebang_matches(fn)
96
+ begin
97
+ line = File.open(fn, :encoding => opt[:standard_encoding]).readline
98
+ if line =~ /^#!/
99
+ if line =~ /\b(ruby|perl|php|python|make)[0-9.]*\b/i
100
+ FILE_TYPES[$1.downcase.intern].first
101
+ elsif line =~ /\b(sh|bash|csh|ksh|zsh)\b/
102
+ ".sh"
103
+ else
104
+ ".other"
105
+ end
106
+ elsif line =~ /^<\?xml\b/
107
+ ".xml"
108
+ else
109
+ false
110
+ end
111
+ rescue
112
+ nil
113
+ end
114
+ end
115
+
116
+ def self.compile_pattern(str)
117
+ if opt[:literal]
118
+ str = Regexp.quote(str)
119
+ end
120
+ if opt[:match_whole_words]
121
+ str = "\\b(?:" + str + ")\\b"
122
+ end
123
+ if opt[:match_whole_lines]
124
+ str = "^(?:" + str + ")$"
125
+ end
126
+ if opt[:match_line_starts]
127
+ str = "^(?:" + str + ")"
128
+ end
129
+ if opt[:match_line_ends]
130
+ str = "(?:" + str + ")$"
131
+ end
132
+ str = str.gsub("~bang", "!").gsub("~ques", "?")
133
+ if $use_onig
134
+ flags = opt[:ignore_case] ? Oniguruma::OPTION_IGNORECASE : nil
135
+ Oniguruma::ORegexp.new(str, :options => flags)
136
+ else
137
+ flags = opt[:ignore_case] ? Regexp::IGNORECASE : nil
138
+ Regexp.new(str, flags)
139
+ end
140
+ end
141
+
142
+ end
@@ -0,0 +1,36 @@
1
+ class Prak
2
+
3
+ def self.search
4
+
5
+ parse_command_line_options
6
+
7
+ unless opt[:colour]
8
+ FILE_COLOUR.replace ""
9
+ CLEAR_COLOURS.replace ""
10
+ MATCH_COLOUR.replace ""
11
+ end
12
+
13
+ if opt[:only_print_filelist]
14
+ each_file(ARGV) do |fn|
15
+ puts fn
16
+ end
17
+ elsif ARGV.empty?
18
+ # TODO USAGE_HELP
19
+ puts USAGE_HELP
20
+ exit
21
+ else
22
+ re = compile_pattern(ARGV.shift)
23
+ compiled = false
24
+ file_separator = ""
25
+ each_file(ARGV) do |fn|
26
+ # each_file might turn off printing file name, but only before first yield
27
+ unless compiled
28
+ compile_match_file
29
+ compiled = true
30
+ end
31
+ match_file(re, fn, file_separator)
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+
2
+ Gem::Specification.spec do |s|
3
+ s.name = %q{prak}
4
+ s.version = "2.0"
5
+
6
+ s.authors = ["Daniel Lucraft"]
7
+ s.date = %q{2008-02-03}
8
+ s.default_executable = %q{prak}
9
+ s.description = %q{Based on the Perl tool 'ack' by Andy Lester. Examples with similar grep: $ prak pattern $ grep pattern $(find . | grep -v .svn) $ prak --ruby pattern $ grep pattern $(find . -name '*.rb' | grep -v .svn) == FEATURES/PROBLEMS: * Ruby regular expression syntax (uses oniguruma gem if installed). * Highlighted output. * Automatically recurses down the current directory or any given directories. * Skips version control directories, backups like '~' and '#' and your * ruby project's pkg directory. * Allows inclusion and exclusion of files based on types. * Many options similar to grep.}
10
+ s.email = %q{dan@fluentradical.com}
11
+ s.executables = ["prak"]
12
+ s.files = FileList["{lib,spec,bin,doc}/**/*"]
13
+ s.homepage = %q{http://github.com/sven-q/prak.git}
14
+ s.require_paths = ["lib"]
15
+ s.rubygems_version = %q{1.3.0}
16
+ s.summary = %q{A grep replacement in Ruby, type "prak pattern".}
17
+ s.required_ruby_version = '>= 1.9.2'
18
+
19
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prak
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sven Winkler
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-23 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: hoe
16
+ requirement: &2153032040 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.12'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *2153032040
25
+ description: ! 'Modifications by Sven Winkler
26
+
27
+
28
+ == DESCRIPTION:
29
+
30
+
31
+ Replacement for grep. Recursively scans directories to match a given
32
+
33
+ Ruby regular expression. Prints highlighted results.
34
+
35
+
36
+ Based on the Perl tool ''ack'' by Andy Lester.'
37
+ email: sven@q-logix.de
38
+ executables:
39
+ - prak
40
+ extensions: []
41
+ extra_rdoc_files:
42
+ - History.txt
43
+ - Manifest.txt
44
+ - README.txt
45
+ files:
46
+ - History.txt
47
+ - Manifest.txt
48
+ - README.txt
49
+ - Rakefile
50
+ - bin/prak
51
+ - lib/prak.rb
52
+ - lib/prak/bootstrap.rb
53
+ - lib/prak/command_line.rb
54
+ - lib/prak/compile_match_file.rb
55
+ - lib/prak/file.rb
56
+ - lib/prak/search.rb
57
+ - prak.gemspec
58
+ - .gemtest
59
+ homepage:
60
+ licenses: []
61
+ post_install_message:
62
+ rdoc_options:
63
+ - --main
64
+ - README.txt
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project: prak
81
+ rubygems_version: 1.8.6
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: A grep replacement in Ruby, type "$prak pattern".
85
+ test_files: []