@ -1087,6 +1087,7 @@ fn select_regex(cx: &mut Context) {
cx ,
cx ,
"select:" . into ( ) ,
"select:" . into ( ) ,
Some ( reg ) ,
Some ( reg ) ,
| _input : & str | Vec ::new ( ) ,
move | view , doc , regex , event | {
move | view , doc , regex , event | {
if event ! = PromptEvent ::Update {
if event ! = PromptEvent ::Update {
return ;
return ;
@ -1109,6 +1110,7 @@ fn split_selection(cx: &mut Context) {
cx ,
cx ,
"split:" . into ( ) ,
"split:" . into ( ) ,
Some ( reg ) ,
Some ( reg ) ,
| _input : & str | Vec ::new ( ) ,
move | view , doc , regex , event | {
move | view , doc , regex , event | {
if event ! = PromptEvent ::Update {
if event ! = PromptEvent ::Update {
return ;
return ;
@ -1172,6 +1174,15 @@ fn search_impl(doc: &mut Document, view: &mut View, contents: &str, regex: &Rege
} ;
} ;
}
}
fn search_completions ( cx : & mut Context , reg : Option < char > ) -> Vec < String > {
let mut items = reg
. and_then ( | reg | cx . editor . registers . get ( reg ) )
. map_or ( Vec ::new ( ) , | reg | reg . read ( ) . iter ( ) . take ( 200 ) . collect ( ) ) ;
items . sort_unstable ( ) ;
items . dedup ( ) ;
items . into_iter ( ) . cloned ( ) . collect ( )
}
// TODO: use one function for search vs extend
// TODO: use one function for search vs extend
fn search ( cx : & mut Context ) {
fn search ( cx : & mut Context ) {
let reg = cx . register . unwrap_or ( '/' ) ;
let reg = cx . register . unwrap_or ( '/' ) ;
@ -1182,11 +1193,19 @@ fn search(cx: &mut Context) {
// HAXX: sadly we can't avoid allocating a single string for the whole buffer since we can't
// HAXX: sadly we can't avoid allocating a single string for the whole buffer since we can't
// feed chunks into the regex yet
// feed chunks into the regex yet
let contents = doc . text ( ) . slice ( .. ) . to_string ( ) ;
let contents = doc . text ( ) . slice ( .. ) . to_string ( ) ;
let completions = search_completions ( cx , Some ( reg ) ) ;
let prompt = ui ::regex_prompt (
let prompt = ui ::regex_prompt (
cx ,
cx ,
"search:" . into ( ) ,
"search:" . into ( ) ,
Some ( reg ) ,
Some ( reg ) ,
move | input : & str | {
completions
. iter ( )
. filter ( | comp | comp . starts_with ( input ) )
. map ( | comp | ( 0 .. , std ::borrow ::Cow ::Owned ( comp . clone ( ) ) ) )
. collect ( )
} ,
move | view , doc , regex , event | {
move | view , doc , regex , event | {
if event ! = PromptEvent ::Update {
if event ! = PromptEvent ::Update {
return ;
return ;
@ -1246,10 +1265,19 @@ fn global_search(cx: &mut Context) {
let ( all_matches_sx , all_matches_rx ) =
let ( all_matches_sx , all_matches_rx ) =
tokio ::sync ::mpsc ::unbounded_channel ::< ( usize , PathBuf ) > ( ) ;
tokio ::sync ::mpsc ::unbounded_channel ::< ( usize , PathBuf ) > ( ) ;
let smart_case = cx . editor . config . smart_case ;
let smart_case = cx . editor . config . smart_case ;
let completions = search_completions ( cx , None ) ;
let prompt = ui ::regex_prompt (
let prompt = ui ::regex_prompt (
cx ,
cx ,
"global search:" . into ( ) ,
"global search:" . into ( ) ,
None ,
None ,
move | input : & str | {
completions
. iter ( )
. filter ( | comp | comp . starts_with ( input ) )
. map ( | comp | ( 0 .. , std ::borrow ::Cow ::Owned ( comp . clone ( ) ) ) )
. collect ( )
} ,
move | _view , _doc , regex , event | {
move | _view , _doc , regex , event | {
if event ! = PromptEvent ::Validate {
if event ! = PromptEvent ::Validate {
return ;
return ;
@ -4086,6 +4114,7 @@ fn keep_selections(cx: &mut Context) {
cx ,
cx ,
"keep:" . into ( ) ,
"keep:" . into ( ) ,
Some ( reg ) ,
Some ( reg ) ,
| _input : & str | Vec ::new ( ) ,
move | view , doc , regex , event | {
move | view , doc , regex , event | {
if event ! = PromptEvent ::Update {
if event ! = PromptEvent ::Update {
return ;
return ;