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.
- data/.gemtest +0 -0
- data/History.txt +27 -0
- data/Manifest.txt +12 -0
- data/README.txt +70 -0
- data/Rakefile +17 -0
- data/bin/prak +7 -0
- data/lib/prak.rb +9 -0
- data/lib/prak/bootstrap.rb +22 -0
- data/lib/prak/command_line.rb +292 -0
- data/lib/prak/compile_match_file.rb +145 -0
- data/lib/prak/file.rb +142 -0
- data/lib/prak/search.rb +36 -0
- data/prak.gemspec +19 -0
- metadata +85 -0
data/.gemtest
ADDED
File without changes
|
data/History.txt
ADDED
@@ -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
|
+
|
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -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.
|
data/Rakefile
ADDED
@@ -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
|
data/bin/prak
ADDED
data/lib/prak.rb
ADDED
@@ -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
|
data/lib/prak/file.rb
ADDED
@@ -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
|
data/lib/prak/search.rb
ADDED
@@ -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
|
data/prak.gemspec
ADDED
@@ -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: []
|