Module: Redcar::DocumentSearch::FindCommandMixin
- Included in:
- FindCommandBase, ReplaceCommandBase
- Defined in:
- plugins/document_search/lib/document_search/commands.rb
Overview
Utilities for extended search commands.
Instance Method Summary (collapse)
-
- (Object) is_valid(query)
Indicates if the query is valid.
-
- (Object) make_literal_query(query, options)
An instance of a search type method: Plain text search.
-
- (Object) make_regex_query(query, options)
An instance of a search type method: Regular expression.
-
- (Object) replace_selection_if_match(doc, start_pos, query, replace)
Replaces the current selection, if it matches the query completely.
-
- (Object) select_next_match(doc, start_pos, query, wrap_around)
Selects the first match of query, starting from the start_pos.
-
- (Object) select_previous_match(doc, search_pos, query, wrap_around)
Selects the match that first precedes the search position.
-
- (Object) select_range(start, stop)
Selects the specified range and scrolls to the start.
-
- (Object) select_range_bytes(start, stop)
Selects the specified byte range, mapping to character indices first.
-
- (Object) selection_byte_offsets
Returns the document selection range as byte offsets, adjusting for multi-byte characters.
Instance Method Details
- (Object) is_valid(query)
Indicates if the query is valid.
8 9 10 |
# File 'plugins/document_search/lib/document_search/commands.rb', line 8 def is_valid(query) query.inspect != "//i" end |
- (Object) make_literal_query(query, options)
An instance of a search type method: Plain text search
18 19 20 |
# File 'plugins/document_search/lib/document_search/commands.rb', line 18 def make_literal_query(query, ) make_regex_query(Regexp.escape(query), ) end |
- (Object) make_regex_query(query, options)
An instance of a search type method: Regular expression
13 14 15 |
# File 'plugins/document_search/lib/document_search/commands.rb', line 13 def make_regex_query(query, ) Regexp.new(query, !.match_case) end |
- (Object) replace_selection_if_match(doc, start_pos, query, replace)
Replaces the current selection, if it matches the query completely.
101 102 103 104 105 106 107 108 109 110 111 |
# File 'plugins/document_search/lib/document_search/commands.rb', line 101 def replace_selection_if_match(doc, start_pos, query, replace) scanner = StringScanner.new(doc.selected_text) scanner.check(query) if (not scanner.matched?) || (scanner.matched_size != doc.selected_text.length) return 0 end matched_text = doc.get_range(start_pos, scanner.matched_size) replacement_text = matched_text.gsub(query, replace) doc.replace(start_pos, scanner.matched_size, replacement_text) replacement_text.length end |
- (Object) select_next_match(doc, start_pos, query, wrap_around)
Selects the first match of query, starting from the start_pos.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'plugins/document_search/lib/document_search/commands.rb', line 41 def select_next_match(doc, start_pos, query, wrap_around) return false unless is_valid(query) scanner = StringScanner.new(doc.get_all_text) scanner.pos = start_pos if not scanner.scan_until(query) if not wrap_around return false end scanner.reset if not scanner.scan_until(query) return false end end selection_pos = scanner.pos - scanner.matched_size select_range_bytes(selection_pos, scanner.pos) true end |
- (Object) select_previous_match(doc, search_pos, query, wrap_around)
Selects the match that first precedes the search position.
The current implementation is brain-dead, but works: the document is scanned from the start up to the search position, retaining the most recent match. Many smarter, but more complicated strategies are possible; the best would be full reversal of the query regex, but that obviously has a lot of tricky aspects to it.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'plugins/document_search/lib/document_search/commands.rb', line 67 def select_previous_match(doc, search_pos, query, wrap_around) return false unless is_valid(query) previous_match = nil scanner = StringScanner.new(doc.get_all_text) scanner.pos = 0 while scanner.scan_until(query) start_pos = scanner.pos - scanner.matched_size if start_pos < search_pos previous_match = [start_pos, scanner.pos] elsif previous_match select_range_bytes(*previous_match) return true elsif not wrap_around return false else break end end # Find the last match in the document. while scanner.scan_until(query) start_pos = scanner.pos - scanner.matched_size previous_match = [start_pos, scanner.pos] end if previous_match select_range_bytes(*previous_match) return true else return false end end |
- (Object) select_range(start, stop)
Selects the specified range and scrolls to the start.
114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'plugins/document_search/lib/document_search/commands.rb', line 114 def select_range(start, stop) line = doc.line_at_offset(start) lineoff = start - doc.offset_at_line(line) if lineoff < doc.smallest_visible_horizontal_index horiz = lineoff else horiz = stop - doc.offset_at_line(line) end doc.set_selection_range(start, stop) doc.scroll_to_line(line) doc.scroll_to_horizontal_offset(horiz) if horiz end |
- (Object) select_range_bytes(start, stop)
Selects the specified byte range, mapping to character indices first.
This method is necessary, because Ruby (1.8) strings really work in terms of bytes, and thus our regex and scanning matches return byte ranges, while the editor view deals in terms of character ranges.
132 133 134 135 136 137 138 139 140 |
# File 'plugins/document_search/lib/document_search/commands.rb', line 132 def select_range_bytes(start, stop) text = doc.get_all_text # Unpack span up to start into array of Unicode chars and count for start_chars. start_chars = text.slice(0, start).unpack('U*').size # Do the same for the span between start and stop, and then use to compute stop_chars. char_span = text.slice(start, stop - start).unpack('U*').size stop_chars = start_chars + char_span select_range(start_chars, stop_chars) end |
- (Object) selection_byte_offsets
Returns the document selection range as byte offsets, adjusting for multi-byte characters.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'plugins/document_search/lib/document_search/commands.rb', line 25 def selection_byte_offsets char_offsets = [doc.cursor_offset, doc.selection_offset] min_char_offset = char_offsets.min max_char_offset = char_offsets.max # For the min_byte_offset, get all document text before the selection, and count the bytes. min_byte_offset = doc.get_range(0, min_char_offset).size # If the selection is non-empty, count the bytes in the selection text, too. max_byte_offset = (min_byte_offset + (max_char_offset > min_char_offset ? doc.get_slice(min_char_offset, max_char_offset).size : 0)) [min_byte_offset, max_byte_offset] end |