commit 4893fc8: [Minor] Update replxx library

Vsevolod Stakhov vsevolod at highsecure.ru
Tue Aug 24 14:56:04 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-08-24 15:47:07 +0100
URL: https://github.com/rspamd/rspamd/commit/4893fc8dc5b54968be8949fe3b45fc7326cbb90f

[Minor] Update replxx library

---
 contrib/replxx/include/replxx.h      | 142 +++++-
 contrib/replxx/include/replxx.hxx    | 174 ++++++-
 contrib/replxx/src/conversion.cxx    |  88 ++--
 contrib/replxx/src/conversion.hxx    |  21 +-
 contrib/replxx/src/escape.cxx        |  36 +-
 contrib/replxx/src/history.cxx       | 390 ++++++++++++---
 contrib/replxx/src/history.hxx       | 134 ++++--
 contrib/replxx/src/killring.hxx      |   6 +-
 contrib/replxx/src/prompt.cxx        |  64 ++-
 contrib/replxx/src/prompt.hxx        |  12 +-
 contrib/replxx/src/replxx.cxx        | 159 ++++++-
 contrib/replxx/src/replxx_impl.cxx   | 896 +++++++++++++++++++++++------------
 contrib/replxx/src/replxx_impl.hxx   |  73 ++-
 contrib/replxx/src/unicodestring.hxx |  28 +-
 contrib/replxx/src/utf8string.hxx    |  33 +-
 contrib/replxx/src/util.cxx          |  30 +-
 contrib/replxx/src/util.hxx          |   6 +-
 contrib/replxx/src/windows.cxx       |  38 +-
 contrib/replxx/src/windows.hxx       |   2 +-
 19 files changed, 1692 insertions(+), 640 deletions(-)

diff --git a/contrib/replxx/include/replxx.h b/contrib/replxx/include/replxx.h
index 4bdad5127..5127ac2ae 100644
--- a/contrib/replxx/include/replxx.h
+++ b/contrib/replxx/include/replxx.h
@@ -126,6 +126,8 @@ enum { REPLXX_KEY_F22          = REPLXX_KEY_F21       + 1 };
 enum { REPLXX_KEY_F23          = REPLXX_KEY_F22       + 1 };
 enum { REPLXX_KEY_F24          = REPLXX_KEY_F23       + 1 };
 enum { REPLXX_KEY_MOUSE        = REPLXX_KEY_F24       + 1 };
+enum { REPLXX_KEY_PASTE_START  = REPLXX_KEY_MOUSE     + 1 };
+enum { REPLXX_KEY_PASTE_FINISH = REPLXX_KEY_PASTE_START + 1 };
 
 #define REPLXX_KEY_SHIFT( key )   ( ( key ) | REPLXX_KEY_BASE_SHIFT )
 #define REPLXX_KEY_CONTROL( key ) ( ( key ) | REPLXX_KEY_BASE_CONTROL )
