diff options
author | Dave Davenport <qball@gmpclient.org> | 2021-06-01 13:14:45 +0200 |
---|---|---|
committer | Dave Davenport <qball@gmpclient.org> | 2021-06-01 13:14:45 +0200 |
commit | 2eefd9b191ee02c78bef11c6fa4575e48e1d372d (patch) | |
tree | 2adce80970216e4acf51ec7b9dcc89dc61b93fc4 | |
parent | 3598ebe60377abf2abd7fd787d61f79c0ddd58b4 (diff) |
[Run] Allow (Ctrl-L) to complete files using file-browser.
Merge old setup from #1116
issue: #1116 #659
-rw-r--r-- | doc/rofi.1 | 2 | ||||
-rw-r--r-- | doc/rofi.1.markdown | 1 | ||||
-rw-r--r-- | include/keyb.h | 1 | ||||
-rw-r--r-- | include/mode.h | 2 | ||||
-rw-r--r-- | source/dialogs/filebrowser.c | 2 | ||||
-rw-r--r-- | source/dialogs/run.c | 85 | ||||
-rw-r--r-- | source/keyb.c | 1 | ||||
-rw-r--r-- | source/rofi.c | 10 | ||||
-rw-r--r-- | source/view.c | 11 |
9 files changed, 114 insertions, 1 deletions
@@ -1369,6 +1369,8 @@ Please see rofi\-theme(5) manpage for more information on themeing. \fB\fCAlt\-grave\fR: Toggle sorting. .IP \(bu 2 \fB\fCAlt\-Shift\-S\fR: Take a screenshot and store it in the Pictures directory. +.IP \(bu 2 +\fB\fCCtrl\-l\fR: File complete for run dialog. .PP To get a full list of key bindings on the commandline, see \fB\fCrofi \-h\fR\&. diff --git a/doc/rofi.1.markdown b/doc/rofi.1.markdown index 96863421..433e6438 100644 --- a/doc/rofi.1.markdown +++ b/doc/rofi.1.markdown @@ -836,6 +836,7 @@ Please see rofi-theme(5) manpage for more information on themeing. * `grave`: Toggle case sensitivity. * `Alt-grave`: Toggle sorting. * `Alt-Shift-S`: Take a screenshot and store it in the Pictures directory. + * `Ctrl-l`: File complete for run dialog. To get a full list of key bindings on the commandline, see `rofi -h`. The options starting with `-kb` are keybindings. diff --git a/include/keyb.h b/include/keyb.h index 1f5259ea..398376e7 100644 --- a/include/keyb.h +++ b/include/keyb.h @@ -92,6 +92,7 @@ typedef enum ACCEPT_ALT, ACCEPT_CUSTOM, MODE_NEXT, + MODE_COMPLETE, MODE_PREVIOUS, TOGGLE_CASE_SENSITIVITY, DELETE_ENTRY, diff --git a/include/mode.h b/include/mode.h index fd4f8ae6..080eaccd 100644 --- a/include/mode.h +++ b/include/mode.h @@ -81,6 +81,8 @@ typedef enum MENU_CUSTOM_COMMAND = 0x00800000, /** Go to the previous menu. */ MENU_PREVIOUS = 0x00400000, + /** Go to the complete. */ + MENU_COMPLETE = 0x01000000, /** Bindings specifics */ MENU_CUSTOM_ACTION = 0x10000000, /** Mask */ diff --git a/source/dialogs/filebrowser.c b/source/dialogs/filebrowser.c index c9637285..a1a2807e 100644 --- a/source/dialogs/filebrowser.c +++ b/source/dialogs/filebrowser.c @@ -401,7 +401,7 @@ Mode *create_new_file_browser ( void ) return sw; } -#if 0 +#if 1 ModeMode file_browser_mode_completer ( Mode *sw, int mretv, char **input, unsigned int selected_line, char **path ) { ModeMode retv = MODE_EXIT; diff --git a/source/dialogs/run.c b/source/dialogs/run.c index a4aa7bc1..029bbc1d 100644 --- a/source/dialogs/run.c +++ b/source/dialogs/run.c @@ -51,6 +51,7 @@ #include "helper.h" #include "history.h" #include "dialogs/run.h" +#include "dialogs/filebrowser.h" #include "mode-private.h" @@ -70,6 +71,14 @@ typedef struct char **cmd_list; /** Length of the #cmd_list. */ unsigned int cmd_list_length; + + /** Current mode. */ + gboolean file_complete; + uint32_t selected_line; + char *old_input; + + Mode *completer; + char *old_completer_input; } RunModePrivateData; /** @@ -347,6 +356,8 @@ static int run_mode_init ( Mode *sw ) RunModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); sw->private_data = (void *) pd; pd->cmd_list = get_apps ( &( pd->cmd_list_length ) ); + pd->completer = create_new_file_browser (); + mode_init ( pd->completer ); } return TRUE; @@ -356,6 +367,9 @@ static void run_mode_destroy ( Mode *sw ) RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data; if ( rmpd != NULL ) { g_strfreev ( rmpd->cmd_list ); + g_free ( rmpd->old_input ); + g_free ( rmpd->old_completer_input ); + mode_destroy ( rmpd->completer ); g_free ( rmpd ); sw->private_data = NULL; } @@ -364,6 +378,9 @@ static void run_mode_destroy ( Mode *sw ) static unsigned int run_mode_get_num_entries ( const Mode *sw ) { const RunModePrivateData *rmpd = (const RunModePrivateData *) sw->private_data; + if ( rmpd->file_complete ){ + return rmpd->completer->_get_num_entries( rmpd->completer ); + } return rmpd->cmd_list_length; } @@ -373,6 +390,38 @@ static ModeMode run_mode_result ( Mode *sw, int mretv, char **input, unsigned in ModeMode retv = MODE_EXIT; gboolean run_in_term = ( ( mretv & MENU_CUSTOM_ACTION ) == MENU_CUSTOM_ACTION ); + if ( rmpd->file_complete == TRUE ) { + + retv = RELOAD_DIALOG; + + if ( ( mretv& (MENU_COMPLETE)) ) { + g_free ( rmpd->old_completer_input ); + rmpd->old_completer_input = *input; + *input = NULL; + if ( rmpd->selected_line < rmpd->cmd_list_length ) { + (*input) = g_strdup ( rmpd->old_input ); + } + rmpd->file_complete = FALSE; + } else if ( (mretv&MENU_CANCEL) ) { + retv = MODE_EXIT; + } else { + char *path = NULL; + retv = file_browser_mode_completer ( rmpd->completer, mretv, input, selected_line, &path ); + if ( retv == MODE_EXIT ) { + if ( path == NULL ) + { + exec_cmd ( rmpd->cmd_list[rmpd->selected_line], run_in_term ); + } else { + char *arg= g_strdup_printf ( "%s '%s'", rmpd->cmd_list[rmpd->selected_line], path); + exec_cmd ( arg, run_in_term ); + g_free(arg); + } + + } + g_free (path); + } + return retv; + } if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line] != NULL ) { if ( !exec_cmd ( rmpd->cmd_list[selected_line], run_in_term ) ) { @@ -394,6 +443,19 @@ static ModeMode run_mode_result ( Mode *sw, int mretv, char **input, unsigned in } else if ( mretv & MENU_CUSTOM_COMMAND ) { retv = ( mretv & MENU_LOWER_MASK ); + } else if ( ( mretv& MENU_COMPLETE) ) { + retv = RELOAD_DIALOG; + if ( selected_line < rmpd->cmd_list_length ) { + rmpd->selected_line = selected_line; + + g_free ( rmpd->old_input ); + rmpd->old_input = g_strdup ( *input ); + + if ( *input ) g_free (*input); + *input = g_strdup ( rmpd->old_completer_input ); + + rmpd->file_complete = TRUE; + } } return retv; } @@ -401,14 +463,36 @@ static ModeMode run_mode_result ( Mode *sw, int mretv, char **input, unsigned in static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **list, int get_entry ) { const RunModePrivateData *rmpd = (const RunModePrivateData *) sw->private_data; + if ( rmpd->file_complete ){ + return rmpd->completer->_get_display_value (rmpd->completer, selected_line, state, list, get_entry ); + } return get_entry ? g_strdup ( rmpd->cmd_list[selected_line] ) : NULL; } static int run_token_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index ) { const RunModePrivateData *rmpd = (const RunModePrivateData *) sw->private_data; + if ( rmpd->file_complete ){ + return rmpd->completer->_token_match (rmpd->completer, tokens, index ); + } return helper_token_match ( tokens, rmpd->cmd_list[index] ); } +static char *run_get_message ( const Mode *sw ) +{ + RunModePrivateData *pd = sw->private_data; + if ( pd->file_complete ) { + if ( pd->selected_line < pd->cmd_list_length ) { + char *msg = mode_get_message ( pd->completer); + if (msg ){ + char *retv = g_strdup_printf("File complete for: %s\n%s", pd->cmd_list[pd->selected_line], msg); + g_free (msg); + return retv; + } + return g_strdup_printf("File complete for: %s", pd->cmd_list[pd->selected_line]); + } + } + return NULL; +} #include "mode-private.h" Mode run_mode = @@ -420,6 +504,7 @@ Mode run_mode = ._result = run_mode_result, ._destroy = run_mode_destroy, ._token_match = run_token_match, + ._get_message = run_get_message, ._get_display_value = _get_display_value, ._get_icon = NULL, ._get_completion = NULL, diff --git a/source/keyb.c b/source/keyb.c index 7a8c09b1..3bd51841 100644 --- a/source/keyb.c +++ b/source/keyb.c @@ -66,6 +66,7 @@ ActionBindingEntry rofi_bindings[] = { .id = DELETE_ENTRY, .name = "kb-delete-entry", .binding = "Shift+Delete", .comment = "Delete entry from history" }, { .id = MODE_NEXT, .name = "kb-mode-next", .binding = "Shift+Right,Control+Tab", .comment = "Switch to the next mode." }, { .id = MODE_PREVIOUS, .name = "kb-mode-previous", .binding = "Shift+Left,Control+ISO_Left_Tab", .comment = "Switch to the previous mode." }, + { .id = MODE_COMPLETE, .name = "kb-mode-complete", .binding = "Control+l", .comment = "Start completion for mode." }, { .id = ROW_LEFT, .name = "kb-row-left", .binding = "Control+Page_Up", .comment = "Go to the previous column" }, { .id = ROW_RIGHT, .name = "kb-row-right", .binding = "Control+Page_Down", .comment = "Go to the next column" }, { .id = ROW_UP, .name = "kb-row-up", .binding = "Up,Control+p,ISO_Left_Tab", .comment = "Select previous entry" }, diff --git a/source/rofi.c b/source/rofi.c index 9727f9d2..81f3e789 100644 --- a/source/rofi.c +++ b/source/rofi.c @@ -211,6 +211,16 @@ void process_result ( RofiViewState *state ) MenuReturn mretv = rofi_view_get_return_value ( state ); char *input = g_strdup ( rofi_view_get_user_input ( state ) ); ModeMode retv = mode_result ( sw, mretv, &input, selected_line ); + { + if ( state->text ){ + if ( input == NULL ) { + textbox_text ( state->text, "" ); + } else if ( strcmp ( rofi_view_get_user_input ( state ), input ) != 0 ) { + textbox_text ( state->text, input ); + textbox_cursor_end ( state->text ); + } + } + } g_free ( input ); ModeMode mode = curr_switcher; diff --git a/source/view.c b/source/view.c index f344e4eb..f09cd560 100644 --- a/source/view.c +++ b/source/view.c @@ -1272,6 +1272,17 @@ static void rofi_view_trigger_global_action ( KeyBindingAction action ) ( state->selected_line ) = 0; state->quit = TRUE; break; + case MODE_COMPLETE: + { + unsigned int selected = listview_get_selected ( state->list_view ); + state->selected_line = UINT32_MAX; + if ( selected < state->filtered_lines ) { + state->selected_line = state->line_map[selected]; + } + state->retv = MENU_COMPLETE; + state->quit = TRUE; + break; + } // Toggle case sensitivity. case TOGGLE_CASE_SENSITIVITY: if ( state->case_indicator != NULL ) { |