Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite318b6b

Browse files
first draft of incremental search (ctrl-r/s)
1 parentfc1cf63 commite318b6b

File tree

3 files changed

+68
-15
lines changed

3 files changed

+68
-15
lines changed

‎bpython/curtsiesfrontend/interaction.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def has_focus(self):
5151
returnself.in_promptorself.in_confirmorself.waiting_for_refresh
5252

5353
defmessage(self,msg):
54+
"""Sets a temporary message"""
5455
self.message_start_time=time.time()
5556
self._message=msg
5657
self.refresh_request(time.time()+self.message_time)

‎bpython/curtsiesfrontend/repl.py‎

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -298,16 +298,19 @@ def smarter_request_reload(desc):
298298
self.stdin=FakeStdin(self.coderunner,self,self.edit_keys)
299299

300300
self.request_paint_to_clear_screen=False# next paint should clear screen
301-
self.last_events= [None]*50
302-
self.presentation_mode=False
303-
self.paste_mode=False
304-
self.current_match=None
305-
self.list_win_visible=False
306-
self.watching_files=False
301+
self.last_events= [None]*50# some commands act differently based on the prev event
302+
# this list doesn't include instances of event.Event,
303+
# only keypress-type events (no refresh screen events etc.)
304+
self.presentation_mode=False# displays prev events in a column on the right hand side
305+
self.paste_mode=False# currently processing a paste event
306+
self.current_match=None# currently tab-selected autocompletion suggestion
307+
self.list_win_visible=False# whether the infobox (suggestions, docstring) is visible
308+
self.watching_files=False# auto reloading turned on
309+
self.special_mode=None# 'reverse_incremental_search' and 'incremental_search'
307310

308311
self.original_modules=sys.modules.keys()
309312

310-
self.width=None# will both be set by a window resize event
313+
self.width=None
311314
self.height=None
312315

313316
self.status_bar.message(banner)
@@ -460,6 +463,12 @@ def process_key_event(self, e):
460463
self.down_one_line()
461464
elifein ("<Ctrl-d>",):
462465
self.on_control_d()
466+
elifein ("<Ctrl-r>",):
467+
self.incremental_search(reverse=True)
468+
elifein ("<Ctrl-s>",):
469+
self.incremental_search()
470+
elifein ("<BACKSPACE>",'<Ctrl-h>')andself.special_mode:
471+
self.add_to_incremental_search(self,backspace=True)
463472
elifeinself.edit_keys.cut_buffer_edits:
464473
self.readline_kill(e)
465474
elifeinself.edit_keys.simple_edits:
@@ -507,6 +516,21 @@ def process_key_event(self, e):
507516
else:
508517
self.add_normal_character(e)
509518

519+
defincremental_search(self,reverse=False):
520+
ifself.special_mode==None:
521+
current_line=''
522+
ifreverse:
523+
self.special_mode='reverse_incremental_search'
524+
else:
525+
self.special_mode='incremental_search'
526+
else:
527+
self._set_current_line(self.rl_history.back(False,search=True)
528+
ifreverseelse
529+
self.rl_history.forward(False,search=True),
530+
reset_rl_history=False,clear_special_mode=False)
531+
self._set_cursor_offset(len(self.current_line),reset_rl_history=False,
532+
clear_special_mode=False)
533+
510534
defreadline_kill(self,e):
511535
func=self.edit_keys[e]
512536
self.cursor_offset,self.current_line,cut=func(self.cursor_offset,self.current_line)
@@ -659,14 +683,35 @@ def toggle_file_watch(self):
659683
defadd_normal_character(self,char):
660684
iflen(char)>1oris_nop(char):
661685
return
662-
self.current_line= (self.current_line[:self.cursor_offset]+
663-
char+
664-
self.current_line[self.cursor_offset:])
665-
self.cursor_offset+=1
686+
ifself.special_mode=='reverse_incremental_search':
687+
self.add_to_incremental_search(char)
688+
else:
689+
self.current_line= (self.current_line[:self.cursor_offset]+
690+
char+
691+
self.current_line[self.cursor_offset:])
692+
self.cursor_offset+=1
666693
ifself.config.cli_trim_promptsandself.current_line.startswith(self.ps1):
667694
self.current_line=self.current_line[4:]
668695
self.cursor_offset=max(0,self.cursor_offset-4)
669696