@@ -139,19 +141,25 @@ enum { REPLXX_KEY_ENTER        = REPLXX_KEY_CONTROL( 'M' ) };
  */
 typedef enum {
 	REPLXX_ACTION_INSERT_CHARACTER,
+	REPLXX_ACTION_NEW_LINE,
 	REPLXX_ACTION_DELETE_CHARACTER_UNDER_CURSOR,
 	REPLXX_ACTION_DELETE_CHARACTER_LEFT_OF_CURSOR,
 	REPLXX_ACTION_KILL_TO_END_OF_LINE,
 	REPLXX_ACTION_KILL_TO_BEGINING_OF_LINE,
 	REPLXX_ACTION_KILL_TO_END_OF_WORD,
 	REPLXX_ACTION_KILL_TO_BEGINING_OF_WORD,
+	REPLXX_ACTION_KILL_TO_END_OF_SUBWORD,
+	REPLXX_ACTION_KILL_TO_BEGINING_OF_SUBWORD,
 	REPLXX_ACTION_KILL_TO_WHITESPACE_ON_LEFT,
 	REPLXX_ACTION_YANK,
 	REPLXX_ACTION_YANK_CYCLE,
+	REPLXX_ACTION_YANK_LAST_ARG,
 	REPLXX_ACTION_MOVE_CURSOR_TO_BEGINING_OF_LINE,
 	REPLXX_ACTION_MOVE_CURSOR_TO_END_OF_LINE,
 	REPLXX_ACTION_MOVE_CURSOR_ONE_WORD_LEFT,
 	REPLXX_ACTION_MOVE_CURSOR_ONE_WORD_RIGHT,
+	REPLXX_ACTION_MOVE_CURSOR_ONE_SUBWORD_LEFT,
+	REPLXX_ACTION_MOVE_CURSOR_ONE_SUBWORD_RIGHT,
 	REPLXX_ACTION_MOVE_CURSOR_LEFT,
 	REPLXX_ACTION_MOVE_CURSOR_RIGHT,
 	REPLXX_ACTION_HISTORY_NEXT,
@@ -165,12 +173,16 @@ typedef enum {
 	REPLXX_ACTION_CAPITALIZE_WORD,
 	REPLXX_ACTION_LOWERCASE_WORD,
 	REPLXX_ACTION_UPPERCASE_WORD,
+	REPLXX_ACTION_CAPITALIZE_SUBWORD,
+	REPLXX_ACTION_LOWERCASE_SUBWORD,
+	REPLXX_ACTION_UPPERCASE_SUBWORD,
 	REPLXX_ACTION_TRANSPOSE_CHARACTERS,
 	REPLXX_ACTION_TOGGLE_OVERWRITE_MODE,
 #ifndef _WIN32
 	REPLXX_ACTION_VERBATIM_INSERT,
 	REPLXX_ACTION_SUSPEND,
 #endif
+	REPLXX_ACTION_BRACKETED_PASTE,
 	REPLXX_ACTION_CLEAR_SCREEN,
 	REPLXX_ACTION_CLEAR_SELF,
 	REPLXX_ACTION_REPAINT,
@@ -196,12 +208,17 @@ typedef struct ReplxxStateTag {
 } ReplxxState;
 
 typedef struct Replxx Replxx;
+typedef struct ReplxxHistoryScan ReplxxHistoryScan;
+typedef struct ReplxxHistoryEntryTag {
+	char const* timestamp;
+	char const* text;
+} ReplxxHistoryEntry;
 
-/*! \brief Create Replxx library resouce holder.
+/*! \brief Create Replxx library resource holder.
  *
- * Use replxx_end() to free resoiurce acquired with this function.
+ * Use replxx_end() to free resources acquired with this function.
  *
- * \return Replxx library resouce holder.
+ * \return Replxx library resource holder.
  */
 REPLXX_IMPEXP Replxx* replxx_init( void );
 
@@ -211,6 +228,28 @@ REPLXX_IMPEXP Replxx* replxx_init( void );
  */
 REPLXX_IMPEXP void replxx_end( Replxx* replxx );
 
+/*! \brief Line modification callback type definition.
+ *
+ * User can observe and modify line contents (and cursor position)
+ * in response to changes to both introduced by the user through
+ * normal interactions.
+ *
+ * When callback returns Replxx updates current line content
+ * and current cursor position to the ones updated by the callback.
+ *
+ * \param line[in,out] - a R/W reference to an UTF-8 encoded input entered by the user so far.
+ * \param cursorPosition[in,out] - a R/W reference to current cursor position.
+ * \param userData - pointer to opaque user data block.
+ */
+typedef void (replxx_modify_callback_t)(char** input, int* contextLen, void* userData);
+
+/*! \brief Register modify callback.
+ *
+ * \param fn - user defined callback function.
+ * \param userData - pointer to opaque user data block to be passed into each invocation of the callback.
+ */
+REPLXX_IMPEXP void replxx_set_modify_callback( Replxx*, replxx_modify_callback_t* fn, void* userData );
+
 /*! \brief Highlighter callback type definition.
  *
  * If user want to have colorful input she must simply install highlighter callback.
@@ -247,8 +286,8 @@ typedef struct replxx_completions replxx_completions;
  * input == "if ( obj.me"
  * contextLen == 2 (depending on \e replxx_set_word_break_characters())
  *
- * Client application is free to update \e contextLen to be 6 (or any orther non-negative
- * number not greated than the number of code points in input) if it makes better sense
+ * Client application is free to update \e contextLen to be 6 (or any other non-negative
+ * number not greater than the number of code points in input) if it makes better sense
  * for given client application semantics.
  *
  * \param input - UTF-8 encoded input entered by the user until current cursor position.
@@ -292,8 +331,8 @@ typedef struct replxx_hints replxx_hints;
  * input == "if ( obj.me"
  * contextLen == 2 (depending on \e replxx_set_word_break_characters())
  *
- * Client application is free to update \e contextLen to be 6 (or any orther non-negative
- * number not greated than the number of code points in input) if it makes better sense
+ * Client application is free to update \e contextLen to be 6 (or any other non-negative
+ * number not greater than the number of code points in input) if it makes better sense
  * for given client application semantics.
  *
  * \param input - UTF-8 encoded input entered by the user until current cursor position.
@@ -314,7 +353,7 @@ REPLXX_IMPEXP void replxx_set_hint_callback( Replxx*, replxx_hint_callback_t* fn
 /*! \brief Key press handler type definition.
  *
  * \param code - the key code replxx got from terminal.
- * \return Decition on how should input() behave after this key handler returns.
+ * \return Decision on how should input() behave after this key handler returns.
  */
 typedef ReplxxActionResult (key_press_handler_t)( int code, void* userData );
 
@@ -326,6 +365,8 @@ typedef ReplxxActionResult (key_press_handler_t)( int code, void* userData );
 REPLXX_IMPEXP void replxx_add_hint( replxx_hints* hints, const char* str );
 
 /*! \brief Read line of user input.
+ *
+ * Returned pointer is managed by the library and is not to be freed in the client.
  *
  * \param prompt - prompt to be displayed before getting user input.
  * \return An UTF-8 encoded input given by the user (or nullptr on EOF).
@@ -356,11 +397,17 @@ REPLXX_IMPEXP void replxx_set_state( Replxx*, ReplxxState* state );
  *
  * \param fmt - printf style format.
  */
-#ifdef __GNUC__
-__attribute__((format(printf, 2, 3)))
-#endif
 REPLXX_IMPEXP int replxx_print( Replxx*, char const* fmt, ... );
 
+/*! \brief Prints a char array with the given length to standard output.
+ *
+ * \copydetails print
+ *
+ * \param str - The char array to print.
+ * \param length - The length of the array.
+ */
+REPLXX_IMPEXP int replxx_write( Replxx*, char const* str, int length );
+
 /*! \brief Schedule an emulated key press event.
  *
  * \param code - key press code to be emulated.
@@ -385,6 +432,19 @@ REPLXX_IMPEXP ReplxxActionResult replxx_invoke( Replxx*, ReplxxAction action, in
  */
 REPLXX_IMPEXP void replxx_bind_key( Replxx*, int code, key_press_handler_t handler, void* userData );
 
+/*! \brief Bind internal `replxx` action (by name) to handle given key-press event.
+ *
+ * Action names are the same as unique part of names of ReplxxAction enumerations
+ * but in lower case, e.g.: an action for recalling previous history line
+ * is \e REPLXX_ACTION_HISTORY_PREVIOUS so action name to be used in this
+ * interface for the same effect is "history_previous".
+ *
+ * \param code - handle this key-press event with following handler.
+ * \param actionName - name of internal action to be invoked on key press.
+ * \return -1 if invalid action name was used, 0 otherwise.
+ */
+int replxx_bind_key_internal( Replxx*, int code, char const* actionName );
+
 REPLXX_IMPEXP void replxx_set_preload_buffer( Replxx*, const char* preloadText );
 
 REPLXX_IMPEXP void replxx_history_add( Replxx*, const char* line );
@@ -430,6 +490,23 @@ REPLXX_IMPEXP void replxx_set_complete_on_empty( Replxx*, int val );
  */
 REPLXX_IMPEXP void replxx_set_beep_on_ambiguous_completion( Replxx*, int val );
 
+/*! \brief Set complete next/complete previous behavior.
+ *
+ * COMPLETE_NEXT/COMPLETE_PREVIOUS actions have two modes of operations,
+ * in case when a partial completion is possible complete only partial part (`false` setting)
+ * or complete first proposed completion fully (`true` setting).
+ * The default is to complete fully (a `true` setting - complete immediately).
+ *
+ * \param val - complete immediately.
+ */
+REPLXX_IMPEXP void replxx_set_immediate_completion( Replxx*, int val );
+
+/*! \brief Set history duplicate entries behaviour.
+ *
+ * \param val - should history contain only unique entries?
+ */
+REPLXX_IMPEXP void replxx_set_unique_history( Replxx*, int val );
+
 /*! \brief Disable output coloring.
  *
  * \param val - if set to non-zero disable output colors.
@@ -439,15 +516,56 @@ REPLXX_IMPEXP void replxx_set_no_color( Replxx*, int val );
 /*! \brief Set maximum number of entries in history list.
  */
 REPLXX_IMPEXP void replxx_set_max_history_size( Replxx*, int len );
-REPLXX_IMPEXP char const* replxx_history_line( Replxx*, int index );
+REPLXX_IMPEXP ReplxxHistoryScan* replxx_history_scan_start( Replxx* );
+REPLXX_IMPEXP void replxx_history_scan_stop( Replxx*, ReplxxHistoryScan* );
+REPLXX_IMPEXP int replxx_history_scan_next( Replxx*, ReplxxHistoryScan*, ReplxxHistoryEntry* );
+
+/*! \brief Synchronize REPL's history with given file.
+ *
+ * Synchronizing means loading existing history from given file,
+ * merging it with current history sorted by timestamps,
+ * saving merged version to given file,
+ * keeping merged version as current REPL's history.
+ *
+ * This call is an equivalent of calling:
+ * replxx_history_save( rx, "some-file" );
+ * replxx_history_load( rx, "some-file" );
+ *
+ * \param filename - a path to the file with which REPL's current history should be synchronized.
+ * \return 0 iff history file was successfully created, -1 otherwise.
+ */
+REPLXX_IMPEXP int replxx_history_sync( Replxx*, const char* filename );
+
+/*! \brief Save REPL's history into given file.
+ *
+ * Saving means loading existing history from given file,
+ * merging it with current history sorted by timestamps,
+ * saving merged version to given file,
+ * keeping original (NOT merged) version as current REPL's history.
+ *
+ * \param filename - a path to the file where REPL's history should be saved.
+ * \return 0 iff history file was successfully created, -1 otherwise.
+ */
 REPLXX_IMPEXP int replxx_history_save( Replxx*, const char* filename );
+
+/*! \brief Load REPL's history from given file.
+ *
+ * \param filename - a path to the file which contains REPL's history that should be loaded.
+ * \return 0 iff history file was successfully opened, -1 otherwise.
+ */
 REPLXX_IMPEXP int replxx_history_load( Replxx*, const char* filename );
+
+/*! \brief Clear REPL's in-memory history.
+ */
+REPLXX_IMPEXP void replxx_history_clear( Replxx* );
 REPLXX_IMPEXP void replxx_clear_screen( Replxx* );
 #ifdef __REPLXX_DEBUG__
 void replxx_debug_dump_print_codes(void);
 #endif
 /* the following is extension to the original linenoise API */
 REPLXX_IMPEXP int replxx_install_window_change_handler( Replxx* );
+REPLXX_IMPEXP void replxx_enable_bracketed_paste( Replxx* );
+REPLXX_IMPEXP void replxx_disable_bracketed_paste( Replxx* );
 
 #ifdef __cplusplus
 }
diff --git a/contrib/replxx/include/replxx.hxx b/contrib/replxx/include/replxx.hxx
index 1401ea27c..5362312e5 100644
--- a/contrib/replxx/include/replxx.hxx
+++ b/contrib/replxx/include/replxx.hxx
@@ -131,6 +131,8 @@ public:
 		static char32_t const F23          = F22       + 1;
 		static char32_t const F24          = F23       + 1;
 		static char32_t const MOUSE        = F24       + 1;
+		static char32_t const PASTE_START  = MOUSE     + 1;
+		static char32_t const PASTE_FINISH = PASTE_START + 1;
 		static constexpr char32_t shift( char32_t key_ ) {
 			return ( key_ | BASE_SHIFT );
 		}
@@ -148,19 +150,25 @@ public:
 	 */
 	enum class ACTION {
 		INSERT_CHARACTER,
+		NEW_LINE,
 		DELETE_CHARACTER_UNDER_CURSOR,
 		DELETE_CHARACTER_LEFT_OF_CURSOR,
 		KILL_TO_END_OF_LINE,
 		KILL_TO_BEGINING_OF_LINE,
 		KILL_TO_END_OF_WORD,
 		KILL_TO_BEGINING_OF_WORD,
+		KILL_TO_END_OF_SUBWORD,
+		KILL_TO_BEGINING_OF_SUBWORD,
 		KILL_TO_WHITESPACE_ON_LEFT,
 		YANK,
 		YANK_CYCLE,
+		YANK_LAST_ARG,
 		MOVE_CURSOR_TO_BEGINING_OF_LINE,
 		MOVE_CURSOR_TO_END_OF_LINE,
 		MOVE_CURSOR_ONE_WORD_LEFT,
 		MOVE_CURSOR_ONE_WORD_RIGHT,
+		MOVE_CURSOR_ONE_SUBWORD_LEFT,
+		MOVE_CURSOR_ONE_SUBWORD_RIGHT,
 		MOVE_CURSOR_LEFT,
 		MOVE_CURSOR_RIGHT,
 		HISTORY_NEXT,
@@ -174,12 +182,16 @@ public:
 		CAPITALIZE_WORD,
 		LOWERCASE_WORD,
 		UPPERCASE_WORD,
+		CAPITALIZE_SUBWORD,
+		LOWERCASE_SUBWORD,
+		UPPERCASE_SUBWORD,
 		TRANSPOSE_CHARACTERS,
 		TOGGLE_OVERWRITE_MODE,
 #ifndef _WIN32
 		VERBATIM_INSERT,
 		SUSPEND,
 #endif
+		BRACKETED_PASTE,
 		CLEAR_SCREEN,
 		CLEAR_SELF,
 		REPAINT,
@@ -222,8 +234,60 @@ public:
 		}
 	};
 	typedef std::vector<Completion> completions_t;
