2011-09-02 18:51:20 +02:00
# include "window.hh"
# include "buffer.hh"
2012-05-03 09:25:13 +02:00
# include "shell_manager.hh"
2012-05-07 05:13:34 +02:00
# include "commands.hh"
2011-09-07 20:16:56 +02:00
# include "command_manager.hh"
2011-09-08 16:30:36 +02:00
# include "buffer_manager.hh"
2011-09-23 16:31:57 +02:00
# include "register_manager.hh"
2011-09-21 16:37:09 +02:00
# include "selectors.hh"
2011-09-09 21:24:18 +02:00
# include "assert.hh"
2011-10-07 16:16:38 +02:00
# include "debug.hh"
2011-11-29 23:37:20 +01:00
# include "highlighters.hh"
# include "highlighter_registry.hh"
2011-12-02 15:28:27 +01:00
# include "filters.hh"
# include "filter_registry.hh"
2012-04-03 14:01:01 +02:00
# include "hook_manager.hh"
2012-04-03 15:39:20 +02:00
# include "option_manager.hh"
2012-01-23 14:56:43 +01:00
# include "context.hh"
2012-02-16 15:25:16 +01:00
# include "ncurses.hh"
2012-04-14 03:17:09 +02:00
# include "regex.hh"
2011-09-02 18:51:20 +02:00
# include <unordered_map>
2011-12-28 20:04:06 +01:00
# include <sys/types.h>
# include <sys/wait.h>
2011-09-02 18:51:20 +02:00
using namespace Kakoune ;
2011-09-23 16:27:34 +02:00
using namespace std : : placeholders ;
2011-09-02 18:51:20 +02:00
2012-05-07 05:13:34 +02:00
namespace Kakoune
{
Context main_context ;
bool quit_requested = false ;
2011-12-05 15:28:45 +01:00
struct InsertSequence
{
IncrementalInserter : : Mode mode ;
2012-01-23 15:17:31 +01:00
std : : vector < Key > keys ;
2011-12-05 15:28:45 +01:00
InsertSequence ( ) : mode ( IncrementalInserter : : Mode : : Insert ) { }
} ;
InsertSequence last_insert_sequence ;
2012-07-27 10:22:33 +02:00
template < typename GetKey , typename Redraw >
void insert_sequence ( IncrementalInserter & inserter ,
GetKey get_key , Redraw redraw )
2011-12-05 15:28:45 +01:00
{
2012-07-27 10:22:33 +02:00
while ( true )
2011-12-05 15:28:45 +01:00
{
2012-07-27 10:22:33 +02:00
Key key = get_key ( ) ;
switch ( key . modifiers )
2012-01-24 20:08:57 +01:00
{
2012-07-27 10:22:33 +02:00
case Key : : Modifiers : : None :
switch ( key . key )
{
case 27 :
return ;
default :
inserter . insert ( String ( ) + key . key ) ;
}
2012-01-24 20:08:57 +01:00
break ;
2012-07-27 10:22:33 +02:00
case Key : : Modifiers : : Control :
switch ( key . key )
{
case ' r ' :
{
Key next_key = get_key ( ) ;
if ( next_key . modifiers = = Key : : Modifiers : : None )
inserter . insert ( RegisterManager : : instance ( ) [ next_key . key ] ) ;
break ;
}
case ' m ' :
inserter . insert ( String ( ) + ' \n ' ) ;
break ;
case ' i ' :
inserter . insert ( String ( ) + ' \t ' ) ;
break ;
case ' d ' :
inserter . move_cursors ( { 0 , - 1 } ) ;
break ;
case ' e ' :
inserter . move_cursors ( { 0 , 1 } ) ;
break ;
case ' g ' :
inserter . erase ( ) ;
break ;
}
2012-01-23 15:17:31 +01:00
break ;
}
2012-07-27 10:22:33 +02:00
redraw ( ) ;
2011-12-05 15:28:45 +01:00
}
}
2012-08-05 19:39:37 +02:00
template < IncrementalInserter : : Mode mode >
void do_insert ( const Context & context )
2011-09-20 00:00:29 +02:00
{
2011-12-05 15:28:45 +01:00
last_insert_sequence . mode = mode ;
last_insert_sequence . keys . clear ( ) ;
2012-08-05 19:39:37 +02:00
IncrementalInserter inserter ( context . editor ( ) , mode ) ;
draw_editor_ifn ( context . editor ( ) ) ;
2012-07-27 10:22:33 +02:00
insert_sequence ( inserter ,
[ & ] ( ) { Key key = get_key ( ) ;
last_insert_sequence . keys . push_back ( key ) ;
return key ; } ,
2012-08-05 19:39:37 +02:00
[ & ] ( ) { draw_editor_ifn ( context . editor ( ) ) ; } ) ;
2011-09-02 18:51:20 +02:00
}
2012-08-05 19:39:37 +02:00
void do_repeat_insert ( const Context & context )
2011-12-05 15:28:45 +01:00
{
2012-07-27 10:22:33 +02:00
if ( last_insert_sequence . keys . empty ( ) )
return ;
2012-08-05 19:39:37 +02:00
IncrementalInserter inserter ( context . editor ( ) , last_insert_sequence . mode ) ;
2012-07-27 10:22:33 +02:00
size_t index = 0 ;
insert_sequence ( inserter ,
[ & ] ( ) { return last_insert_sequence . keys [ index + + ] ; } ,
[ ] ( ) { } ) ;
2011-12-05 15:28:45 +01:00
}
2011-10-10 16:24:17 +02:00
template < bool append >
2012-08-05 19:39:37 +02:00
void do_go ( const Context & context )
2011-09-22 16:02:07 +02:00
{
2012-08-05 19:39:37 +02:00
int count = context . numeric_param ( ) ;
Editor & editor = context . editor ( ) ;
2011-09-22 16:02:07 +02:00
if ( count ! = 0 )
2011-10-10 16:24:17 +02:00
{
BufferIterator target =
2012-02-02 21:48:03 +01:00
editor . buffer ( ) . iterator_at ( BufferCoord ( count - 1 , 0 ) ) ;
2011-10-10 16:24:17 +02:00
2012-02-02 21:48:03 +01:00
editor . select ( target ) ;
2011-10-10 16:24:17 +02:00
}
2011-09-22 16:02:07 +02:00
else
{
2012-01-25 00:18:59 +01:00
Key key = get_key ( ) ;
if ( key . modifiers ! = Key : : Modifiers : : None )
return ;
switch ( key . key )
2011-09-22 16:02:07 +02:00
{
case ' g ' :
case ' t ' :
2011-10-10 16:24:17 +02:00
{
BufferIterator target =
2012-02-02 21:48:03 +01:00
editor . buffer ( ) . iterator_at ( BufferCoord ( 0 , 0 ) ) ;
editor . select ( target ) ;
2011-09-24 15:08:04 +02:00
break ;
2011-10-10 16:24:17 +02:00
}
2011-09-24 15:08:04 +02:00
case ' l ' :
2011-10-10 16:24:17 +02:00
case ' L ' :
2012-02-02 21:48:03 +01:00
editor . select ( select_to_eol , append ) ;
2011-09-24 15:08:04 +02:00
break ;
case ' h ' :
2011-10-10 16:24:17 +02:00
case ' H ' :
2012-02-02 21:48:03 +01:00
editor . select ( select_to_eol_reverse , append ) ;
2011-09-22 16:02:07 +02:00
break ;
case ' b ' :
2011-10-10 16:24:17 +02:00
{
2012-02-02 21:48:03 +01:00
BufferIterator target = editor . buffer ( ) . iterator_at (
BufferCoord ( editor . buffer ( ) . line_count ( ) - 1 , 0 ) ) ;
editor . select ( target ) ;
2011-09-22 16:02:07 +02:00
break ;
}
2011-10-10 16:24:17 +02:00
}
2011-09-22 16:02:07 +02:00
}
}
2012-08-05 19:39:37 +02:00
void do_command ( const Context & context )
2011-09-02 18:51:20 +02:00
{
try
{
2011-09-23 16:29:42 +02:00
auto cmdline = prompt ( " : " , std : : bind ( & CommandManager : : complete ,
& CommandManager : : instance ( ) ,
_1 , _2 ) ) ;
2012-08-05 19:39:37 +02:00
CommandManager : : instance ( ) . execute ( cmdline , context ) ;
2011-09-02 18:51:20 +02:00
}
catch ( prompt_aborted & ) { }
}
2012-08-05 19:39:37 +02:00
void do_pipe ( const Context & context )
2011-12-28 20:04:06 +01:00
{
try
{
auto cmdline = prompt ( " | " , complete_nothing ) ;
2012-08-05 19:39:37 +02:00
context . buffer ( ) . begin_undo_group ( ) ;
for ( auto & sel : const_cast < const Editor & > ( context . editor ( ) ) . selections ( ) )
2011-12-28 20:04:06 +01:00
{
2012-05-29 12:39:03 +02:00
String new_content = ShellManager : : instance ( ) . pipe ( String ( sel . begin ( ) , sel . end ( ) ) ,
2012-08-05 19:39:37 +02:00
cmdline , context , { } ) ;
context . buffer ( ) . modify ( Modification : : make_erase ( sel . begin ( ) , sel . end ( ) ) ) ;
context . buffer ( ) . modify ( Modification : : make_insert ( sel . begin ( ) , new_content ) ) ;
2011-12-28 20:04:06 +01:00
}
2012-08-05 19:39:37 +02:00
context . buffer ( ) . end_undo_group ( ) ;
2011-12-28 20:04:06 +01:00
}
catch ( prompt_aborted & ) { }
}
2012-02-28 21:50:47 +01:00
template < bool append >
2012-08-05 19:39:37 +02:00
void do_search ( const Context & context )
2011-09-02 18:51:20 +02:00
{
try
{
2012-04-14 03:17:09 +02:00
String ex = prompt ( " / " ) ;
2011-09-24 14:48:58 +02:00
if ( ex . empty ( ) )
2012-06-29 13:25:34 +02:00
ex = RegisterManager : : instance ( ) [ ' / ' ] [ 0 ] ;
2011-09-24 14:48:58 +02:00
else
2012-02-10 00:47:55 +01:00
RegisterManager : : instance ( ) [ ' / ' ] = ex ;
2011-09-24 14:48:58 +02:00
2012-08-05 19:39:37 +02:00
context . editor ( ) . select ( std : : bind ( select_next_match , _1 , ex ) , append ) ;
2011-09-02 18:51:20 +02:00
}
catch ( prompt_aborted & ) { }
}
2012-02-28 21:50:47 +01:00
template < bool append >
2012-08-05 19:39:37 +02:00
void do_search_next ( const Context & context )
2011-09-24 14:48:58 +02:00
{
2012-06-29 13:25:34 +02:00
const String & ex = RegisterManager : : instance ( ) [ ' / ' ] [ 0 ] ;
2011-09-24 14:48:58 +02:00
if ( not ex . empty ( ) )
2012-08-05 19:39:37 +02:00
context . editor ( ) . select ( std : : bind ( select_next_match , _1 , ex ) , append ) ;
2011-09-24 14:48:58 +02:00
else
2012-06-06 01:15:19 +02:00
print_status ( " no search pattern " ) ;
2011-09-24 14:48:58 +02:00
}
2012-08-05 19:39:37 +02:00
void do_yank ( const Context & context )
2011-09-23 16:31:57 +02:00
{
2012-08-05 19:39:37 +02:00
RegisterManager : : instance ( ) [ ' " ' ] = context . editor ( ) . selections_content ( ) ;
2011-09-23 16:31:57 +02:00
}
2012-08-05 19:39:37 +02:00
void do_erase ( const Context & context )
2011-09-26 10:59:32 +02:00
{
2012-08-05 19:39:37 +02:00
RegisterManager : : instance ( ) [ ' " ' ] = context . editor ( ) . selections_content ( ) ;
context . editor ( ) . erase ( ) ;
2011-09-26 10:59:32 +02:00
}
2012-08-05 19:39:37 +02:00
void do_change ( const Context & context )
2011-09-26 10:59:32 +02:00
{
2012-08-05 19:39:37 +02:00
RegisterManager : : instance ( ) [ ' " ' ] = context . editor ( ) . selections_content ( ) ;
do_insert < IncrementalInserter : : Mode : : Change > ( context ) ;
2011-09-26 10:59:32 +02:00
}
2012-07-11 14:15:27 +02:00
enum class PasteMode
{
Before ,
After ,
Replace
} ;
template < PasteMode paste_mode >
2012-08-05 19:39:37 +02:00
void do_paste ( const Context & context )
2011-09-23 16:31:57 +02:00
{
2012-08-05 19:39:37 +02:00
Editor & editor = context . editor ( ) ;
int count = context . numeric_param ( ) ;
2012-02-10 15:00:21 +01:00
Register & reg = RegisterManager : : instance ( ) [ ' " ' ] ;
if ( count = = 0 )
{
2012-07-11 14:15:27 +02:00
if ( paste_mode = = PasteMode : : Before )
2012-02-10 15:00:21 +01:00
editor . insert ( reg ) ;
2012-07-11 14:15:27 +02:00
else if ( paste_mode = = PasteMode : : After )
editor . append ( reg ) ;
else if ( paste_mode = = PasteMode : : Replace )
editor . replace ( reg ) ;
2012-02-10 15:00:21 +01:00
}
2011-09-27 16:15:20 +02:00
else
2012-02-10 15:00:21 +01:00
{
2012-07-11 14:15:27 +02:00
if ( paste_mode = = PasteMode : : Before )
2012-06-29 13:25:34 +02:00
editor . insert ( reg [ count - 1 ] ) ;
2012-07-11 14:15:27 +02:00
else if ( paste_mode = = PasteMode : : After )
editor . append ( reg [ count - 1 ] ) ;
else if ( paste_mode = = PasteMode : : Replace )
editor . replace ( reg [ count - 1 ] ) ;
2012-02-10 15:00:21 +01:00
}
2011-09-23 16:31:57 +02:00
}
2012-08-05 19:39:37 +02:00
void do_select_regex ( const Context & context )
2011-11-16 15:06:01 +01:00
{
try
{
2012-04-14 03:17:09 +02:00
String ex = prompt ( " select: " ) ;
2012-08-05 19:39:37 +02:00
context . editor ( ) . multi_select ( std : : bind ( select_all_matches , _1 , ex ) ) ;
2011-11-16 15:06:01 +01:00
}
catch ( prompt_aborted & ) { }
}
2012-08-05 19:39:37 +02:00
void do_split_regex ( const Context & context )
2011-11-21 20:30:44 +01:00
{
try
{
2012-04-14 03:17:09 +02:00
String ex = prompt ( " split: " ) ;
2012-08-05 19:39:37 +02:00
context . editor ( ) . multi_select ( std : : bind ( split_selection , _1 , ex ) ) ;
2011-11-21 20:30:44 +01:00
}
catch ( prompt_aborted & ) { }
}
2012-08-05 19:39:37 +02:00
void do_join ( const Context & context )
2011-11-22 15:24:50 +01:00
{
2012-08-05 19:39:37 +02:00
Editor & editor = context . editor ( ) ;
2012-02-07 15:26:51 +01:00
editor . select ( select_whole_lines ) ;
2012-02-02 21:48:03 +01:00
editor . select ( select_to_eol , true ) ;
editor . multi_select ( std : : bind ( select_all_matches , _1 , " \n \\ h* " ) ) ;
editor . replace ( " " ) ;
editor . clear_selections ( ) ;
editor . move_selections ( { 0 , - 1 } ) ;
2011-11-22 15:24:50 +01:00
}
2012-03-12 15:23:30 +01:00
template < bool inner >
2012-08-05 19:39:37 +02:00
void do_select_object ( const Context & context )
2012-01-04 15:18:08 +01:00
{
2012-03-12 15:23:30 +01:00
typedef std : : function < SelectionAndCaptures ( const Selection & ) > Selector ;
static const std : : unordered_map < Key , Selector > key_to_selector =
2012-01-04 15:18:08 +01:00
{
2012-03-12 15:23:30 +01:00
{ { Key : : Modifiers : : None , ' ( ' } , std : : bind ( select_surrounding , _1 , std : : pair < char , char > { ' ( ' , ' ) ' } , inner ) } ,
{ { Key : : Modifiers : : None , ' ) ' } , std : : bind ( select_surrounding , _1 , std : : pair < char , char > { ' ( ' , ' ) ' } , inner ) } ,
{ { Key : : Modifiers : : None , ' b ' } , std : : bind ( select_surrounding , _1 , std : : pair < char , char > { ' ( ' , ' ) ' } , inner ) } ,
{ { Key : : Modifiers : : None , ' { ' } , std : : bind ( select_surrounding , _1 , std : : pair < char , char > { ' { ' , ' } ' } , inner ) } ,
{ { Key : : Modifiers : : None , ' } ' } , std : : bind ( select_surrounding , _1 , std : : pair < char , char > { ' { ' , ' } ' } , inner ) } ,
{ { Key : : Modifiers : : None , ' B ' } , std : : bind ( select_surrounding , _1 , std : : pair < char , char > { ' { ' , ' } ' } , inner ) } ,
{ { Key : : Modifiers : : None , ' [ ' } , std : : bind ( select_surrounding , _1 , std : : pair < char , char > { ' [ ' , ' ] ' } , inner ) } ,
{ { Key : : Modifiers : : None , ' ] ' } , std : : bind ( select_surrounding , _1 , std : : pair < char , char > { ' [ ' , ' ] ' } , inner ) } ,
{ { Key : : Modifiers : : None , ' < ' } , std : : bind ( select_surrounding , _1 , std : : pair < char , char > { ' < ' , ' > ' } , inner ) } ,
{ { Key : : Modifiers : : None , ' > ' } , std : : bind ( select_surrounding , _1 , std : : pair < char , char > { ' < ' , ' > ' } , inner ) } ,
{ { Key : : Modifiers : : None , ' w ' } , std : : bind ( select_whole_word < false > , _1 , inner ) } ,
{ { Key : : Modifiers : : None , ' W ' } , std : : bind ( select_whole_word < true > , _1 , inner ) } ,
2012-01-04 15:18:08 +01:00
} ;
2012-03-12 15:23:30 +01:00
Key key = get_key ( ) ;
auto it = key_to_selector . find ( key ) ;
if ( it ! = key_to_selector . end ( ) )
2012-08-05 19:39:37 +02:00
context . editor ( ) . select ( it - > second ) ;
2012-01-04 15:18:08 +01:00
}
2012-08-05 19:39:37 +02:00
std : : unordered_map < Key , std : : function < void ( const Context & context ) > > keymap =
2011-09-02 18:51:20 +02:00
{
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : None , ' h ' } , [ ] ( const Context & context ) { context . editor ( ) . move_selections ( BufferCoord ( 0 , - std : : max ( context . numeric_param ( ) , 1 ) ) ) ; } } ,
{ { Key : : Modifiers : : None , ' j ' } , [ ] ( const Context & context ) { context . editor ( ) . move_selections ( BufferCoord ( std : : max ( context . numeric_param ( ) , 1 ) , 0 ) ) ; } } ,
{ { Key : : Modifiers : : None , ' k ' } , [ ] ( const Context & context ) { context . editor ( ) . move_selections ( BufferCoord ( - std : : max ( context . numeric_param ( ) , 1 ) , 0 ) ) ; } } ,
{ { Key : : Modifiers : : None , ' l ' } , [ ] ( const Context & context ) { context . editor ( ) . move_selections ( BufferCoord ( 0 , std : : max ( context . numeric_param ( ) , 1 ) ) ) ; } } ,
2011-10-14 16:29:53 +02:00
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : None , ' H ' } , [ ] ( const Context & context ) { context . editor ( ) . move_selections ( BufferCoord ( 0 , - std : : max ( context . numeric_param ( ) , 1 ) ) , true ) ; } } ,
{ { Key : : Modifiers : : None , ' J ' } , [ ] ( const Context & context ) { context . editor ( ) . move_selections ( BufferCoord ( std : : max ( context . numeric_param ( ) , 1 ) , 0 ) , true ) ; } } ,
{ { Key : : Modifiers : : None , ' K ' } , [ ] ( const Context & context ) { context . editor ( ) . move_selections ( BufferCoord ( - std : : max ( context . numeric_param ( ) , 1 ) , 0 ) , true ) ; } } ,
{ { Key : : Modifiers : : None , ' L ' } , [ ] ( const Context & context ) { context . editor ( ) . move_selections ( BufferCoord ( 0 , std : : max ( context . numeric_param ( ) , 1 ) ) , true ) ; } } ,
2011-10-07 16:03:25 +02:00
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : None , ' t ' } , [ ] ( const Context & context ) { context . editor ( ) . select ( std : : bind ( select_to , _1 , get_key ( ) . key , context . numeric_param ( ) , false ) ) ; } } ,
{ { Key : : Modifiers : : None , ' f ' } , [ ] ( const Context & context ) { context . editor ( ) . select ( std : : bind ( select_to , _1 , get_key ( ) . key , context . numeric_param ( ) , true ) ) ; } } ,
{ { Key : : Modifiers : : None , ' T ' } , [ ] ( const Context & context ) { context . editor ( ) . select ( std : : bind ( select_to , _1 , get_key ( ) . key , context . numeric_param ( ) , false ) , true ) ; } } ,
{ { Key : : Modifiers : : None , ' F ' } , [ ] ( const Context & context ) { context . editor ( ) . select ( std : : bind ( select_to , _1 , get_key ( ) . key , context . numeric_param ( ) , true ) , true ) ; } } ,
2011-09-22 16:35:28 +02:00
2011-12-21 15:29:28 +01:00
{ { Key : : Modifiers : : None , ' d ' } , do_erase } ,
{ { Key : : Modifiers : : None , ' c ' } , do_change } ,
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : None , ' i ' } , do_insert < IncrementalInserter : : Mode : : Insert > } ,
{ { Key : : Modifiers : : None , ' I ' } , do_insert < IncrementalInserter : : Mode : : InsertAtLineBegin > } ,
{ { Key : : Modifiers : : None , ' a ' } , do_insert < IncrementalInserter : : Mode : : Append > } ,
{ { Key : : Modifiers : : None , ' A ' } , do_insert < IncrementalInserter : : Mode : : AppendAtLineEnd > } ,
{ { Key : : Modifiers : : None , ' o ' } , do_insert < IncrementalInserter : : Mode : : OpenLineBelow > } ,
{ { Key : : Modifiers : : None , ' O ' } , do_insert < IncrementalInserter : : Mode : : OpenLineAbove > } ,
2011-09-22 11:24:16 +02:00
2011-12-21 15:29:28 +01:00
{ { Key : : Modifiers : : None , ' g ' } , do_go < false > } ,
{ { Key : : Modifiers : : None , ' G ' } , do_go < true > } ,
2011-09-22 11:24:16 +02:00
2011-12-21 15:29:28 +01:00
{ { Key : : Modifiers : : None , ' y ' } , do_yank } ,
2012-07-11 14:15:27 +02:00
{ { Key : : Modifiers : : None , ' p ' } , do_paste < PasteMode : : After > } ,
{ { Key : : Modifiers : : None , ' P ' } , do_paste < PasteMode : : Before > } ,
{ { Key : : Modifiers : : Alt , ' p ' } , do_paste < PasteMode : : Replace > } ,
2011-09-23 16:31:57 +02:00
2011-12-21 15:29:28 +01:00
{ { Key : : Modifiers : : None , ' s ' } , do_select_regex } ,
2011-11-16 15:06:01 +01:00
2011-12-05 15:28:45 +01:00
2011-12-21 15:29:28 +01:00
{ { Key : : Modifiers : : None , ' . ' } , do_repeat_insert } ,
2011-12-05 15:28:45 +01:00
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : None , ' % ' } , [ ] ( const Context & context ) { context . editor ( ) . clear_selections ( ) ; context . editor ( ) . select ( select_whole_buffer ) ; } } ,
2011-09-24 15:45:25 +02:00
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : None , ' : ' } , do_command } ,
2011-12-28 20:04:06 +01:00
{ { Key : : Modifiers : : None , ' | ' } , do_pipe } ,
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : None , ' ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; if ( count = = 0 ) context . editor ( ) . clear_selections ( ) ;
else context . editor ( ) . keep_selection ( count - 1 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; if ( count = = 0 ) context . editor ( ) . clear_selections ( ) ;
else context . editor ( ) . remove_selection ( count - 1 ) ; } } ,
{ { Key : : Modifiers : : None , ' w ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_next_word < false > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' e ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_next_word_end < false > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' b ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_previous_word < false > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' W ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_next_word < false > , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' E ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_next_word_end < false > , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' B ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_previous_word < false > , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' x ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_line , false ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' X ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_line , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' m ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; context . editor ( ) . select ( select_matching ) ; } } ,
{ { Key : : Modifiers : : None , ' M ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; context . editor ( ) . select ( select_matching , true ) ; } } ,
{ { Key : : Modifiers : : None , ' / ' } , do_search < false > } ,
{ { Key : : Modifiers : : None , ' ? ' } , do_search < true > } ,
{ { Key : : Modifiers : : None , ' n ' } , do_search_next < false > } ,
{ { Key : : Modifiers : : None , ' N ' } , do_search_next < true > } ,
{ { Key : : Modifiers : : None , ' u ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { if ( not context . editor ( ) . undo ( ) ) { print_status ( " nothing left to undo " ) ; break ; } } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' U ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { if ( not context . editor ( ) . redo ( ) ) { print_status ( " nothing left to redo " ) ; break ; } } while ( - - count > 0 ) ; } } ,
2011-12-21 15:29:28 +01:00
2012-03-12 15:23:30 +01:00
{ { Key : : Modifiers : : Alt , ' i ' } , do_select_object < true > } ,
{ { Key : : Modifiers : : Alt , ' a ' } , do_select_object < false > } ,
2012-01-04 15:18:08 +01:00
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : Alt , ' t ' } , [ ] ( const Context & context ) { context . editor ( ) . select ( std : : bind ( select_to_reverse , _1 , get_key ( ) . key , context . numeric_param ( ) , false ) ) ; } } ,
{ { Key : : Modifiers : : Alt , ' f ' } , [ ] ( const Context & context ) { context . editor ( ) . select ( std : : bind ( select_to_reverse , _1 , get_key ( ) . key , context . numeric_param ( ) , true ) ) ; } } ,
{ { Key : : Modifiers : : Alt , ' T ' } , [ ] ( const Context & context ) { context . editor ( ) . select ( std : : bind ( select_to_reverse , _1 , get_key ( ) . key , context . numeric_param ( ) , false ) , true ) ; } } ,
{ { Key : : Modifiers : : Alt , ' F ' } , [ ] ( const Context & context ) { context . editor ( ) . select ( std : : bind ( select_to_reverse , _1 , get_key ( ) . key , context . numeric_param ( ) , true ) , true ) ; } } ,
2011-12-21 15:29:28 +01:00
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : Alt , ' w ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_next_word < true > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' e ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_next_word_end < true > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' b ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_previous_word < true > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' W ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_next_word < true > , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' E ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_next_word_end < true > , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' B ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_previous_word < true > , true ) ; } while ( - - count > 0 ) ; } } ,
2011-12-21 15:29:28 +01:00
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : Alt , ' l ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_eol , false ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' L ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_eol , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' h ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_eol_reverse , false ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' H ' } , [ ] ( const Context & context ) { int count = context . numeric_param ( ) ; do { context . editor ( ) . select ( select_to_eol_reverse , true ) ; } while ( - - count > 0 ) ; } } ,
2011-12-21 15:29:28 +01:00
{ { Key : : Modifiers : : Alt , ' s ' } , do_split_regex } ,
{ { Key : : Modifiers : : Alt , ' j ' } , do_join } ,
2012-08-05 19:39:37 +02:00
{ { Key : : Modifiers : : Alt , ' x ' } , [ ] ( const Context & context ) { context . editor ( ) . select ( select_whole_lines ) ; } } ,
2011-10-25 16:28:20 +02:00
} ;
2012-05-03 09:24:27 +02:00
}
2012-03-21 20:27:36 +01:00
void run_unit_tests ( ) ;
2011-09-21 16:37:09 +02:00
int main ( int argc , char * argv [ ] )
2011-09-02 18:51:20 +02:00
{
2012-06-14 15:20:40 +02:00
GlobalOptionManager option_manager ;
GlobalHookManager hook_manager ;
2012-05-03 09:25:13 +02:00
ShellManager shell_manager ;
2011-11-29 23:37:20 +01:00
CommandManager command_manager ;
BufferManager buffer_manager ;
RegisterManager register_manager ;
HighlighterRegistry highlighter_registry ;
2011-12-02 15:28:27 +01:00
FilterRegistry filter_registry ;
2011-09-23 16:29:42 +02:00
2012-03-21 20:27:36 +01:00
run_unit_tests ( ) ;
2012-05-03 09:25:13 +02:00
shell_manager . register_env_var ( " bufname " ,
2012-06-25 19:40:18 +02:00
[ ] ( const String & name , const Context & context )
2012-05-03 09:25:13 +02:00
{ return context . buffer ( ) . name ( ) ; } ) ;
2012-05-07 08:56:53 +02:00
shell_manager . register_env_var ( " selection " ,
2012-06-25 19:40:18 +02:00
[ ] ( const String & name , const Context & context )
2012-05-07 08:56:53 +02:00
{ return context . window ( ) . selections_content ( ) . back ( ) ; } ) ;
2012-06-27 14:28:43 +02:00
shell_manager . register_env_var ( " opt_.+ " ,
[ ] ( const String & name , const Context & context )
2012-06-28 14:01:37 +02:00
{ return context . option_manager ( ) [ name . substr ( 4 ) ] . as_string ( ) ; } ) ;
2012-06-29 18:37:17 +02:00
register_manager . register_dynamic_register ( ' % ' , [ & ] ( ) { return std : : vector < String > ( 1 , main_context . buffer ( ) . name ( ) ) ; } ) ;
register_manager . register_dynamic_register ( ' . ' , [ & ] ( ) { return main_context . window ( ) . selections_content ( ) ; } ) ;
2012-05-07 05:13:34 +02:00
register_commands ( ) ;
2011-11-29 23:37:20 +01:00
register_highlighters ( ) ;
2011-12-02 15:28:27 +01:00
register_filters ( ) ;
2011-11-08 15:28:01 +01:00
2011-09-02 18:51:20 +02:00
try
{
2012-06-28 14:11:43 +02:00
NCursesClient client ;
current_client = & client ;
2012-06-06 01:15:19 +02:00
2012-06-12 15:10:33 +02:00
try
{
command_manager . execute ( " runtime kakrc " , main_context ) ;
}
catch ( Kakoune : : runtime_error & error )
{
print_status ( error . description ( ) ) ;
}
2011-11-28 19:52:29 +01:00
write_debug ( " *** This is the debug buffer, where debug info will be written *** \n " ) ;
2012-04-14 03:17:09 +02:00
write_debug ( " utf-8 test: é á ï " ) ;
2011-11-28 19:52:29 +01:00
2012-05-07 05:13:34 +02:00
if ( argc > 1 )
command_manager . execute ( String ( " edit " ) + argv [ 1 ] , main_context ) ;
else
{
auto buffer = new Buffer ( " *scratch* " , Buffer : : Type : : Scratch ) ;
main_context = Context ( * buffer - > get_or_create_window ( ) ) ;
}
2011-09-02 18:51:20 +02:00
2012-06-28 14:11:43 +02:00
current_client - > draw_window ( main_context . window ( ) ) ;
2011-09-02 18:51:20 +02:00
int count = 0 ;
while ( not quit_requested )
{
2011-09-09 20:40:59 +02:00
try
2011-09-02 18:51:20 +02:00
{
2012-01-23 15:17:31 +01:00
Key key = get_key ( ) ;
if ( key . modifiers = = Key : : Modifiers : : None and isdigit ( key . key ) )
count = count * 10 + key . key - ' 0 ' ;
2011-09-09 20:40:59 +02:00
else
2011-09-02 18:51:20 +02:00
{
2011-12-21 15:29:28 +01:00
auto it = keymap . find ( key ) ;
if ( it ! = keymap . end ( ) )
2011-09-09 20:40:59 +02:00
{
2012-08-05 19:39:37 +02:00
main_context . numeric_param ( count ) ;
it - > second ( main_context ) ;
2012-06-28 14:11:43 +02:00
current_client - > draw_window ( main_context . window ( ) ) ;
2011-09-09 20:40:59 +02:00
}
count = 0 ;
2011-09-02 18:51:20 +02:00
}
2011-09-09 20:40:59 +02:00
}
catch ( Kakoune : : runtime_error & error )
{
2012-06-06 01:15:19 +02:00
print_status ( error . description ( ) ) ;
2011-09-02 18:51:20 +02:00
}
}
}
2011-09-09 21:24:18 +02:00
catch ( Kakoune : : exception & error )
{
puts ( " uncaught exception: \n " ) ;
puts ( error . description ( ) . c_str ( ) ) ;
return - 1 ;
}
2012-06-28 13:46:14 +02:00
main_context = Context ( ) ;
2011-09-02 18:51:20 +02:00
return 0 ;
}