/* * Copyright (c) 2017-2018, Marcin Konarski (amok at codestation.org) * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Redis nor the names of its contributors may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef HAVE_REPLXX_REPLXX_IMPL_HXX_INCLUDED #define HAVE_REPLXX_REPLXX_IMPL_HXX_INCLUDED 1 #include #include #include #include #include #include #include #include "replxx.hxx" #include "history.hxx" #include "killring.hxx" #include "utf8string.hxx" #include "prompt.hxx" #include "io.hxx" namespace replxx { class Replxx::ReplxxImpl { public: class Completion { UnicodeString _text; Replxx::Color _color; public: Completion( UnicodeString const& text_, Replxx::Color color_ ) : _text( text_ ) , _color( color_ ) { } Completion( Replxx::Completion const& completion_ ) : _text( completion_.text() ) , _color( completion_.color() ) { } Completion( Completion const& ) = default; Completion& operator = ( Completion const& ) = default; Completion( Completion&& ) = default; Completion& operator = ( Completion&& ) = default; UnicodeString const& text( void ) const { return ( _text ); } Replxx::Color color( void ) const { return ( _color ); } }; typedef std::vector completions_t; typedef std::vector hints_t; typedef std::unique_ptr utf8_buffer_t; typedef std::unique_ptr input_buffer_t; typedef std::vector char_widths_t; typedef std::vector display_t; typedef std::deque key_presses_t; typedef std::deque messages_t; enum class HINT_ACTION { REGENERATE, REPAINT, TRIM, SKIP }; typedef Replxx::ACTION_RESULT ( ReplxxImpl::* key_press_handler_raw_t )( char32_t ); typedef std::unordered_map key_press_handlers_t; private: typedef int long long unsigned action_trait_t; static action_trait_t const NOOP = 0; static action_trait_t const WANT_REFRESH = 1; static action_trait_t const RESET_KILL_ACTION = 2; static action_trait_t const SET_KILL_ACTION = 4; static action_trait_t const DONT_RESET_PREFIX = 8; static action_trait_t const DONT_RESET_COMPLETIONS = 16; private: mutable Utf8String _utf8Buffer; UnicodeString _data; char_widths_t _charWidths; // character widths from mk_wcwidth() display_t _display; int _displayInputLength; UnicodeString _hint; int _pos; // character position in buffer ( 0 <= _pos <= _len ) int _prefix; // prefix length used in common prefix search int _hintSelection; // Currently selected hint. History _history; KillRing _killRing; int _maxHintRows; int _hintDelay; char const* _breakChars; int _completionCountCutoff; bool _overwrite; bool _doubleTabCompletion; bool _completeOnEmpty; bool _beepOnAmbiguousCompletion; bool _noColor; key_press_handlers_t _keyPressHandlers; Terminal _terminal; std::thread::id _currentThread; Prompt _prompt; Replxx::completion_callback_t _completionCallback; Replxx::highlighter_callback_t _highlighterCallback; Replxx::hint_callback_t _hintCallback; key_presses_t _keyPresses; messages_t _messages; completions_t _completions; int _completionContextLength; int _completionSelection; std::string _preloadedBuffer; // used with set_preload_buffer std::string _errorMessage; bool _modifiedState; mutable std::mutex _mutex; public: ReplxxImpl( FILE*, FILE*, FILE* ); void set_completion_callback( Replxx::completion_callback_t const& fn ); void set_highlighter_callback( Replxx::highlighter_callback_t const& fn ); void set_hint_callback( Replxx::hint_callback_t const& fn ); char const* input( std::string const& prompt ); void history_add( std::string const& line ); int history_save( std::string const& filename ); int history_load( std::string const& filename ); std::string history_line( int index ); int history_size( void ) const; void set_preload_buffer(std::string const& preloadText); void set_word_break_characters( char const* wordBreakers ); void set_max_hint_rows( int count ); void set_hint_delay( int milliseconds ); void set_double_tab_completion( bool val ); void set_complete_on_empty( bool val ); void set_beep_on_ambiguous_completion( bool val ); void set_no_color( bool val ); void set_max_history_size( int len ); void set_completion_count_cutoff( int len ); int install_window_change_handler( void ); completions_t call_completer( std::string const& input, int& ) const; hints_t call_hinter( std::string const& input, int&, Replxx::Color& color ) const; void print( char const*, int ); Replxx::ACTION_RESULT clear_screen( char32_t ); void emulate_key_press( char32_t ); Replxx::ACTION_RESULT invoke( Replxx::ACTION, char32_t ); void bind_key( char32_t, Replxx::key_press_handler_t ); Replxx::State get_state( void ) const; void set_state( Replxx::State const& ); private: ReplxxImpl( ReplxxImpl const& ) = delete; ReplxxImpl& operator = ( ReplxxImpl const& ) = delete; private: void preload_puffer( char const* preloadText ); int get_input_line( void ); Replxx::ACTION_RESULT action( action_trait_t, key_press_handler_raw_t const&, char32_t ); Replxx::ACTION_RESULT insert_character( char32_t ); Replxx::ACTION_RESULT go_to_begining_of_line( char32_t ); Replxx::ACTION_RESULT go_to_end_of_line( char32_t ); Replxx::ACTION_RESULT move_one_char_left( char32_t ); Replxx::ACTION_RESULT move_one_char_right( char32_t ); Replxx::ACTION_RESULT move_one_word_left( char32_t ); Replxx::ACTION_RESULT move_one_word_right( char32_t ); Replxx::ACTION_RESULT kill_word_to_left( char32_t ); Replxx::ACTION_RESULT kill_word_to_right( char32_t ); Replxx::ACTION_RESULT kill_to_whitespace_to_left( char32_t ); Replxx::ACTION_RESULT kill_to_begining_of_line( char32_t ); Replxx::ACTION_RESULT kill_to_end_of_line( char32_t ); Replxx::ACTION_RESULT yank( char32_t ); Replxx::ACTION_RESULT yank_cycle( char32_t ); Replxx::ACTION_RESULT capitalize_word( char32_t ); Replxx::ACTION_RESULT lowercase_word( char32_t ); Replxx::ACTION_RESULT uppercase_word( char32_t ); Replxx::ACTION_RESULT transpose_characters( char32_t ); Replxx::ACTION_RESULT abort_line( char32_t ); Replxx::ACTION_RESULT send_eof( char32_t ); Replxx::ACTION_RESULT delete_character( char32_t ); Replxx::ACTION_RESULT backspace_character( char32_t ); Replxx::ACTION_RESULT commit_line( char32_t ); Replxx::ACTION_RESULT history_next( char32_t ); Replxx::ACTION_RESULT history_previous( char32_t ); Replxx::ACTION_RESULT history_move( bool ); Replxx::ACTION_RESULT history_first( char32_t ); Replxx::ACTION_RESULT history_last( char32_t ); Replxx::ACTION_RESULT history_jump( bool ); Replxx::ACTION_RESULT hint_next( char32_t ); Replxx::ACTION_RESULT hint_previous( char32_t ); Replxx::ACTION_RESULT hint_move( bool ); Replxx::ACTION_RESULT toggle_overwrite_mode( char32_t ); #ifndef _WIN32 Replxx::ACTION_RESULT verbatim_insert( char32_t ); Replxx::ACTION_RESULT suspend( char32_t ); #endif Replxx::ACTION_RESULT complete_line( char32_t ); Replxx::ACTION_RESULT complete_next( char32_t ); Replxx::ACTION_RESULT complete_previous( char32_t ); Replxx::ACTION_RESULT complete( bool ); Replxx::ACTION_RESULT incremental_history_search( char32_t startChar ); Replxx::ACTION_RESULT common_prefix_search( char32_t startChar ); char32_t read_char( HINT_ACTION = HINT_ACTION::SKIP ); char const* read_from_stdin( void ); char32_t do_complete_line( bool ); void refresh_line( HINT_ACTION = HINT_ACTION::REGENERATE ); void render( char32_t ); void render( HINT_ACTION ); int handle_hints( HINT_ACTION ); void set_color( Replxx::Color ); int context_length( void ); void clear( void ); void repaint( void ); bool is_word_break_character( char32_t ) const; void dynamicRefresh(Prompt& pi, char32_t* buf32, int len, int pos); char const* finalize_input( char const* ); void clear_self_to_end_of_screen( void ); typedef struct { int index; bool error; } paren_info_t; paren_info_t matching_paren( void ); }; } #endif