+	class HistoryEntry {
+		std::string _timestamp;
+		std::string _text;
+	public:
+		HistoryEntry( std::string const& timestamp_, std::string const& text_ )
+			: _timestamp( timestamp_ )
+			, _text( text_ ) {
+		}
+		std::string const& timestamp( void ) const {
+			return ( _timestamp );
+		}
+		std::string const& text( void ) const {
+			return ( _text );
+		}
+	};
+	class HistoryScanImpl;
+	class HistoryScan {
+	public:
+		typedef std::unique_ptr<HistoryScanImpl, void (*)( HistoryScanImpl* )> impl_t;
+	private:
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4251)
+#endif
+		impl_t _impl;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+	public:
+		HistoryScan( impl_t );
+		HistoryScan( HistoryScan&& ) = default;
+		HistoryScan& operator = ( HistoryScan&& ) = default;
+		bool next( void );
+		HistoryEntry const& get( void ) const;
+	private:
+		HistoryScan( HistoryScan const& ) = delete;
+		HistoryScan& operator = ( HistoryScan const& ) = delete;
+	};
 	typedef std::vector<std::string> hints_t;
 
+	/*! \brief Line modification callback type definition.
+	 *
+	 * User can observe and modify line contents (and cursor position)
+	 * in response to changes to both introduced by the user through
+	 * normal interactions.
+	 *
+	 * When callback returns Replxx updates current line content
+	 * and current cursor position to the ones updated by the callback.
+	 *
+	 * \param line[in,out] - a R/W reference to an UTF-8 encoded input entered by the user so far.
+	 * \param cursorPosition[in,out] - a R/W reference to current cursor position.
+	 */
+	typedef std::function<void ( std::string& line, int& cursorPosition )> modify_callback_t;
+
 	/*! \brief Completions callback type definition.
 	 *
 	 * \e contextLen is counted in Unicode code points (not in bytes!).
@@ -234,8 +298,8 @@ public:
 	 * input == "if ( obj.me"
 	 * contextLen == 2 (depending on \e set_word_break_characters())
 	 *
-	 * Client application is free to update \e contextLen to be 6 (or any orther non-negative
-	 * number not greated than the number of code points in input) if it makes better sense
+	 * Client application is free to update \e contextLen to be 6 (or any other non-negative
+	 * number not greater than the number of code points in input) if it makes better sense
 	 * for given client application semantics.
 	 *
 	 * \param input - UTF-8 encoded input entered by the user until current cursor position.
@@ -252,7 +316,7 @@ public:
 	 * displayed user input.
 	 *
 	 * Size of \e colors buffer is equal to number of code points in user \e input
-	 * which will be different from simple `input.lenght()`!
+	 * which will be different from simple `input.length()`!
 	 *
 	 * \param input - an UTF-8 encoded input entered by the user so far.
 	 * \param colors - output buffer for color information.
@@ -269,8 +333,8 @@ public:
 	 * input == "if ( obj.me"
 	 * contextLen == 2 (depending on \e set_word_break_characters())
 	 *
-	 * Client application is free to update \e contextLen to be 6 (or any orther non-negative
-	 * number not greated than the number of code points in input) if it makes better sense
+	 * Client application is free to update \e contextLen to be 6 (or any other non-negative
+	 * number not greater than the number of code points in input) if it makes better sense
 	 * for given client application semantics.
 	 *
 	 * \param input - UTF-8 encoded input entered by the user until current cursor position.
@@ -283,7 +347,7 @@ public:
 	/*! \brief Key press handler type definition.
 	 *
 	 * \param code - the key code replxx got from terminal.
-	 * \return Decition on how should input() behave after this key handler returns.
+	 * \return Decision on how should input() behave after this key handler returns.
 	 */
 	typedef std::function<ACTION_RESULT ( char32_t code )> key_press_handler_t;
 
