diakonos 0.8.7 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. metadata +38 -59
  2. data/CHANGELOG +0 -238
  3. data/LICENCE +0 -21
  4. data/README +0 -75
  5. data/bin/diakonos +0 -6
  6. data/diakonos-256-colour.conf +0 -102
  7. data/diakonos.conf +0 -1233
  8. data/lib/diakonos.rb +0 -618
  9. data/lib/diakonos/array.rb +0 -15
  10. data/lib/diakonos/bignum.rb +0 -9
  11. data/lib/diakonos/bookmark.rb +0 -50
  12. data/lib/diakonos/buffer-hash.rb +0 -60
  13. data/lib/diakonos/buffer-management.rb +0 -73
  14. data/lib/diakonos/buffer.rb +0 -2044
  15. data/lib/diakonos/clipboard.rb +0 -47
  16. data/lib/diakonos/config.rb +0 -304
  17. data/lib/diakonos/ctag.rb +0 -28
  18. data/lib/diakonos/display.rb +0 -288
  19. data/lib/diakonos/enumerable.rb +0 -15
  20. data/lib/diakonos/finding.rb +0 -32
  21. data/lib/diakonos/fixnum.rb +0 -17
  22. data/lib/diakonos/functions.rb +0 -1420
  23. data/lib/diakonos/grep.rb +0 -78
  24. data/lib/diakonos/hash.rb +0 -108
  25. data/lib/diakonos/help.rb +0 -92
  26. data/lib/diakonos/hooks.rb +0 -13
  27. data/lib/diakonos/interaction.rb +0 -139
  28. data/lib/diakonos/keycode.rb +0 -110
  29. data/lib/diakonos/keying.rb +0 -124
  30. data/lib/diakonos/list.rb +0 -55
  31. data/lib/diakonos/logging.rb +0 -24
  32. data/lib/diakonos/object.rb +0 -6
  33. data/lib/diakonos/readline.rb +0 -274
  34. data/lib/diakonos/regexp.rb +0 -6
  35. data/lib/diakonos/sessions.rb +0 -70
  36. data/lib/diakonos/sized-array.rb +0 -48
  37. data/lib/diakonos/string.rb +0 -326
  38. data/lib/diakonos/text-mark.rb +0 -19
  39. data/lib/diakonos/vendor/fuzzy_file_finder.rb +0 -353
  40. data/lib/diakonos/window.rb +0 -32
  41. data/test/buffer-test.rb +0 -53
  42. data/test/clipboard-test.rb +0 -70
  43. data/test/diakonos-test.rb +0 -14
  44. data/test/hash-test.rb +0 -404
  45. data/test/regexp-test.rb +0 -26
  46. data/test/sizedarray-test.rb +0 -113
  47. data/test/string-test.rb +0 -160
