Skip to content

Commit f93fcf7

Browse files
authored
Merge pull request #8 from metaflow/misc
Misc fixes from @metaflow. - Fixed some typos - Can double click on search results to take you to line number - More context in status line - Default prompt shows `file:* case:yes` - Corrected quoting bug - Corrected Windows path handling bugs - File paths relative to project See #8 for full context.
2 parents 5b350fd + cc6828f commit f93fcf7

14 files changed

+150
-50
lines changed

Code Search Results.YAML-tmLanguage

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ patterns:
1212

1313
- match: '^ +([0-9]+) '
1414
captures:
15-
'1': {name: constant.numeric.line-number.cearch}
15+
'1': {name: constant.numeric.line-number.csearch}
1616

1717
- match: '^ +([0-9]+):'
1818
captures:

Code Search Results.hidden-tmLanguage

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<key>1</key>
2727
<dict>
2828
<key>name</key>
29-
<string>constant.numeric.line-number.cearch</string>
29+
<string>constant.numeric.line-number.csearch</string>
3030
</dict>
3131
</dict>
3232
<key>match</key>

Default (Linux).sublime-mousemap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"button": "button1", "count": 2,
4+
"press_command": "drag_select",
5+
"press_args": {"by": "words"},
6+
"command": "double_click_callback"
7+
},
8+
]

Default (OSX).sublime-mousemap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"button": "button1", "count": 2,
4+
"press_command": "drag_select",
5+
"press_args": {"by": "words"},
6+
"command": "double_click_callback"
7+
},
8+
]

Default (Windows).sublime-mousemap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"button": "button1", "count": 2,
4+
"press_command": "drag_select",
5+
"press_args": {"by": "words"},
6+
"command": "double_click_callback"
7+
},
8+
]