@@ -307,12 +371,12 @@ public:
 	class ReplxxImpl;
 private:
 	typedef std::unique_ptr<ReplxxImpl, void (*)( ReplxxImpl* )> impl_t;
-#ifdef _WIN32
+#ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4251)
 #endif
 	impl_t _impl;
-#ifdef _WIN32
+#ifdef _MSC_VER
 #pragma warning(pop)
 #endif
 
@@ -321,6 +385,12 @@ public:
 	Replxx( Replxx&& ) = default;
 	Replxx& operator = ( Replxx&& ) = default;
 
+	/*! \brief Register modify callback.
+	 *
+	 * \param fn - user defined callback function.
+	 */
+	void set_modify_callback( modify_callback_t const& fn );
+
 	/*! \brief Register completion callback.
 	 *
 	 * \param fn - user defined callback function.
@@ -340,6 +410,8 @@ public:
 	void set_hint_callback( hint_callback_t const& fn );
 
 	/*! \brief Read line of user input.
+	 *
+	 * Returned pointer is managed by the library and is not to be freed in the client.
 	 *
 	 * \param prompt - prompt to be displayed before getting user input.
 	 * \return An UTF-8 encoded input given by the user (or nullptr on EOF).
@@ -370,11 +442,17 @@ public:
 	 *
 	 * \param fmt - printf style format.
 	 */
