1 #ifndef REPLXX_HISTORY_HXX_INCLUDED 2 #define REPLXX_HISTORY_HXX_INCLUDED 1 3 4 #include <list> 5 #include <unordered_map> 6 7 #include "unicodestring.hxx" 8 #include "utf8string.hxx" 9 #include "conversion.hxx" 10 #include "util.hxx" 11 12 namespace std { 13 template<> 14 struct hash<replxx::UnicodeString> { operator ()std::hash15 std::size_t operator()( replxx::UnicodeString const& us_ ) const { 16 std::size_t h( 0 ); 17 char32_t const* p( us_.get() ); 18 char32_t const* e( p + us_.length() ); 19 while ( p != e ) { 20 h *= 31; 21 h += *p; 22 ++ p; 23 } 24 return ( h ); 25 } 26 }; 27 } 28 29 namespace replxx { 30 31 class History { 32 public: 33 class Entry { 34 std::string _timestamp; 35 UnicodeString _text; 36 public: Entry(std::string const & timestamp_,UnicodeString const & text_)37 Entry( std::string const& timestamp_, UnicodeString const& text_ ) 38 : _timestamp( timestamp_ ) 39 , _text( text_ ) { 40 } timestamp(void) const41 std::string const& timestamp( void ) const { 42 return ( _timestamp ); 43 } text(void) const44 UnicodeString const& text( void ) const { 45 return ( _text ); 46 } operator <(Entry const & other_) const47 bool operator < ( Entry const& other_ ) const { 48 return ( _timestamp < other_._timestamp ); 49 } 50 }; 51 typedef std::list<Entry> entries_t; 52 typedef std::unordered_map<UnicodeString, entries_t::const_iterator> locations_t; 53 private: 54 entries_t _entries; 55 locations_t _locations; 56 int _maxSize; 57 entries_t::const_iterator _current; 58 entries_t::const_iterator _yankPos; 59 /* 60 * _previous and _recallMostRecent are used to allow 61 * HISTORY_NEXT action (a down-arrow key) to have a special meaning 62 * if invoked after a line from history was accepted without 63 * any modification. 64 * Special meaning is: a down arrow shall jump to the line one 65 * after previously accepted from history. 66 */ 67 entries_t::const_iterator _previous; 68 bool _recallMostRecent; 69 bool _unique; 70 public: 71 History( void ); 72 void add( UnicodeString const& line, std::string const& when = now_ms_str() ); 73 bool save( std::string const& filename ); 74 bool load( std::string const& filename ); 75 void clear( void ); 76 void set_max_size( int len ); set_unique(bool unique_)77 void set_unique( bool unique_ ) { 78 _unique = unique_; 79 remove_duplicates(); 80 } 81 void reset_yank_iterator(); 82 bool next_yank_position( void ); reset_recall_most_recent(void)83 void reset_recall_most_recent( void ) { 84 _recallMostRecent = false; 85 } commit_index(void)86 void commit_index( void ) { 87 _previous = _current; 88 _recallMostRecent = true; 89 } is_empty(void) const90 bool is_empty( void ) const { 91 return ( _entries.empty() ); 92 } 93 void update_last( UnicodeString const& ); 94 void drop_last( void ); 95 bool is_last( void ) const; 96 bool move( bool ); current(void) const97 UnicodeString const& current( void ) const { 98 return ( _current->text() ); 99 } yank_line(void) const100 UnicodeString const& yank_line( void ) const { 101 return ( _yankPos->text() ); 102 } 103 void jump( bool, bool = true ); 104 bool common_prefix_search( UnicodeString const&, int, bool ); size(void) const105 int size( void ) const { 106 return ( static_cast<int>( _entries.size() ) ); 107 } 108 Replxx::HistoryScan::impl_t scan( void ) const; 109 void save_pos( void ); 110 void restore_pos( void ); 111 private: 112 History( History const& ) = delete; 113 History& operator = ( History const& ) = delete; 114 bool move( entries_t::const_iterator&, int, bool = false ) const; 115 entries_t::const_iterator moved( entries_t::const_iterator, int, bool = false ) const; 116 void erase( entries_t::const_iterator ); 117 void trim_to_max_size( void ); 118 void remove_duplicate( UnicodeString const& ); 119 void remove_duplicates( void ); 120 bool do_load( std::string const& ); 121 entries_t::const_iterator last( void ) const; 122 void sort( void ); 123 }; 124 125 class Replxx::HistoryScanImpl { 126 History::entries_t const& _entries; 127 History::entries_t::const_iterator _it; 128 mutable Utf8String _utf8Cache; 129 mutable Replxx::HistoryEntry _entryCache; 130 mutable bool _cacheValid; 131 public: 132 HistoryScanImpl( History::entries_t const& ); 133 bool next( void ); 134 Replxx::HistoryEntry const& get( void ) const; 135 }; 136 137 } 138 139 #endif 140 141