[Run] Allow (Ctrl-L) to complete files using file-browser.

Merge old setup from #1116

issue: #1116  #659
This commit is contained in:
Dave Davenport 2021-06-01 13:14:45 +02:00
parent 3598ebe603
commit 2eefd9b191
9 changed files with 114 additions and 1 deletions

View File

@ -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\&.

View File

@ -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.

View File

@ -92,6 +92,7 @@ typedef enum
ACCEPT_ALT,
ACCEPT_CUSTOM,
MODE_NEXT,
MODE_COMPLETE,
MODE_PREVIOUS,
TOGGLE_CASE_SENSITIVITY,
DELETE_ENTRY,

View File

@ -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 */

View File

@ -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;

View File

@ -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,

View File

@ -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" },

View File

@ -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;

View File

@ -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 ) {