@@ -14,6 +14,7 @@ use crate::cli::vi::cursor::{Cursor, MotionCommand, MotionError};
1414use crate :: cli:: vi:: word:: { current_bigword, BigWordIter } ;
1515use crate :: parse:: word_parser:: parse_word;
1616use crate :: pattern:: { FilenamePattern , HistoryPattern } ;
17+ use crate :: shell:: history:: History ;
1718use crate :: shell:: Shell ;
1819use crate :: wordexp:: expand_word;
1920use crate :: wordexp:: pathname:: glob;
@@ -297,23 +298,57 @@ pub struct ViEditor {
297298 /// 0 means the `edit_line`, from 1 on
298299 /// its an index into the history starting
299300 /// from the most recent command
300- current_command_in_history : usize ,
301+ current_history_command : usize ,
301302}
302303
303304impl ViEditor {
304305 fn edit_current_line ( & mut self , shell : & Shell ) -> & mut Vec < u8 > {
305- if self . current_command_in_history != 0 {
306+ if self . current_history_command != 0 {
306307 self . edit_line = shell
307308 . history
308- . get_reverse ( self . current_command_in_history - 1 )
309+ . get_reverse ( self . current_history_command - 1 )
309310 . unwrap ( )
310311 . as_bytes ( )
311312 . to_vec ( ) ;
312- self . current_command_in_history = 0 ;
313+ self . current_history_command = 0 ;
313314 }
314315 & mut self . edit_line
315316 }
316317
318+ fn set_current_history_command ( & mut self , index : usize ) {
319+ if self . current_history_command == 0 {
320+ self . saved_edit_line_position = self . cursor . position ;
321+ }
322+ self . current_history_command = index;
323+ self . cursor . position = 0 ;
324+ }
325+
326+ fn find_in_history (
327+ & self ,
328+ history : & History ,
329+ pattern : & HistoryPattern ,
330+ reverse : bool ,
331+ ) -> Option < usize > {
332+ if reverse {
333+ if self . current_history_command == 0 {
334+ return None ;
335+ }
336+ let skipped = history. entries_count ( ) - self . current_history_command + 1 ;
337+ history
338+ . entries ( )
339+ . skip ( skipped)
340+ . position ( |e| pattern. matches ( & e. command ) )
341+ . map ( |i| history. entries_count ( ) - i - skipped)
342+ } else {
343+ history
344+ . entries ( )
345+ . rev ( )
346+ . skip ( self . current_history_command )
347+ . position ( |e| pattern. matches ( & e. command ) )
348+ . map ( |i| self . current_history_command + i + 1 )
349+ }
350+ }
351+
317352 fn execute_command (
318353 & mut self ,
319354 command : Command ,
@@ -333,7 +368,7 @@ impl ViEditor {
333368 result. push ( b'\n' ) ;
334369 self . mode = EditorMode :: Insert ;
335370 self . cursor . position = 0 ;
336- self . current_command_in_history = 0 ;
371+ self . current_history_command = 0 ;
337372 self . edit_line . clear ( ) ;
338373 return Ok ( Action :: Execute ( result) ) ;
339374 }
@@ -630,59 +665,50 @@ impl ViEditor {
630665 CommandOp :: UndoLastCommand => { }
631666 CommandOp :: UndoAll => { }
632667 CommandOp :: PreviousShellCommand => {
633- if self . current_command_in_history == 0 {
668+ if self . current_history_command == 0 {
634669 self . saved_edit_line_position = self . cursor . position ;
635670 self . cursor . position = 0 ;
636671 }
637672 let number = command. count . unwrap_or ( 1 ) ;
638- if self . current_command_in_history + number > shell. history . entries_count ( ) {
673+ if self . current_history_command + number > shell. history . entries_count ( ) {
639674 return Err ( CommandError ) ;
640675 }
641- self . current_command_in_history += number;
676+ self . current_history_command += number;
642677 self . cursor . position = 0 ;
643678 }
644679 CommandOp :: NextShellCommand => {
645680 let number = command. count . unwrap_or ( 1 ) ;
646- if number > self . current_command_in_history {
647- self . current_command_in_history = 0 ;
681+ if number > self . current_history_command {
682+ self . current_history_command = 0 ;
648683 return Err ( CommandError ) ;
649684 }
650- self . current_command_in_history -= number;
651- if self . current_command_in_history == 0 {
685+ self . current_history_command -= number;
686+ if self . current_history_command == 0 {
652687 self . cursor . position = self . saved_edit_line_position ;
653688 } else {
654689 self . cursor . position = 0 ;
655690 }
656691 }
657692 CommandOp :: OldestShellCommand => {
658693 let number = command. count . unwrap_or ( shell. history . entries_count ( ) ) ;
659- if self . current_command_in_history == 0 {
694+ if self . current_history_command == 0 {
660695 self . saved_edit_line_position = self . cursor . position ;
661696 }
662- if number > self . current_command_in_history {
697+ if number > self . current_history_command {
663698 return Err ( CommandError ) ;
664699 }
665- self . current_command_in_history = number;
700+ self . current_history_command = number;
666701 self . cursor . position = 0 ;
667702 }
668703 CommandOp :: SearchPattern { pattern, reverse } => {
669704 let history_pattern = HistoryPattern :: new ( pattern) . map_err ( |_| CommandError ) ?;
670- let result = shell. history . find_pattern (
671- & history_pattern,
672- self . current_command_in_history ,
673- reverse,
674- ) ;
705+ let result = self . find_in_history ( & shell. history , & history_pattern, reverse) ;
675706 self . last_search = Some ( LastSearch {
676707 pattern : history_pattern,
677708 reverse,
678709 } ) ;
679710 if let Some ( index) = result {
680- let index = index + 1 ;
681- if self . current_command_in_history == 0 {
682- self . saved_edit_line_position = self . cursor . position ;
683- }
684- self . current_command_in_history = index;
685- self . cursor . position = 0 ;
711+ self . set_current_history_command ( index)
686712 } else {
687713 return Err ( CommandError ) ;
688714 }
@@ -694,34 +720,23 @@ impl ViEditor {
694720 } else {
695721 last_search. reverse
696722 } ;
697- let result = shell. history . find_pattern (
698- & last_search. pattern ,
699- self . current_command_in_history ,
700- reverse,
701- ) ;
702- if let Some ( index) = result {
703- let index = index + 1 ;
704- if self . current_command_in_history == 0 {
705- self . saved_edit_line_position = self . cursor . position ;
706- }
707- self . current_command_in_history = index;
708- self . cursor . position = 0 ;
709- } else {
710- return Err ( CommandError ) ;
711- }
723+ let index = self
724+ . find_in_history ( & shell. history , & last_search. pattern , reverse)
725+ . ok_or ( CommandError ) ?;
726+ self . set_current_history_command ( index) ;
712727 }
713728 CommandOp :: Move ( _) => unreachable ! ( ) ,
714729 }
715730 Ok ( Action :: None )
716731 }
717732
718733 pub fn current_line < ' a > ( & ' a self , shell : & ' a Shell ) -> & ' a [ u8 ] {
719- if self . current_command_in_history == 0 {
734+ if self . current_history_command == 0 {
720735 & self . edit_line
721736 } else {
722737 shell
723738 . history
724- . get_reverse ( self . current_command_in_history - 1 )
739+ . get_reverse ( self . current_history_command - 1 )
725740 . unwrap ( )
726741 . as_bytes ( )
727742 }
@@ -819,7 +834,7 @@ impl Default for ViEditor {
819834 last_nonmotion_command : None ,
820835 last_search : None ,
821836 save_buffer : Vec :: new ( ) ,
822- current_command_in_history : 0 ,
837+ current_history_command : 0 ,
823838 }
824839 }
825840}
0 commit comments