@@ -1,19 +0,0 @@
1
- module Diakonos
2
-
3
- class TextMark
4
- attr_reader :formatting, :start_row, :start_col, :end_row, :end_col
5
-
6
- def initialize( start_row, start_col, end_row, end_col, formatting )
7
- @start_row = start_row
8
- @start_col = start_col
9
- @end_row = end_row
10
- @end_col = end_col
11
- @formatting = formatting
12
- end
13
-
14
- def to_s
15
- "(#{start_row},#{start_col})-(#{end_row},#{end_col}) #{formatting}"
16
- end
17
- end
18
-
19
- end
@@ -1,353 +0,0 @@
1
- #--
2
- # ==================================================================
3
- # Author: Jamis Buck (jamis@jamisbuck.org)
4
- # Date: 2008-10-09
5
- #
6
- # This file is in the public domain. Usage, modification, and
7
- # redistribution of this file are unrestricted.
8
- # ==================================================================
9
- #++
10
-
11
- # The "fuzzy" file finder provides a way for searching a directory
12
- # tree with only a partial name. This is similar to the "cmd-T"
13
- # feature in TextMate (http://macromates.com).
14
- #
15
- # Usage:
16
- #
17
- # finder = FuzzyFileFinder.new
18
- # finder.search("app/blogcon") do |match|
19
- # puts match[:highlighted_path]
20
- # end
21
- #
22
- # In the above example, all files matching "app/blogcon" will be
23
- # yielded to the block. The given pattern is reduced to a regular
24
- # expression internally, so that any file that contains those
25
- # characters in that order (even if there are other characters
26
- # in between) will match.
27
- #
28
- # In other words, "app/blogcon" would match any of the following
29
- # (parenthesized strings indicate how the match was made):
30
- #
31
- # * (app)/controllers/(blog)_(con)troller.rb
32
- # * lib/c(ap)_(p)ool/(bl)ue_(o)r_(g)reen_(co)loratio(n)
33
- # * test/(app)/(blog)_(con)troller_test.rb
34
- #
35
- # And so forth.
36
- class FuzzyFileFinder
37
- module Version
38
- MAJOR = 1
39
- MINOR = 0
40
- TINY = 4
41
- STRING = [MAJOR, MINOR, TINY].join(".")
42
- end
43
-
44
- # This is the exception that is raised if you try to scan a
45
- # directory tree with too many entries. By default, a ceiling of
46
- # 10,000 entries is enforced, but you can change that number via
47
- # the +ceiling+ parameter to FuzzyFileFinder.new.
48
- class TooManyEntries < RuntimeError; end
49
-
50
- # Used internally to represent a run of characters within a
51
- # match. This is used to build the highlighted version of
52
- # a file name.
53
- class CharacterRun < Struct.new(:string, :inside) #:nodoc:
54
- def to_s
55
- if inside
56
- "(#{string})"
57
- else
58
- string
59
- end
60
- end
61
- end
62
-
63
- # Used internally to represent a file within the directory tree.
64
- class FileSystemEntry #:nodoc:
65
- attr_reader :parent
66
- attr_reader :name
67
-
68
- def initialize(parent, name)
69
- @parent = parent
70
- @name = name
71
- end
72
-
73
- def path
74
- File.join(parent.name, name)
75
- end
76
- end
77
-
78
- # Used internally to represent a subdirectory within the directory
79
- # tree.
80
- class Directory #:nodoc:
81
- attr_reader :name
82
-
83
- def initialize(name, is_root=false)
84
- @name = name
85
- @is_root = is_root
86
- end
87
-
88
- def root?
89
- is_root
90
- end
91
- end
92
-
93
- # The roots directory trees to search.
94
- attr_reader :roots
95
-
96
- # The list of files beneath all +roots+
97
- attr_reader :files
98
-
99
- # The maximum number of files beneath all +roots+
100
- attr_reader :ceiling
101
-
102
- # The prefix shared by all +roots+.
103
- attr_reader :shared_prefix
104
-
105
- # The list of glob patterns to ignore.
106
- attr_reader :ignores
107
-
108
- # Initializes a new FuzzyFileFinder. This will scan the
109
- # given +directories+, using +ceiling+ as the maximum number
110
- # of entries to scan. If there are more than +ceiling+ entries
111
- # a TooManyEntries exception will be raised.
112
- def initialize(directories=['.'], ceiling=10_000, ignores=nil)
113
- directories = Array(directories)
114
- directories << "." if directories.empty?
115
-
116
- # expand any paths with ~
117
- root_dirnames = directories.map { |d| File.expand_path(d) }.select { |d| File.directory?(d) }.uniq
118
-
119
- @roots = root_dirnames.map { |d| Directory.new(d, true) }
120
- @shared_prefix = determine_shared_prefix
121
- @shared_prefix_re = Regexp.new("^#{Regexp.escape(shared_prefix)}" + (shared_prefix.empty? ? "" : "/"))
122
-
123
- @files = []
124
- @ceiling = ceiling
125
-
126
- @ignores = Array(ignores)
127
-
128
- rescan!
129
- end
130
-
131
- # Rescans the subtree. If the directory contents every change,
132
- # you'll need to call this to force the finder to be aware of
133
- # the changes.
134
- def rescan!
135
- @files.clear
136
- roots.each { |root| follow_tree(root) }
137
- end
138
-
139
- # Takes the given +pattern+ (which must be a string) and searches
140
- # all files beneath +root+, yielding each match.
141
- #
142
- # +pattern+ is interpreted thus:
143
- #
144
- # * "foo" : look for any file with the characters 'f', 'o', and 'o'
145
- # in its basename (discounting directory names). The characters
146
- # must be in that order.
147
- # * "foo/bar" : look for any file with the characters 'b', 'a',
148
- # and 'r' in its basename (discounting directory names). Also,
149
- # any successful match must also have at least one directory
150
- # element matching the characters 'f', 'o', and 'o' (in that
151
- # order.
152
- # * "foo/bar/baz" : same as "foo/bar", but matching two
153
- # directory elements in addition to a file name of "baz".
154
- #
155
- # Each yielded match will be a hash containing the following keys:
156
- #
157
- # * :path refers to the full path to the file
158
- # * :directory refers to the directory of the file
159
- # * :name refers to the name of the file (without directory)
160
- # * :highlighted_directory refers to the directory of the file with
161
- # matches highlighted in parentheses.
162
- # * :highlighted_name refers to the name of the file with matches
163
- # highlighted in parentheses
164
- # * :highlighted_path refers to the full path of the file with
165
- # matches highlighted in parentheses
166
- # * :abbr refers to an abbreviated form of :highlighted_path, where
167
- # path segments without matches are compressed to just their first
168
- # character.
169
- # * :score refers to a value between 0 and 1 indicating how closely
170
- # the file matches the given pattern. A score of 1 means the
171
- # pattern matches the file exactly.
172
- def search(pattern, &block)
173
- pattern.strip!
174
- path_parts = pattern.split("/")
175
- path_parts.push "" if pattern[-1,1] == "/"
176
-
177
- file_name_part = path_parts.pop || ""
178
-
179
- if path_parts.any?
180
- path_regex_raw = "^(.*?)" + path_parts.map { |part| make_pattern(part) }.join("(.*?/.*?)") + "(.*?)$"
181
- path_regex = Regexp.new(path_regex_raw, Regexp::IGNORECASE)
182
- end
183
-
184
- file_regex_raw = "^(.*?)" << make_pattern(file_name_part) << "(.*)$"
185
- file_regex = Regexp.new(file_regex_raw, Regexp::IGNORECASE)
186
-
187
- path_matches = {}
188
- files.each do |file|
189
- path_match = match_path(file.parent, path_matches, path_regex, path_parts.length)
190
- next if path_match[:missed]
191
-
192
- match_file(file, file_regex, path_match, &block)
193
- end
194
- end
195
-
196
- # Takes the given +pattern+ (which must be a string, formatted as
197
- # described in #search), and returns up to +max+ matches in an
198
- # Array. If +max+ is nil, all matches will be returned.
199
- def find(pattern, max=nil)
200
- results = []
201
- search(pattern) do |match|
202
- results << match
203
- break if max && results.length >= max
204
- end
205
- return results
206
- end
207
-
208
- # Displays the finder object in a sane, non-explosive manner.
209
- def inspect #:nodoc:
210
- "#<%s:0x%x roots=%s, files=%d>" % [self.class.name, object_id, roots.map { |r| r.name.inspect }.join(", "), files.length]
211
- end
212
-
213
- private
214
-
215
- # Recursively scans +directory+ and all files and subdirectories
216
- # beneath it, depth-first.
217
- def follow_tree(directory)
218
- Dir.entries(directory.name).each do |entry|
219
- next if entry[0,1] == "."
220
- raise TooManyEntries if files.length > ceiling
221
-
222
- full = File.join(directory.name, entry)
223
-
224
- if File.directory?(full)
225
- follow_tree(Directory.new(full))
226
- elsif !ignore?(full.sub(@shared_prefix_re, ""))
227
- files.push(FileSystemEntry.new(directory, entry))
228
- end
229
- end
230
- end
231
-
232
- # Returns +true+ if the given name matches any of the ignore
233
- # patterns.
234
- def ignore?(name)
235
- ignores.any? { |pattern| File.fnmatch(pattern, name) }
236
- end
237
-
238
- # Takes the given pattern string "foo" and converts it to a new
239
- # string "(f)([^/]*?)(o)([^/]*?)(o)" that can be used to create
240
- # a regular expression.
241
- def make_pattern(pattern)
242
- pattern = pattern.split(//)
243
- pattern << "" if pattern.empty?
244
-
245
- pattern.inject("") do |regex, character|
246
- regex << "([^/]*?)" if regex.length > 0
247
- regex << "(" << Regexp.escape(character) << ")"
248
- end
249
- end
250
-
251
- # Given a MatchData object +match+ and a number of "inside"
252
- # segments to support, compute both the match score and the
253
- # highlighted match string. The "inside segments" refers to how
254
- # many patterns were matched in this one match. For a file name,
255
- # this will always be one. For directories, it will be one for
256
- # each directory segment in the original pattern.
257
- def build_match_result(match, inside_segments)
258
- runs = []
259
- inside_chars = total_chars = 0
260
- match.captures.each_with_index do |capture, index|
261
- if capture.length > 0
262
- # odd-numbered captures are matches inside the pattern.
263
- # even-numbered captures are matches between the pattern's elements.
264
- inside = index % 2 != 0
265
-
266
- total_chars += capture.gsub(%r(/), "").length # ignore '/' delimiters
267
- inside_chars += capture.length if inside
268
-
269
- if runs.last && runs.last.inside == inside
270
- runs.last.string << capture
271
- else
272
- runs << CharacterRun.new(capture, inside)
273
- end
274
- end
275
- end
276
-
277
- # Determine the score of this match.
278
- # 1. fewer "inside runs" (runs corresponding to the original pattern)
279
- # is better.
280
- # 2. better coverage of the actual path name is better
281
-
282
- inside_runs = runs.select { |r| r.inside }
283
- run_ratio = inside_runs.length.zero? ? 1 : inside_segments / inside_runs.length.to_f
284
-
285
- char_ratio = total_chars.zero? ? 1 : inside_chars.to_f / total_chars
286
-
287
- score = run_ratio * char_ratio
288
-
289
- return { :score => score, :result => runs.join }
290
- end
291
-
292
- # Match the given path against the regex, caching the result in +path_matches+.
293
- # If +path+ is already cached in the path_matches cache, just return the cached
294
- # value.
295
- def match_path(path, path_matches, path_regex, path_segments)
296
- return path_matches[path] if path_matches.key?(path)
297
-
298
- name_with_slash = path.name + "/" # add a trailing slash for matching the prefix
299
- matchable_name = name_with_slash.sub(@shared_prefix_re, "")
300
- matchable_name.chop! # kill the trailing slash
301
-
302
- if path_regex
303
- match = matchable_name.match(path_regex)
304
-
305
- path_matches[path] =
306
- match && build_match_result(match, path_segments) ||
307
- { :score => 1, :result => matchable_name, :missed => true }
308
- else
309
- path_matches[path] = { :score => 1, :result => matchable_name }
310
- end
311
- end
312
-
313
- # Match +file+ against +file_regex+. If it matches, yield the match
314
- # metadata to the block.
315
- def match_file(file, file_regex, path_match, &block)
316
- if file_match = file.name.match(file_regex)
317
- match_result = build_match_result(file_match, 1)
318
- full_match_result = path_match[:result].empty? ? match_result[:result] : File.join(path_match[:result], match_result[:result])
319
- shortened_path = path_match[:result].gsub(/[^\/]+/) { |m| m.index("(") ? m : m[0,1] }
320
- abbr = shortened_path.empty? ? match_result[:result] : File.join(shortened_path, match_result[:result])
321
-
322
- result = { :path => file.path,
323
- :abbr => abbr,
324
- :directory => file.parent.name,
325
- :name => file.name,
326
- :highlighted_directory => path_match[:result],
327
- :highlighted_name => match_result[:result],
328
- :highlighted_path => full_match_result,
329
- :score => path_match[:score] * match_result[:score] }
330
- yield result
331
- end
332
- end
333
-
334
- def determine_shared_prefix
335
- # the common case: if there is only a single root, then the entire
336
- # name of the root is the shared prefix.
337
- return roots.first.name if roots.length == 1
338
-
339
- split_roots = roots.map { |root| root.name.split(%r{/}) }
340
- segments = split_roots.map { |root| root.length }.max
341
- master = split_roots.pop
342
-
343
- segments.times do |segment|
344
- if !split_roots.all? { |root| root[segment] == master[segment] }
345
- return master[0,segment].join("/")
346
- end
347
- end
348
-
349
- # shouldn't ever get here, since we uniq the root list before
350
- # calling this method, but if we do, somehow...
351
- return roots.first.name
352
- end
353
- end
@@ -1,32 +0,0 @@
1
- class Curses::Window
2
- def puts( string = "" )
3
- addstr( string + "\n" )
4
- end
5
-
6
- # setpos, but with some boundary checks
7
- def setpos_( y, x )
8
- $diakonos.debugLog "setpos: y < 0 (#{y})" if y < 0
9
- $diakonos.debugLog "setpos: x < 0 (#{x})" if x < 0
10
- $diakonos.debugLog "setpos: y > lines (#{y})" if y > Curses::lines
11
- $diakonos.debugLog "setpos: x > cols (#{x})" if x > Curses::cols
12
- setpos( y, x )
13
- end
14
-
15
- def addstr_( string )
16
- x = curx
17
- y = cury
18
- x2 = curx + string.length
19
-
20
- if y < 0 or x < 0 or y > Curses::lines or x > Curses::cols or x2 < 0 or x2 > Curses::cols
21
- begin
22
- raise Exception
23
- rescue Exception => e
24
- $diakonos.debugLog e.backtrace[ 1 ]
25
- $diakonos.debugLog e.backtrace[ 2 ]
26
- end
27
- end
28
-
29
- addstr( string )
30
- end
31
- end
32
-
@@ -1,53 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'test/unit'
4
- require 'diakonos'
5
-
6
- class TC_Buffer < Test::Unit::TestCase
7
- SAMPLE_FILE = File.dirname( File.expand_path( __FILE__ ) ) + '/sample-file.rb'
8
-
9
- def setup
10
- @d = Diakonos::Diakonos.new [ '-e', 'quit', '--test', ]
11
- @d.start
12
- end
13
-
14
- def teardown
15
- system "reset"
16
- end
17
-
18
- def test_selected_text
19
- @d.openFile( SAMPLE_FILE )
20
- b = Diakonos::Buffer.new( @d, SAMPLE_FILE, SAMPLE_FILE )
21
- @d.anchorSelection
22
- @d.cursorDown
23
- @d.cursorDown
24
- @d.cursorDown
25
- @d.copySelection
26
- assert_equal(
27
- [
28
- "#!/usr/bin/env ruby",
29
- "",
30
- "# This is only a sample file used in the tests.",
31
- ""
32
- ],
33
- @d.clipboard.clip
34
- )
35
- end
36
-
37
- def test_replace
38
- @d.openFile SAMPLE_FILE
39
- b = Diakonos::Buffer.new( @d, SAMPLE_FILE, SAMPLE_FILE )
40
- b.find( [ /only/ ], :direction => :down, :replacement => "\\2", :auto_choice => Diakonos::CHOICE_YES_AND_STOP )
41
- assert_equal "# This is a sample file used in the tests.", b[ 2 ]
42
- b.find( [ /\bx\b/ ], :direction => :down, :replacement => "\\0_", :auto_choice => Diakonos::CHOICE_YES_AND_STOP )
43
- assert_equal " @x_ = 1", b[ 6 ]
44
- b.find( [ /\b(y)\b/ ], :direction => :down, :replacement => "\\1_", :auto_choice => Diakonos::CHOICE_YES_AND_STOP )
45
- assert_equal " @y_ = 2", b[ 7 ]
46
- b.find( [ /puts (\w+)/ ], :direction => :down, :replacement => "print \\1", :auto_choice => Diakonos::CHOICE_YES_AND_STOP )
47
- assert_equal " print x", b[ 11 ]
48
- b.find( [ /puts (\w+)/ ], :direction => :down, :replacement => "puts \\1, \\1, \\1", :auto_choice => Diakonos::CHOICE_YES_AND_STOP )
49
- assert_equal " puts y, y, y", b[ 12 ]
50
- b.find( [ /Sample\.(\w+)/ ], :direction => :down, :replacement => "\\1\\\\\\1", :auto_choice => Diakonos::CHOICE_YES_AND_STOP )
51
- assert_equal "s = new\\new", b[ 16 ]
52
- end
53
- end