-#ifdef __GNUC__
-	__attribute__((format(printf, 2, 3)))
-#endif
 	void print( char const* fmt, ... );
 
+	/*! \brief Prints a char array with the given length to standard output.
+	 *
+	 * \copydetails print
+	 *
+	 * \param str - The char array to print.
+	 * \param length - The length of the array.
+	 */
+	void write( char const* str, int length );
+
 	/*! \brief Schedule an emulated key press event.
 	 *
 	 * \param code - key press code to be emulated.
@@ -398,11 +476,60 @@ public:
 	 */
 	void bind_key( char32_t code, key_press_handler_t handler );
 
+	/*! \brief Bind internal `replxx` action (by name) to handle given key-press event.
+	 *
+	 * Action names are the same as names of Replxx::ACTION enumerations
+	 * but in lower case, e.g.: an action for recalling previous history line
+	 * is \e Replxx::ACTION::HISTORY_PREVIOUS so action name to be used in this
+	 * interface for the same effect is "history_previous".
+	 *
+	 * \param code - handle this key-press event with following handler.
+	 * \param actionName - name of internal action to be invoked on key press.
+	 */
+	void bind_key_internal( char32_t code, char const* actionName );
+
 	void history_add( std::string const& line );
-	int history_save( std::string const& filename );
-	int history_load( std::string const& filename );
+
+	/*! \brief Synchronize REPL's history with given file.
+	 *
+	 * Synchronizing means loading existing history from given file,
+	 * merging it with current history sorted by timestamps,
+	 * saving merged version to given file,
+	 * keeping merged version as current REPL's history.
+	 *
+	 * This call is an equivalent of calling:
+	 * history_save( "some-file" );
+	 * history_load( "some-file" );
+	 *
+	 * \param filename - a path to the file with which REPL's current history should be synchronized.
+	 * \return True iff history file was successfully created.
+	 */
+	bool history_sync( std::string const& filename );
+
+	/*! \brief Save REPL's history into given file.
+	 *
+	 * Saving means loading existing history from given file,
+	 * merging it with current history sorted by timestamps,
+	 * saving merged version to given file,
+	 * keeping original (NOT merged) version as current REPL's history.
+	 *
+	 * \param filename - a path to the file where REPL's history should be saved.
+	 * \return True iff history file was successfully created.
+	 */
+	bool history_save( std::string const& filename );
+
+	/*! \brief Load REPL's history from given file.
+	 *
+	 * \param filename - a path to the file which contains REPL's history that should be loaded.
+	 * \return True iff history file was successfully opened.
+	 */
+	bool history_load( std::string const& filename );
+
+	/*! \brief Clear REPL's in-memory history.
+	 */
+	void history_clear( void );
 	int history_size( void ) const;
