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 ;
2012-02-02 21:48:03 +01:00
void draw_editor_ifn ( Editor & editor )
{
Window * window = dynamic_cast < Window * > ( & editor ) ;
if ( window )
2012-02-16 15:25:16 +01:00
NCurses : : draw_window ( * window ) ;
2012-02-02 21:48:03 +01:00
}
2012-02-16 15:25:16 +01:00
PromptFunc prompt_func ;
2012-04-14 03:17:09 +02:00
String prompt ( const String & text , Completer completer = complete_nothing )
2011-12-20 20:22:05 +01:00
{
return prompt_func ( text , completer ) ;
}
2012-02-16 15:25:16 +01:00
GetKeyFunc get_key_func ;
2012-01-25 00:18:59 +01:00
Key get_key ( )
{
return get_key_func ( ) ;
}
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-02-02 21:48:03 +01:00
bool insert_char ( IncrementalInserter & inserter , const Key & key )
2011-12-05 15:28:45 +01:00
{
2012-01-23 15:17:31 +01:00
switch ( key . modifiers )
2011-12-05 15:28:45 +01:00
{
2012-01-23 15:17:31 +01:00
case Key : : Modifiers : : None :
switch ( key . key )
{
case 27 :
return false ;
default :
2012-04-14 03:17:09 +02:00
inserter . insert ( String ( ) + key . key ) ;
2012-01-23 15:17:31 +01:00
}
2011-12-05 15:28:45 +01:00
break ;
2012-01-23 15:17:31 +01:00
case Key : : Modifiers : : Control :
switch ( key . key )
{
2012-01-24 20:08:57 +01:00
case ' r ' :
{
Key next_key = get_key ( ) ;
last_insert_sequence . keys . push_back ( next_key ) ;
if ( next_key . modifiers = = Key : : Modifiers : : None )
{
switch ( next_key . key )
{
case ' % ' :
2012-02-02 21:48:03 +01:00
inserter . insert ( inserter . buffer ( ) . name ( ) ) ;
2012-01-24 20:08:57 +01:00
break ;
default :
2012-02-10 00:47:55 +01:00
inserter . insert ( RegisterManager : : instance ( ) [ next_key . key ] ) ;
2012-01-24 20:08:57 +01:00
}
}
break ;
}
2012-01-25 00:19:26 +01:00
case ' m ' :
2012-04-14 03:17:09 +02:00
inserter . insert ( String ( ) + ' \n ' ) ;
2012-01-25 00:19:26 +01:00
break ;
2012-04-03 15:38:01 +02:00
case ' i ' :
2012-04-14 03:17:09 +02:00
inserter . insert ( String ( ) + ' \t ' ) ;
2012-04-03 15:38:01 +02:00
break ;
2012-01-23 15:17:31 +01:00
case ' d ' :
2012-01-25 15:23:02 +01:00
inserter . move_cursors ( { 0 , - 1 } ) ;
2012-01-23 15:17:31 +01:00
break ;
case ' e ' :
2012-01-25 15:23:02 +01:00
inserter . move_cursors ( { 0 , 1 } ) ;
2012-01-23 15:17:31 +01:00
break ;
case ' g ' :
inserter . erase ( ) ;
break ;
}
2011-12-05 15:28:45 +01:00
break ;
}
return true ;
}
2012-02-02 21:48:03 +01:00
void do_insert ( Editor & editor , IncrementalInserter : : Mode mode )
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-02-02 21:48:03 +01:00
IncrementalInserter inserter ( editor , mode ) ;
draw_editor_ifn ( editor ) ;
2011-09-02 18:51:20 +02:00
while ( true )
{
2012-01-23 15:17:31 +01:00
Key key = get_key ( ) ;
2011-09-20 00:00:29 +02:00
2012-02-02 21:48:03 +01:00
if ( not insert_char ( inserter , key ) )
2012-01-31 20:12:06 +01:00
break ;
2011-09-20 00:00:29 +02:00
2012-01-23 15:17:31 +01:00
last_insert_sequence . keys . push_back ( key ) ;
2012-02-02 21:48:03 +01:00
draw_editor_ifn ( editor ) ;
2011-09-02 18:51:20 +02:00
}
}
2012-02-02 21:48:03 +01:00
void do_repeat_insert ( Editor & editor , int count )
2011-12-05 15:28:45 +01:00
{
2012-02-02 21:48:03 +01:00
IncrementalInserter inserter ( editor , last_insert_sequence . mode ) ;
2012-01-23 15:17:31 +01:00
for ( const Key & key : last_insert_sequence . keys )
2011-12-05 15:28:45 +01:00
{
2012-02-02 21:48:03 +01:00
insert_char ( inserter , key ) ;
2011-12-05 15:28:45 +01:00
}
2012-02-02 21:48:03 +01:00
draw_editor_ifn ( editor ) ;
2011-12-05 15:28:45 +01:00
}
2011-10-10 16:24:17 +02:00
template < bool append >
2012-02-02 21:48:03 +01:00
void do_go ( Editor & editor , int count )
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
}
}
2011-09-02 18:51:20 +02:00
void do_command ( )
{
try
{
2011-09-23 16:29:42 +02:00
auto cmdline = prompt ( " : " , std : : bind ( & CommandManager : : complete ,
& CommandManager : : instance ( ) ,
_1 , _2 ) ) ;
2011-11-26 19:32:57 +01:00
CommandManager : : instance ( ) . execute ( cmdline , main_context ) ;
2011-09-02 18:51:20 +02:00
}
catch ( prompt_aborted & ) { }
}
2012-02-02 21:48:03 +01:00
void do_pipe ( Editor & editor , int count )
2011-12-28 20:04:06 +01:00
{
try
{
auto cmdline = prompt ( " | " , complete_nothing ) ;
2012-02-02 21:48:03 +01:00
editor . buffer ( ) . begin_undo_group ( ) ;
for ( auto & sel : const_cast < const Editor & > ( 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 ( ) ) ,
cmdline , main_context , { } ) ;
2012-05-03 09:33:13 +02:00
editor . buffer ( ) . modify ( Modification : : make_erase ( sel . begin ( ) , sel . end ( ) ) ) ;
editor . buffer ( ) . modify ( Modification : : make_insert ( sel . begin ( ) , new_content ) ) ;
2011-12-28 20:04:06 +01:00
}
2012-02-02 21:48:03 +01:00
editor . 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-02-02 21:48:03 +01:00
void do_search ( Editor & editor )
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-02-08 00:01:02 +01:00
ex = RegisterManager : : instance ( ) [ ' / ' ] . get ( ) ;
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-02-28 21:50:47 +01:00
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-02-02 21:48:03 +01:00
void do_search_next ( Editor & editor )
2011-09-24 14:48:58 +02:00
{
2012-04-14 03:17:09 +02:00
const String & ex = RegisterManager : : instance ( ) [ ' / ' ] . get ( ) ;
2011-09-24 14:48:58 +02:00
if ( not ex . empty ( ) )
2012-02-28 21:50:47 +01:00
editor . select ( std : : bind ( select_next_match , _1 , ex ) , append ) ;
2011-09-24 14:48:58 +02:00
else
2012-02-16 15:25:16 +01:00
NCurses : : print_status ( " no search pattern " ) ;
2011-09-24 14:48:58 +02:00
}
2012-02-02 21:48:03 +01:00
void do_yank ( Editor & editor , int count )
2011-09-23 16:31:57 +02:00
{
2012-02-10 00:47:55 +01:00
RegisterManager : : instance ( ) [ ' " ' ] = editor . selections_content ( ) ;
2011-09-23 16:31:57 +02:00
}
2012-02-02 21:48:03 +01:00
void do_erase ( Editor & editor , int count )
2011-09-26 10:59:32 +02:00
{
2012-02-10 00:47:55 +01:00
RegisterManager : : instance ( ) [ ' " ' ] = editor . selections_content ( ) ;
2012-02-02 21:48:03 +01:00
editor . erase ( ) ;
2011-09-26 10:59:32 +02:00
}
2012-02-02 21:48:03 +01:00
void do_change ( Editor & editor , int count )
2011-09-26 10:59:32 +02:00
{
2012-02-10 00:47:55 +01:00
RegisterManager : : instance ( ) [ ' " ' ] = editor . selections_content ( ) ;
2012-02-02 21:48:03 +01:00
do_insert ( editor , IncrementalInserter : : Mode : : Change ) ;
2011-09-26 10:59:32 +02:00
}
2011-09-27 16:15:20 +02:00
template < bool append >
2012-02-02 21:48:03 +01:00
void do_paste ( Editor & editor , int count )
2011-09-23 16:31:57 +02:00
{
2012-02-10 15:00:21 +01:00
Register & reg = RegisterManager : : instance ( ) [ ' " ' ] ;
if ( count = = 0 )
{
if ( append )
editor . append ( reg ) ;
else
editor . insert ( reg ) ;
}
2011-09-27 16:15:20 +02:00
else
2012-02-10 15:00:21 +01:00
{
if ( append )
editor . append ( reg . get ( count - 1 ) ) ;
else
editor . insert ( reg . get ( count - 1 ) ) ;
}
2011-09-23 16:31:57 +02:00
}
2012-02-02 21:48:03 +01:00
void do_select_regex ( Editor & editor , int count )
2011-11-16 15:06:01 +01:00
{
try
{
2012-04-14 03:17:09 +02:00
String ex = prompt ( " select: " ) ;
2012-02-02 21:48:03 +01:00
editor . multi_select ( std : : bind ( select_all_matches , _1 , ex ) ) ;
2011-11-16 15:06:01 +01:00
}
catch ( prompt_aborted & ) { }
}
2012-02-02 21:48:03 +01:00
void do_split_regex ( Editor & editor , int count )
2011-11-21 20:30:44 +01:00
{
try
{
2012-04-14 03:17:09 +02:00
String ex = prompt ( " split: " ) ;
2012-02-02 21:48:03 +01:00
editor . multi_select ( std : : bind ( split_selection , _1 , ex ) ) ;
2011-11-21 20:30:44 +01:00
}
catch ( prompt_aborted & ) { }
}
2012-02-02 21:48:03 +01:00
void do_join ( Editor & editor , int count )
2011-11-22 15:24:50 +01:00
{
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 >
void do_select_object ( Editor & editor , int count )
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 ( ) )
editor . select ( it - > second ) ;
2012-01-04 15:18:08 +01:00
}
2012-02-02 21:48:03 +01:00
std : : unordered_map < Key , std : : function < void ( Editor & editor , int count ) > > keymap =
2011-09-02 18:51:20 +02:00
{
2012-02-02 21:48:03 +01:00
{ { Key : : Modifiers : : None , ' h ' } , [ ] ( Editor & editor , int count ) { editor . move_selections ( BufferCoord ( 0 , - std : : max ( count , 1 ) ) ) ; } } ,
{ { Key : : Modifiers : : None , ' j ' } , [ ] ( Editor & editor , int count ) { editor . move_selections ( BufferCoord ( std : : max ( count , 1 ) , 0 ) ) ; } } ,
{ { Key : : Modifiers : : None , ' k ' } , [ ] ( Editor & editor , int count ) { editor . move_selections ( BufferCoord ( - std : : max ( count , 1 ) , 0 ) ) ; } } ,
{ { Key : : Modifiers : : None , ' l ' } , [ ] ( Editor & editor , int count ) { editor . move_selections ( BufferCoord ( 0 , std : : max ( count , 1 ) ) ) ; } } ,
2011-10-14 16:29:53 +02:00
2012-02-02 21:48:03 +01:00
{ { Key : : Modifiers : : None , ' H ' } , [ ] ( Editor & editor , int count ) { editor . move_selections ( BufferCoord ( 0 , - std : : max ( count , 1 ) ) , true ) ; } } ,
{ { Key : : Modifiers : : None , ' J ' } , [ ] ( Editor & editor , int count ) { editor . move_selections ( BufferCoord ( std : : max ( count , 1 ) , 0 ) , true ) ; } } ,
{ { Key : : Modifiers : : None , ' K ' } , [ ] ( Editor & editor , int count ) { editor . move_selections ( BufferCoord ( - std : : max ( count , 1 ) , 0 ) , true ) ; } } ,
{ { Key : : Modifiers : : None , ' L ' } , [ ] ( Editor & editor , int count ) { editor . move_selections ( BufferCoord ( 0 , std : : max ( count , 1 ) ) , true ) ; } } ,
2011-10-07 16:03:25 +02:00
2012-02-16 15:25:16 +01:00
{ { Key : : Modifiers : : None , ' t ' } , [ ] ( Editor & editor , int count ) { editor . select ( std : : bind ( select_to , _1 , get_key ( ) . key , count , false ) ) ; } } ,
{ { Key : : Modifiers : : None , ' f ' } , [ ] ( Editor & editor , int count ) { editor . select ( std : : bind ( select_to , _1 , get_key ( ) . key , count , true ) ) ; } } ,
{ { Key : : Modifiers : : None , ' T ' } , [ ] ( Editor & editor , int count ) { editor . select ( std : : bind ( select_to , _1 , get_key ( ) . key , count , false ) , true ) ; } } ,
{ { Key : : Modifiers : : None , ' F ' } , [ ] ( Editor & editor , int count ) { editor . select ( std : : bind ( select_to , _1 , get_key ( ) . key , count , 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-02-02 21:48:03 +01:00
{ { Key : : Modifiers : : None , ' i ' } , [ ] ( Editor & editor , int count ) { do_insert ( editor , IncrementalInserter : : Mode : : Insert ) ; } } ,
{ { Key : : Modifiers : : None , ' I ' } , [ ] ( Editor & editor , int count ) { do_insert ( editor , IncrementalInserter : : Mode : : InsertAtLineBegin ) ; } } ,
{ { Key : : Modifiers : : None , ' a ' } , [ ] ( Editor & editor , int count ) { do_insert ( editor , IncrementalInserter : : Mode : : Append ) ; } } ,
{ { Key : : Modifiers : : None , ' A ' } , [ ] ( Editor & editor , int count ) { do_insert ( editor , IncrementalInserter : : Mode : : AppendAtLineEnd ) ; } } ,
{ { Key : : Modifiers : : None , ' o ' } , [ ] ( Editor & editor , int count ) { do_insert ( editor , IncrementalInserter : : Mode : : OpenLineBelow ) ; } } ,
{ { Key : : Modifiers : : None , ' O ' } , [ ] ( Editor & editor , int count ) { do_insert ( editor , 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 } ,
{ { Key : : Modifiers : : None , ' p ' } , do_paste < true > } ,
{ { Key : : Modifiers : : None , ' P ' } , do_paste < false > } ,
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-02-07 15:26:51 +01:00
{ { Key : : Modifiers : : None , ' % ' } , [ ] ( Editor & editor , int count ) { editor . clear_selections ( ) ; editor . select ( select_whole_buffer ) ; } } ,
2011-09-24 15:45:25 +02:00
2012-02-02 21:48:03 +01:00
{ { Key : : Modifiers : : None , ' : ' } , [ ] ( Editor & editor , int count ) { do_command ( ) ; } } ,
2011-12-28 20:04:06 +01:00
{ { Key : : Modifiers : : None , ' | ' } , do_pipe } ,
2012-02-02 21:48:03 +01:00
{ { Key : : Modifiers : : None , ' ' } , [ ] ( Editor & editor , int count ) { if ( count = = 0 ) editor . clear_selections ( ) ;
else editor . keep_selection ( count - 1 ) ; } } ,
2012-05-29 13:15:43 +02:00
{ { Key : : Modifiers : : Alt , ' ' } , [ ] ( Editor & editor , int count ) { if ( count = = 0 ) editor . clear_selections ( ) ;
else editor . remove_selection ( count - 1 ) ; } } ,
2012-03-07 20:20:32 +01:00
{ { Key : : Modifiers : : None , ' w ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_next_word < false > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' e ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_next_word_end < false > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' b ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_previous_word < false > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' W ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_next_word < false > , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' E ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_next_word_end < false > , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' B ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_previous_word < false > , true ) ; } while ( - - count > 0 ) ; } } ,
2012-02-02 21:48:03 +01:00
{ { Key : : Modifiers : : None , ' x ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_line , false ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' X ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_line , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' m ' } , [ ] ( Editor & editor , int count ) { editor . select ( select_matching ) ; } } ,
{ { Key : : Modifiers : : None , ' M ' } , [ ] ( Editor & editor , int count ) { editor . select ( select_matching , true ) ; } } ,
2012-02-28 21:50:47 +01:00
{ { Key : : Modifiers : : None , ' / ' } , [ ] ( Editor & editor , int count ) { do_search < false > ( editor ) ; } } ,
{ { Key : : Modifiers : : None , ' ? ' } , [ ] ( Editor & editor , int count ) { do_search < true > ( editor ) ; } } ,
{ { Key : : Modifiers : : None , ' n ' } , [ ] ( Editor & editor , int count ) { do_search_next < false > ( editor ) ; } } ,
{ { Key : : Modifiers : : None , ' N ' } , [ ] ( Editor & editor , int count ) { do_search_next < true > ( editor ) ; } } ,
2012-02-16 15:25:16 +01:00
{ { Key : : Modifiers : : None , ' u ' } , [ ] ( Editor & editor , int count ) { do { if ( not editor . undo ( ) ) { NCurses : : print_status ( " nothing left to undo " ) ; break ; } } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : None , ' U ' } , [ ] ( Editor & editor , int count ) { do { if ( not editor . redo ( ) ) { NCurses : : 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-02-16 15:25:16 +01:00
{ { Key : : Modifiers : : Alt , ' t ' } , [ ] ( Editor & editor , int count ) { editor . select ( std : : bind ( select_to_reverse , _1 , get_key ( ) . key , count , false ) ) ; } } ,
{ { Key : : Modifiers : : Alt , ' f ' } , [ ] ( Editor & editor , int count ) { editor . select ( std : : bind ( select_to_reverse , _1 , get_key ( ) . key , count , true ) ) ; } } ,
{ { Key : : Modifiers : : Alt , ' T ' } , [ ] ( Editor & editor , int count ) { editor . select ( std : : bind ( select_to_reverse , _1 , get_key ( ) . key , count , false ) , true ) ; } } ,
{ { Key : : Modifiers : : Alt , ' F ' } , [ ] ( Editor & editor , int count ) { editor . select ( std : : bind ( select_to_reverse , _1 , get_key ( ) . key , count , true ) , true ) ; } } ,
2011-12-21 15:29:28 +01:00
2012-03-07 20:20:32 +01:00
{ { Key : : Modifiers : : Alt , ' w ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_next_word < true > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' e ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_next_word_end < true > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' b ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_previous_word < true > ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' W ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_next_word < true > , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' E ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_next_word_end < true > , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' B ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_previous_word < true > , true ) ; } while ( - - count > 0 ) ; } } ,
2011-12-21 15:29:28 +01:00
2012-02-02 21:48:03 +01:00
{ { Key : : Modifiers : : Alt , ' l ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_eol , false ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' L ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_eol , true ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' h ' } , [ ] ( Editor & editor , int count ) { do { editor . select ( select_to_eol_reverse , false ) ; } while ( - - count > 0 ) ; } } ,
{ { Key : : Modifiers : : Alt , ' H ' } , [ ] ( Editor & editor , int count ) { do { 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-02-07 15:26:51 +01:00
{ { Key : : Modifiers : : Alt , ' x ' } , [ ] ( Editor & editor , int count ) { 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-02-16 15:25:16 +01:00
NCurses : : init ( prompt_func , get_key_func ) ;
2011-09-23 16:29:42 +02:00
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 ;
2012-04-03 14:01:01 +02:00
GlobalHookManager hook_manager ;
2012-04-03 15:39:20 +02:00
GlobalOptionManager option_manager ;
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 " ,
[ ] ( const Context & context )
{ return context . buffer ( ) . name ( ) ; } ) ;
2012-05-07 08:56:53 +02:00
shell_manager . register_env_var ( " selection " ,
[ ] ( const Context & context )
{ return context . window ( ) . selections_content ( ) . back ( ) ; } ) ;
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-11-27 13:59:59 +01:00
try
{
2012-05-07 05:13:34 +02:00
command_manager . execute ( " runtime kakrc " , main_context ) ;
2011-11-27 13:59:59 +01:00
}
2012-05-29 12:39:03 +02:00
catch ( Kakoune : : runtime_error & error )
2011-11-27 13:59:59 +01:00
{
2012-02-16 15:25:16 +01:00
NCurses : : print_status ( error . description ( ) ) ;
2011-11-27 13:59:59 +01:00
}
2011-09-02 18:51:20 +02:00
try
{
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-02-16 15:25:16 +01:00
NCurses : : 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-01-15 22:33:35 +01:00
it - > second ( main_context . window ( ) , count ) ;
2012-02-16 15:25:16 +01:00
NCurses : : 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-02-16 15:25:16 +01:00
NCurses : : print_status ( error . description ( ) ) ;
2011-09-02 18:51:20 +02:00
}
}
2012-02-16 15:25:16 +01:00
NCurses : : deinit ( ) ;
2011-09-02 18:51:20 +02:00
}
2011-09-09 21:24:18 +02:00
catch ( Kakoune : : exception & error )
{
2012-02-16 15:25:16 +01:00
NCurses : : deinit ( ) ;
2011-09-09 21:24:18 +02:00
puts ( " uncaught exception: \n " ) ;
puts ( error . description ( ) . c_str ( ) ) ;
return - 1 ;
}
2011-09-02 19:05:44 +02:00
catch ( . . . )
2011-09-02 18:51:20 +02:00
{
2012-02-16 15:25:16 +01:00
NCurses : : deinit ( ) ;
2011-09-02 19:05:44 +02:00
throw ;
2011-09-02 18:51:20 +02:00
}
return 0 ;
}