summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Davenport <qball@gmpclient.org>2021-06-01 13:14:45 +0200
committerDave Davenport <qball@gmpclient.org>2021-06-01 13:14:45 +0200
commit2eefd9b191ee02c78bef11c6fa4575e48e1d372d (patch)
tree2adce80970216e4acf51ec7b9dcc89dc61b93fc4
parent3598ebe60377abf2abd7fd787d61f79c0ddd58b4 (diff)
[Run] Allow (Ctrl-L) to complete files using file-browser.
Merge old setup from #1116 issue: #1116 #659
-rw-r--r--doc/rofi.12
-rw-r--r--doc/rofi.1.markdown1
-rw-r--r--include/keyb.h1
-rw-r--r--include/mode.h2
-rw-r--r--source/dialogs/filebrowser.c2
-rw-r--r--source/dialogs/run.c85
-rw-r--r--source/keyb.c1
-rw-r--r--source/rofi.c10
-rw-r--r--source/view.c11
9 files changed, 114 insertions, 1 deletions
diff --git a/doc/rofi.1 b/doc/rofi.1
index 39993312..1ab82952 100644
--- a/doc/rofi.1
+++ b/doc/rofi.1
@@ -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 ) {