-	std::string history_line( int index );
+	HistoryScan history_scan( void ) const;
 
 	void set_preload_buffer( std::string const& preloadText );
 
@@ -446,6 +573,23 @@ public:
 	 */
 	void set_beep_on_ambiguous_completion( bool val );
 
+	/*! \brief Set complete next/complete previous behavior.
+	 *
+	 * COMPLETE_NEXT/COMPLETE_PREVIOUS actions have two modes of operations,
+	 * in case when a partial completion is possible complete only partial part (`false` setting)
+	 * or complete first proposed completion fully (`true` setting).
+	 * The default is to complete fully (a `true` setting - complete immediately).
+	 *
+	 * \param val - complete immediately.
+	 */
+	void set_immediate_completion( bool val );
+
+	/*! \brief Set history duplicate entries behaviour.
+	 *
+	 * \param val - should history contain only unique entries?
+	 */
+	void set_unique_history( bool val );
+
 	/*! \brief Disable output coloring.
 	 *
 	 * \param val - if set to non-zero disable output colors.
@@ -457,6 +601,8 @@ public:
 	void set_max_history_size( int len );
 	void clear_screen( void );
 	int install_window_change_handler( void );
+	void enable_bracketed_paste( void );
+	void disable_bracketed_paste( void );
 
 private:
 	Replxx( Replxx const& ) = delete;
diff --git a/contrib/replxx/src/conversion.cxx b/contrib/replxx/src/conversion.cxx
index ce9bd932b..bcdbe048e 100644
--- a/contrib/replxx/src/conversion.cxx
+++ b/contrib/replxx/src/conversion.cxx
@@ -2,10 +2,7 @@
 #include <string>
 #include <cstring>
 #include <cctype>
-#include <clocale>
-
-#include "unicode/utf8.h"
-
+#include <locale.h>
 
 #include "conversion.hxx"
 
@@ -47,38 +44,20 @@ bool is8BitEncoding( is_8bit_encoding() );
 ConversionResult copyString8to32(char32_t* dst, int dstSize, int& dstCount, const char* src) {
 	ConversionResult res = ConversionResult::conversionOK;
 	if ( ! locale::is8BitEncoding ) {
-		auto sourceStart = reinterpret_cast<const unsigned char*>(src);
-		auto slen = strlen(src);
-		auto targetStart = reinterpret_cast<UChar32*>(dst);
-		int i = 0, j = 0;
-
-		while (i < slen && j < dstSize) {
-			UChar32 uc;
-			auto prev_i = i;
-			U8_NEXT (sourceStart, i, slen, uc);
-
-			if (uc <= 0) {
-				if (U8_IS_LEAD (sourceStart[prev_i])) {
-					auto lead_byte = sourceStart[prev_i];
-					auto trailing_bytes = (((uint8_t)(lead_byte)>=0xc2)+
-							((uint8_t)(lead_byte)>=0xe0)+
-							((uint8_t)(lead_byte)>=0xf0));
-
-					if (trailing_bytes + i > slen) {
-						return ConversionResult::sourceExhausted;
-					}
-				}
-
-				/* Replace with 0xFFFD */
-				uc = 0x0000FFFD;
-			}
-			targetStart[j++] = uc;
-		}
+		const UTF8* sourceStart = reinterpret_cast<const UTF8*>(src);
+		const UTF8* sourceEnd = sourceStart + strlen(src);
+		UTF32* targetStart = reinterpret_cast<UTF32*>(dst);
+		UTF32* targetEnd = targetStart + dstSize;
 