697+
defadd_to_incremental_search(self,char=None,backspace=False):
698+
ifcharisNoneandnotbackspace:
699+
raiseValueError("must provide a char or set backspace to True")
700+
saved_line=self.rl_history.saved_line
701+
ifbackspace:
702+
saved_line=saved_line[:-1]
703+
else:
704+
saved_line+=char
705+
self.update_completion()
706+
self.rl_history.reset()
707+
self.rl_history.enter(saved_line)
708+
ifself.special_mode=='reverse_incremental_search':
709+
self.incremental_search(reverse=True)
710+
elifself.special_mode=='incremental_search':
711+
self.incremental_search()
712+
else:
713+
raiseValueError('add_to_incremental_search should only be called in a special mode')
714+
670715
defupdate_completion(self,tab=False):
671716
"""Update visible docstring and matches, and possibly hide/show completion box"""
672717
#Update autocomplete info; self.matches_iter and self.argspec
@@ -866,6 +911,9 @@ def display_buffer_lines(self):
866911
@property
867912
defdisplay_line_with_prompt(self):
868913
"""colored line with prompt"""
914+
ifself.special_mode=='reverse_incremental_search':
915+
returnfunc_for_letter(self.config.color_scheme['prompt'])(
916+
'(reverse-i-search)`%s\': '% (self.rl_history.saved_line,))+self.current_line_formatted
869917
return (func_for_letter(self.config.color_scheme['prompt'])(self.ps1)
870918
ifself.doneelse
871919
func_for_letter(self.config.color_scheme['prompt_more'])(self.ps2))+self.current_line_formatted
@@ -1085,21 +1133,25 @@ def __repr__(self):
10851133

10861134
def_get_current_line(self):
10871135
returnself._current_line
1088-
def_set_current_line(self,line,update_completion=True,reset_rl_history=True):
1136+
def_set_current_line(self,line,update_completion=True,reset_rl_history=True,clear_special_mode=True):
10891137
self._current_line=line
10901138
ifupdate_completion:
10911139
self.update_completion()
10921140
ifreset_rl_history:
10931141
self.rl_history.reset()
1142+
ifclear_special_mode:
1143+
self.special_mode=None
10941144
current_line=property(_get_current_line,_set_current_line,None,
10951145
"The current line")
10961146
def_get_cursor_offset(self):
10971147
returnself._cursor_offset
1098-
def_set_cursor_offset(self,offset,update_completion=True,reset_rl_history=True):
1148+
def_set_cursor_offset(self,offset,update_completion=True,reset_rl_history=True,clear_special_mode=True):
10991149
ifupdate_completion:
11001150
self.update_completion()
11011151
ifreset_rl_history:
11021152
self.rl_history.reset()
1153+
ifclear_special_mode:
1154+
self.special_mode=None
11031155
self._cursor_offset=offset
11041156
self.update_completion()
11051157
cursor_offset=property(_get_cursor_offset,_set_cursor_offset,None,

‎bpython/test/test_curtsies_painting.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ def test_startup(self):
3838

3939
deftest_enter_text(self):
4040
[self.repl.add_normal_character(c)forcin'1 + 1']
41-
screen=fsarray([cyan('>>> ')+bold(green('1')+cyan(' ')+
42-
yellow('+')+cyan(' ')+green('1')),cyan('Welcome to')])
41+
screen=fsarray([cyan('>>> ')+bold(blue('1')+cyan(' ')+
42+
yellow('+')+cyan(' ')+green('1')),cyan('welcome')])
4343
self.assert_paint(screen, (0,9))
4444

4545
deftest_run_line(self):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp