@ -3870,7 +3870,7 @@ pub mod insert {
. and_then ( | ap | {
. and_then ( | ap | {
auto_pairs ::hook_insert ( text , range , c , ap )
auto_pairs ::hook_insert ( text , range , c , ap )
. map ( | ( change , range ) | ( change , Some ( range ) ) )
. map ( | ( change , range ) | ( change , Some ( range ) ) )
. or ( Some ( insert_char ( * range , c ) ) )
. or _else ( | | Some ( insert_char ( * range , c ) ) )
} )
} )
. unwrap_or_else ( | | insert_char ( * range , c ) )
. unwrap_or_else ( | | insert_char ( * range , c ) )
} ) ;
} ) ;
@ -4047,33 +4047,26 @@ pub mod insert {
doc . apply ( & transaction , view . id ) ;
doc . apply ( & transaction , view . id ) ;
}
}
pub fn delete_char_backward ( cx : & mut Context ) {
fn dedent ( doc : & Document , range : & Range ) -> Option < Deletion > {
let count = cx . count ( ) ;
let ( view , doc ) = current_ref ! ( cx . editor ) ;
let text = doc . text ( ) . slice ( .. ) ;
let text = doc . text ( ) . slice ( .. ) ;
let tab_width = doc . tab_width ( ) ;
let indent_width = doc . indent_width ( ) ;
let auto_pairs = doc . auto_pairs ( cx . editor ) ;
let transaction = Transaction ::delete_by_and_with_selection (
doc . text ( ) ,
doc . selection ( view . id ) ,
| range | {
let pos = range . cursor ( text ) ;
let pos = range . cursor ( text ) ;
if pos = = 0 {
return ( ( pos , pos ) , None ) ;
}
let line_start_pos = text . line_to_char ( range . cursor_line ( text ) ) ;
let line_start_pos = text . line_to_char ( range . cursor_line ( text ) ) ;
// consider to delete by indent level if all characters before `pos` are indent units.
// consider to delete by indent level if all characters before `pos` are indent units.
let fragment = Cow ::from ( text . slice ( line_start_pos .. pos ) ) ;
let fragment = Cow ::from ( text . slice ( line_start_pos .. pos ) ) ;
if ! fragment . is_empty ( ) & & fragment . chars ( ) . all ( | ch | ch = = ' ' | | ch = = '\t' ) {
if fragment . is_empty ( ) | | ! fragment . chars ( ) . all ( | ch | ch = = ' ' | | ch = = '\t' ) {
return None ;
}
if text . get_char ( pos . saturating_sub ( 1 ) ) = = Some ( '\t' ) {
if text . get_char ( pos . saturating_sub ( 1 ) ) = = Some ( '\t' ) {
// fast path, delete one char
// fast path, delete one char
(
return Some ( ( graphemes ::nth_prev_grapheme_boundary ( text , pos , 1 ) , pos ) ) ;
( graphemes ::nth_prev_grapheme_boundary ( text , pos , 1 ) , pos ) ,
}
None ,
)
let tab_width = doc . tab_width ( ) ;
} else {
let indent_width = doc . indent_width ( ) ;
let width : usize = fragment
let width : usize = fragment
. chars ( )
. chars ( )
. map ( | ch | {
. map ( | ch | {
@ -4086,12 +4079,18 @@ pub mod insert {
}
}
} )
} )
. sum ( ) ;
. sum ( ) ;
let mut drop = width % indent_width ; // round down to nearest unit
// round down to nearest unit
let mut drop = width % indent_width ;
// if it's already at a unit, consume a whole unit
if drop = = 0 {
if drop = = 0 {
drop = indent_width
drop = indent_width
} ; // if it's already at a unit, consume a whole unit
} ;
let mut chars = fragment . chars ( ) . rev ( ) ;
let mut chars = fragment . chars ( ) . rev ( ) ;
let mut start = pos ;
let mut start = pos ;
for _ in 0 .. drop {
for _ in 0 .. drop {
// delete up to `drop` spaces
// delete up to `drop` spaces
match chars . next ( ) {
match chars . next ( ) {
@ -4099,43 +4098,45 @@ pub mod insert {
_ = > break ,
_ = > break ,
}
}
}
}
( ( start , pos ) , None ) // delete!
Some ( ( start , pos ) ) // delete!
}
}
} else {
match (
pub fn delete_char_backward ( cx : & mut Context ) {
text . get_char ( pos . saturating_sub ( 1 ) ) ,
let count = cx . count ( ) ;
text . get_char ( pos ) ,
let ( view , doc ) = current_ref ! ( cx . editor ) ;
auto_pairs ,
let text = doc . text ( ) . slice ( .. ) ;
) {
( Some ( _x ) , Some ( _y ) , Some ( ap ) )
let transaction = Transaction ::delete_by_and_with_selection (
if range . is_single_grapheme ( text )
doc . text ( ) ,
& & ap . get ( _x ) . is_some ( )
doc . selection ( view . id ) ,
& & ap . get ( _x ) . unwrap ( ) . open = = _x
| range | {
& & ap . get ( _x ) . unwrap ( ) . close = = _y = >
let pos = range . cursor ( text ) ;
// delete both autopaired characters
{
log ::debug ! ( "cursor: {}, len: {}" , pos , text . len_chars ( ) ) ;
(
(
if pos = = 0 {
graphemes ::nth_prev_grapheme_boundary ( text , pos , count ) ,
return ( ( pos , pos ) , None ) ;
graphemes ::nth_next_grapheme_boundary ( text , pos , count ) ,
) ,
None ,
)
}
}
_ = >
// delete 1 char
dedent ( doc , range )
{
. map ( | dedent | ( dedent , None ) )
. or_else ( | | {
auto_pairs ::hook_delete ( doc . text ( ) , range , doc . auto_pairs ( cx . editor ) ? )
. map ( | ( delete , new_range ) | ( delete , Some ( new_range ) ) )
} )
. unwrap_or_else ( | | {
(
(
( graphemes ::nth_prev_grapheme_boundary ( text , pos , count ) , pos ) ,
( graphemes ::nth_prev_grapheme_boundary ( text , pos , count ) , pos ) ,
None ,
None ,
)
)
}
} )
}
}
} ,
} ,
) ;
) ;
let ( view , doc ) = current ! ( cx . editor ) ;
log ::debug ! ( "delete_char_backward transaction: {:?}" , transaction ) ;
let doc = doc_mut ! ( cx . editor , & doc . id ( ) ) ;
doc . apply ( & transaction , view . id ) ;
doc . apply ( & transaction , view . id ) ;
}
}