-		dstCount = j;
+		res = ConvertUTF8toUTF32(
+				&sourceStart, sourceEnd, &targetStart, targetEnd, lenientConversion);
 
-		if (j < dstSize) {
-			targetStart[j] = 0;
+		if (res == conversionOK) {
+			dstCount = static_cast<int>( targetStart - reinterpret_cast<UTF32*>( dst ) );
+
+			if (dstCount < dstSize) {
+				*targetStart = 0;
+			}
 		}
 	} else {
 		for ( dstCount = 0; ( dstCount < dstSize ) && src[dstCount]; ++ dstCount ) {
@@ -94,28 +73,22 @@ ConversionResult copyString8to32(char32_t* dst, int dstSize, int& dstCount, cons
 	);
 }
 
-void copyString32to8(
-	char* dst, int dstSize, const char32_t* src, int srcSize, int* dstCount
-) {
+int copyString32to8( char* dst, int dstSize, const char32_t* src, int srcSize ) {
+	int resCount( 0 );
 	if ( ! locale::is8BitEncoding ) {
-		int j = 0;
-		UBool is_error = 0;
-
-		for (auto i = 0; i < srcSize; i ++) {
-			U8_APPEND ((uint8_t *)dst, j, dstSize, src[i], is_error);
-
-			if (is_error) {
-				break;
-			}
-		}
-
-		if (!is_error) {
-			if (dstCount) {
-				*dstCount = j;
*** OUTPUT TRUNCATED, 3484 LINES SKIPPED ***


More information about the Commits mailing list