@ -6011,47 +6011,51 @@ fn replay_macro(cx: &mut Context) {
}
fn goto_word ( cx : & mut Context ) {
jump_to_word ( cx , Movement ::Move )
let ranges = generate_viewport_token_ranges ( cx ) ;
prompt_for_label ( cx , ranges , | cx , range | {
let ( view , doc ) = current ! ( cx . editor ) ;
doc . set_selection ( view . id , range . with_direction ( Direction ::Forward ) . into ( ) ) ;
} )
}
fn extend_to_word ( cx : & mut Context ) {
jump_to_word ( cx , Movement ::Extend )
let ranges = generate_viewport_token_ranges ( cx ) ;
prompt_for_label ( cx , ranges , | cx , range | {
let ( view , doc ) = current ! ( cx . editor ) ;
let primary_selection = doc . selection ( view . id ) . primary ( ) ;
let anchor = if range . anchor < range . head {
let from = primary_selection . from ( ) ;
if range . anchor < from {
range . anchor
} else {
from
}
} else {
let to = primary_selection . to ( ) ;
if range . anchor > to {
range . anchor
} else {
to
}
} ;
let range = Range ::new ( anchor , range . head ) ;
doc . set_selection ( view . id , range . into ( ) ) ;
} )
}
fn jump_to_label ( cx : & mut Context , labels : Vec < Range > , behaviour : Movement ) {
let doc = doc ! ( cx . editor ) ;
let alphabet = & cx . editor . config ( ) . jump_label_alphabet ;
if labels . is_empty ( ) {
return ;
}
let alphabet_char = | i | {
let mut res = Tendril ::new ( ) ;
res . push ( alphabet [ i ] ) ;
res
} ;
/// Displays 2-character labels on the ranges provided, and runs the given
/// callback when the user types one of labels.
fn prompt_for_label (
cx : & mut Context ,
label_ranges : Vec < Range > ,
on_label_typed_callback : impl FnOnce ( & mut Context , Range ) + ' static ,
) {
display_labels ( cx , & label_ranges ) ;
// Add label for each jump candidate to the View as virtual text.
let text = doc . text ( ) . slice ( .. ) ;
let mut overlays : Vec < _ > = labels
. iter ( )
. enumerate ( )
. flat_map ( | ( i , range ) | {
[
Overlay ::new ( range . from ( ) , alphabet_char ( i / alphabet . len ( ) ) ) ,
Overlay ::new (
graphemes ::next_grapheme_boundary ( text , range . from ( ) ) ,
alphabet_char ( i % alphabet . len ( ) ) ,
) ,
]
} )
. collect ( ) ;
overlays . sort_unstable_by_key ( | overlay | overlay . char_idx ) ;
let ( view , doc ) = current ! ( cx . editor ) ;
doc . set_jump_labels ( view . id , overlays ) ;
// Accept two characters matching a visible label. Jump to the candidate
// for that label if it exists.
let primary_selection = doc . selection ( view . id ) . primary ( ) ;
let view = view . id ;
let doc = doc . id ( ) ;
cx . on_next_key ( move | cx , event | {
@ -6065,7 +6069,7 @@ fn jump_to_label(cx: &mut Context, labels: Vec<Range>, behaviour: Movement) {
} ;
let outer = i * alphabet . len ( ) ;
// Bail if the given character cannot be a jump label.
if outer > label s. len ( ) {
if outer > label _range s. len ( ) {
doc_mut ! ( cx . editor , & doc ) . remove_jump_labels ( view ) ;
return ;
}
@ -6078,34 +6082,47 @@ fn jump_to_label(cx: &mut Context, labels: Vec<Range>, behaviour: Movement) {
else {
return ;
} ;
if let Some ( mut range ) = labels . get ( outer + inner ) . copied ( ) {
range = if behaviour = = Movement ::Extend {
let anchor = if range . anchor < range . head {
let from = primary_selection . from ( ) ;
if range . anchor < from {
range . anchor
} else {
from
}
} else {
let to = primary_selection . to ( ) ;
if range . anchor > to {
range . anchor
} else {
to
}
} ;
Range ::new ( anchor , range . head )
} else {
range . with_direction ( Direction ::Forward )
} ;
doc_mut ! ( cx . editor , & doc ) . set_selection ( view , range . into ( ) ) ;
if let Some ( range ) = label_ranges . get ( outer + inner ) . copied ( ) {
on_label_typed_callback ( cx , range ) ;
}
} ) ;
} ) ;
}
fn jump_to_word ( cx : & mut Context , behaviour : Movement ) {
/// Displays 2-letter labels on the ranges provided.
fn display_labels ( cx : & mut Context , label_ranges : & [ Range ] ) {
let doc = doc ! ( cx . editor ) ;
let alphabet = & cx . editor . config ( ) . jump_label_alphabet ;
if label_ranges . is_empty ( ) {
return ;
}
let alphabet_char = | i | {
let mut res = Tendril ::new ( ) ;
res . push ( alphabet [ i ] ) ;
res
} ;
// Add label for each jump candidate to the View as virtual text.
let text = doc . text ( ) . slice ( .. ) ;
let mut overlays : Vec < _ > = label_ranges
. iter ( )
. enumerate ( )
. flat_map ( | ( i , range ) | {
[
Overlay ::new ( range . from ( ) , alphabet_char ( i / alphabet . len ( ) ) ) ,
Overlay ::new (
graphemes ::next_grapheme_boundary ( text , range . from ( ) ) ,
alphabet_char ( i % alphabet . len ( ) ) ,
) ,
]
} )
. collect ( ) ;
overlays . sort_unstable_by_key ( | overlay | overlay . char_idx ) ;
let ( view , doc ) = current ! ( cx . editor ) ;
doc . set_jump_labels ( view . id , overlays ) ;
}
fn generate_viewport_token_ranges ( cx : & mut Context ) -> Vec < Range > {
// Calculate the jump candidates: ranges for any visible words with two or
// more characters.
let alphabet = & cx . editor . config ( ) . jump_label_alphabet ;
@ -6192,5 +6209,5 @@ fn jump_to_word(cx: &mut Context, behaviour: Movement) {
break ;
}
}
jump_to_label( cx , words, behaviour )
words
}