Default.sublime-commands

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
"command": "csearch"
55
},
66
{
7-
"caption": "Code Search Index",
7+
"caption": "Code Search: Refresh Index",
88
"command": "cindex"
99
},
1010
{
11-
"caption": "Code Search Index Project",
11+
"caption": "Code Search: Create New Index from Project Settings",
1212
"command": "cindex",
1313
"args": {
1414
"index_project": true

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ specific `YetAnotherCodeSearch.sublime-settings` file. See the default file
107107
for configuration options. Both are easily found via
108108
*Preferences > Package Settings > YetAnotherCodeSearch*.
109109

110+
To add keyboard shortcut open Preferences > Key Bindings - User and add
111+
something like `{ "keys": ["alt+ctrl+shift+f"], "command": "csearch" }`.
112+
110113
### Project Settings
111114

112115
You can specify an index file to use for the project by editing the project

cindex.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def run(self, index_project=False):
6464
try:
6565
s = settings.get_project_settings(
6666
self.window.project_data(),
67+
self.window.project_file_name(),
6768
index_project_folders=index_project)
6869
_CindexListThread(self,
6970
path_cindex=s.cindex_path,
@@ -143,6 +144,8 @@ def _start_indexing(self):
143144
cmd.append('-reset')
144145
cmd.extend(self._paths_to_index)
145146
proc = self._get_proc(cmd)
147+
overall_start = time.perf_counter()
148+
total_count = 0
146149
start = time.time()
147150
count = 0
148151
for line in iter(proc.stdout.readline, b''):
@@ -153,9 +156,13 @@ def _start_indexing(self):
153156
tick = time.time()
154157
if tick - start > .1:
155158
self._listener.on_files_processed(count)
159+
total_count += count
156160
count = 0
157161
start = tick
162+
total_count += count
158163
self._listener.on_files_processed(count)
164+
print('Code Search: indexed {0} files in {1:.3f}s'.format(
165+
total_count, time.perf_counter() - overall_start))
159166
proc.stdout.close()
160167
retcode = proc.poll()
161168
if retcode:

csearch.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import functools
66
import operator
77
import os
8+
import platform
9+
import re
810
import subprocess
911
import threading
1012

@@ -31,7 +33,7 @@ class CsearchCommand(sublime_plugin.WindowCommand, _CsearchListener):
3133
def __init__(self, *args, **kwargs):
3234
super(CsearchCommand, self).__init__(*args, **kwargs)
3335
self._is_running = False
34-
self._last_search = ''
36+
self._last_search = 'file:* case:yes "'
3537

3638
def run(self, query=None):
3739
"""Runs the search command.
@@ -73,7 +75,8 @@ def _on_search(self, result):
7375
view=view, erase=True)
7476
view.set_status('YetAnotherCodeSearch', 'Searching...')
7577
try:
76-
s = settings.get_project_settings(self.window.project_data())
78+
s = settings.get_project_settings(self.window.project_data(),
79+
self.window.project_file_name())
7780
_CsearchThread(parser.parse_query(result), self,
7881
path_csearch=s.csearch_path,
7982
index_filename=s.index_filename).start()
@@ -143,6 +146,23 @@ def on_finished(self, output, err=None):
143146
functools.partial(self._finish, output, matches, err=err))
144147

145148

149+
def fix_windows_output(output):
150+
"""Normalize file paths in csearch output on windows platform."""
151+
152+
result = []
153+
# replace ntpaths to posix
154+
r = re.compile(r"^([^:]*):([^:]*):([^:]*):(.*)$")
155+
for line in output.splitlines():
156+
m = r.match(line)
157+
if m:
158+
line = '/{0}{1}:{2}:{3}'.format(m.group(1),
159+
m.group(2).replace('\\', '/'),
160+
m.group(3),
161+
m.group(4))
162+
result.append(line)
163+
return '\n'.join(result)
164+
165+
146166
class _CsearchThread(threading.Thread):
147167
"""Runs the csearch command in a thread."""
148168

@@ -182,7 +202,10 @@ def _do_search(self):
182202
error = subprocess.CalledProcessError(retcode, cmd)
183203
error.output = stderr
184204
raise error
185-
return output.decode('utf-8')
205+
u8 = output.decode('utf-8')
206+
if platform.system() == 'Windows':
207+
return fix_windows_output(u8)
208+
return u8
186209

187210

188211
class CodeSearchResultsGoToFileCommand(sublime_plugin.WindowCommand):
@@ -217,3 +240,8 @@ def run(self):
217240
self.window.open_file('{0}:{1}:{2}'.format(filename, linenum, col),
218241
sublime.ENCODED_POSITION)
219242
# TODO(pope): Consider highlighting the match
243+
244+
245+
class DoubleClickCallback(sublime_plugin.WindowCommand):
246+
def run(self):
247+
self.window.run_command("code_search_results_go_to_file")

parser.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,17 @@ def _search_quote_state(lex):
5151
Returns:
5252
The next lex state.
5353
"""
54-
# TODO(pope): Handle the error case when we try to leave without seeing a
55-
# closing quote.
5654
while True:
5755
lex.acceptRunIgnoring('\\"')
5856
c = lex.next()
5957
if c == '\\':
6058
lex.next() # Advance over whatever is being escaped.
61-
else:
59+
elif c == '"':
60+
lex.emit('quote')
61+
break
62+
else: # end
63+
lex.emitValue('quote', lex.curstr() + '"')
6264
break
63-
lex.emit('quote')
6465
return _search_text_state
6566

6667

@@ -184,12 +185,22 @@ def hasstr(self):
184185
return self._pos > self._start
185186

186187
def emit(self, tokType):
187-
"""Emit appends the current string to the list of tokens.
188+
"""Emit appends the current string to the list of tokens and advances
189+
position.
190+
191+
Args:
192+
tokType: The token type describing the current string.
193+
"""
194+
self.emitValue(tokType, self.curstr())
195+
196+
def emitValue(self, tokType, value):
197+
"""Emit appends value to the list of tokens and advances position.
188198
189199
Args:
190200
tokType: The token type describing the current string.
201+
value: value of token.
191202
"""
192-
self._tokens.append((tokType, self.curstr()))
203+
self._tokens.append((tokType, value))
193204
self._start = self._pos
194205

195206
def ignore(self):
@@ -344,8 +355,10 @@ def parse_query(text):
344355
try:
345356
while True:
346357
(tokType, tokValue) = next(tokens)
347-
if tokType in ('text', 'quote'):
358+
if tokType == 'text':
348359
res.query.append(tokValue)
360+
elif tokType == 'quote':
361+
res.query.append(tokValue[1:-1])
349362
elif tokType == 'flag':
350363
flag = tokValue.lower()
351364
(ignore_type, value) = next(tokens)
@@ -355,7 +368,8 @@ def parse_query(text):
355368
else:
356369
res.case = True
357370
elif flag == 'file':
358-
res.file = value
371+
if value != '*':
372+
res.file = value
359373
else:
360374
raise Exception('Unsupported flag value: {0}'.format(flag))
361375
else:

0 commit comments

Comments
 (0)