mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-18 13:54:36 -05:00
Add flexible configuration for launching
* You can now specify links: {terminal} -e bash -e "{ssh-client} {host}" * Add test for this code.
This commit is contained in:
parent
5f33d506b9
commit
0462811800
14 changed files with 274 additions and 129 deletions
|
@ -31,6 +31,7 @@ rofi_SOURCES=\
|
|||
source/script-dialog.c\
|
||||
source/history.c\
|
||||
config/config.c\
|
||||
source/helper.c\
|
||||
include/rofi.h\
|
||||
include/run-dialog.h\
|
||||
include/ssh-dialog.h\
|
||||
|
@ -38,7 +39,8 @@ rofi_SOURCES=\
|
|||
include/script-dialog.h\
|
||||
include/xrmoptions.h\
|
||||
include/history.h\
|
||||
include/textbox.h
|
||||
include/textbox.h\
|
||||
include/helper.h
|
||||
|
||||
##
|
||||
# Manpage
|
||||
|
|
|
@ -58,6 +58,12 @@ Settings config = {
|
|||
.menu_bc = "black",
|
||||
// Terminal to use. (for ssh and open in terminal)
|
||||
.terminal_emulator = "x-terminal-emulator",
|
||||
.ssh_client = "ssh",
|
||||
// Command when executing ssh.
|
||||
.ssh_command = "{terminal} -e {ssh-client} {host}",
|
||||
// Command when running
|
||||
.run_command = "{cmd}",
|
||||
.run_shell_command = "{terminal} -e {cmd}",
|
||||
// Key binding
|
||||
.window_key = "F12",
|
||||
.run_key = "mod1+F2",
|
||||
|
@ -68,7 +74,6 @@ Settings config = {
|
|||
.hmode = FALSE,
|
||||
// Padding of the window.
|
||||
.padding = 5,
|
||||
.ssh_set_title = TRUE,
|
||||
.y_offset = 0,
|
||||
.x_offset = 0,
|
||||
.fixed_num_lines = FALSE,
|
||||
|
|
|
@ -10,8 +10,9 @@ rofi - A window switcher, run dialog and dmenu replacement
|
|||
[ -bg *color* ] [ -hlfg *color* ] [ -hlbg *color* ] [ -key *combo* ] [ -dkey *comdo* ] [ -rkey *comdo* ]
|
||||
[ -terminal *terminal* ] [ -location *position* ] [ -hmode ] [ -fixed-num-lines ] [ -padding *padding* ]
|
||||
[ -opacity *opacity%* ] [ -display *display* ] [ -bc *color* ] [ -bw *width* ] [ -dmenu [ -p *prompt* ] ]
|
||||
[ -ssh-set-title *true|false* ] [ -now ] [ -rnow ] [ -snow ] [ -version ] [ -help] [ -dump-xresources ]
|
||||
[ -disable-history ] [ -levenshtein-sort ] [ -show *mode* ] [ -switcher *mode1,mode2* ] [ -e *message*]
|
||||
[ -ssh-client *client* ] [ -ssh-command *command* ] [ -now ] [ -rnow ] [ -snow ] [ -version ]
|
||||
[ -help] [ -dump-xresources ] [ -disable-history ] [ -levenshtein-sort ] [ -show *mode* ] [ -switcher
|
||||
*mode1,mode2* ] [ -e *message*]
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
|
@ -220,6 +221,26 @@ The default key combinations are:
|
|||
Not all terminals support this.
|
||||
Default value is true.
|
||||
|
||||
*This command has been deprecated for the ssh-command string*
|
||||
|
||||
`-ssh-command` *cmd*
|
||||
|
||||
Set the command to execute when starting a ssh session.
|
||||
|
||||
`-run-command` *cmd*
|
||||
|
||||
Set the command to execute when running an application.
|
||||
See *PATTERN*.
|
||||
|
||||
`-run-shell-command` *cmd*
|
||||
|
||||
Set the command to execute when running an application in a shell.
|
||||
See *PATTERN*.
|
||||
|
||||
`-ssh-client` *client*
|
||||
|
||||
Override the used ssh client. Default is `ssh`.
|
||||
|
||||
`-disable-history`
|
||||
|
||||
Disable history
|
||||
|
@ -260,6 +281,15 @@ The default key combinations are:
|
|||
|
||||
Popup a message dialog (used internally for showing errors) with *message*.
|
||||
|
||||
## Pattern
|
||||
|
||||
To launch commands (e.g. when using the ssh dialog) the user can enter the used commandline,
|
||||
the following keys can be used that will be replaced at runtime:
|
||||
|
||||
* `{host}`: The host to connect to.
|
||||
* `{terminal}`: The configured terminal (See -terminal-emulator)
|
||||
* `{ssh-client}`: The configured ssh client (See -ssh-client)
|
||||
* `{cmd}`: The command to execute.
|
||||
|
||||
## Keybindings
|
||||
|
||||
|
|
6
include/helper.h
Normal file
6
include/helper.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef __HELPER_H__
|
||||
#define __HELPER_H__
|
||||
|
||||
int helper_parse_setup ( char * string, char ***output, int *lenght, ... );
|
||||
|
||||
#endif // __HELPER_H__
|
|
@ -106,6 +106,13 @@ typedef struct _Settings
|
|||
char * menu_bc;
|
||||
// Behavior
|
||||
char * terminal_emulator;
|
||||
char * ssh_client;
|
||||
|
||||
// Command to execute when ssh session is selected.
|
||||
char * ssh_command;
|
||||
// Command for executing an application.
|
||||
char * run_command;
|
||||
char * run_shell_command;
|
||||
|
||||
// Key bindings
|
||||
char * window_key;
|
||||
|
@ -117,7 +124,6 @@ typedef struct _Settings
|
|||
int y_offset;
|
||||
int x_offset;
|
||||
|
||||
unsigned int ssh_set_title;
|
||||
unsigned int fixed_num_lines;
|
||||
|
||||
unsigned int disable_history;
|
||||
|
|
73
source/helper.c
Normal file
73
source/helper.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include <glib.h>
|
||||
#include <rofi.h>
|
||||
#include <helper.h>
|
||||
#include <config.h>
|
||||
|
||||
/**
|
||||
* Replace the entries
|
||||
*/
|
||||
static gboolean helper_eval_cb ( const GMatchInfo *info,
|
||||
GString *res,
|
||||
gpointer data )
|
||||
{
|
||||
gchar *match;
|
||||
gchar *r;
|
||||
|
||||
match = g_match_info_fetch ( info, 0 );
|
||||
r = g_hash_table_lookup ( (GHashTable *) data, match );
|
||||
if ( r != NULL ) {
|
||||
g_string_append ( res, r );
|
||||
g_free ( match );
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int helper_parse_setup ( char * string, char ***output, int *length, ... )
|
||||
{
|
||||
GError *error = NULL;
|
||||
GHashTable *h;
|
||||
h = g_hash_table_new ( g_str_hash, g_str_equal );
|
||||
g_hash_table_insert ( h, "{terminal}", config.terminal_emulator );
|
||||
g_hash_table_insert ( h, "{ssh-client}", config.ssh_client );
|
||||
// Add list.
|
||||
va_list ap;
|
||||
va_start ( ap, length );
|
||||
while ( 1 ) {
|
||||
char * key = va_arg ( ap, char * );
|
||||
if ( key == NULL ) {
|
||||
break;
|
||||
}
|
||||
char *value = va_arg ( ap, char * );
|
||||
if ( value == NULL ) {
|
||||
break;
|
||||
}
|
||||
g_hash_table_insert ( h, key, value );
|
||||
}
|
||||
va_end ( ap );
|
||||
|
||||
// Replace hits within {-\w+}.
|
||||
GRegex *reg = g_regex_new ( "{[-\\w]+}", 0, 0, NULL );
|
||||
char *res = g_regex_replace_eval ( reg,
|
||||
string, -1,
|
||||
0, 0, helper_eval_cb, h,
|
||||
NULL );
|
||||
g_regex_unref ( reg );
|
||||
g_hash_table_destroy ( h );
|
||||
if ( g_shell_parse_argv ( res, length, output, &error ) ) {
|
||||
g_free ( res );
|
||||
return TRUE;
|
||||
}
|
||||
g_free ( res );
|
||||
if ( error ) {
|
||||
char *msg = g_strdup_printf ( "Failed to parse: '%s'\nError: '%s'", string,
|
||||
error->message );
|
||||
#ifdef error_dialog
|
||||
error_dialog ( msg );
|
||||
#endif
|
||||
g_free ( msg );
|
||||
// print error.
|
||||
g_error_free ( error );
|
||||
}
|
||||
return FALSE;
|
||||
}
|
|
@ -1070,7 +1070,7 @@ static void menu_calculate_window_and_element_width ( MenuState *state, workarea
|
|||
state->w -= config.menu_bw * 2;
|
||||
}
|
||||
|
||||
if(state->columns > 0 ) {
|
||||
if ( state->columns > 0 ) {
|
||||
state->element_width = state->w - ( 2 * ( config.padding ) );
|
||||
// Divide by the # columns
|
||||
state->element_width = ( state->element_width - ( state->columns - 1 ) * LINE_MARGIN ) / state->columns;
|
||||
|
@ -1678,7 +1678,7 @@ void error_dialog ( char *msg )
|
|||
.quit = FALSE,
|
||||
.filtered_lines = 0,
|
||||
.columns = 0,
|
||||
.update =TRUE,
|
||||
.update = TRUE,
|
||||
};
|
||||
workarea mon;
|
||||
// Get active monitor size.
|
||||
|
@ -1714,8 +1714,7 @@ void error_dialog ( char *msg )
|
|||
XMapRaised ( display, main_window );
|
||||
|
||||
if ( take_keyboard ( main_window ) ) {
|
||||
|
||||
while(!state.quit) {
|
||||
while ( !state.quit ) {
|
||||
// Update if requested.
|
||||
if ( state.update ) {
|
||||
textbox_draw ( state.text );
|
||||
|
@ -2154,16 +2153,10 @@ static void parse_cmd_options ( int argc, char ** argv )
|
|||
config.hmode = TRUE;
|
||||
}
|
||||
|
||||
if ( find_arg ( argc, argv, "-ssh-set-title" ) >= 0 ) {
|
||||
char *value;
|
||||
find_arg_str ( argc, argv, "-ssh-set-title", &value );
|
||||
if ( strcasecmp ( value, "true" ) == 0 ) {
|
||||
config.ssh_set_title = TRUE;
|
||||
}
|
||||
else{
|
||||
config.ssh_set_title = FALSE;
|
||||
}
|
||||
}
|
||||
find_arg_str ( argc, argv, "-ssh-client", &( config.ssh_client ) );
|
||||
find_arg_str ( argc, argv, "-ssh-command", &( config.ssh_command ) );
|
||||
find_arg_str ( argc, argv, "-run-command", &( config.run_command ) );
|
||||
find_arg_str ( argc, argv, "-run-shell-command", &( config.run_shell_command ) );
|
||||
|
||||
// Keybindings
|
||||
find_arg_str ( argc, argv, "-key", &( config.window_key ) );
|
||||
|
@ -2361,14 +2354,14 @@ int main ( int argc, char *argv[] )
|
|||
#endif
|
||||
|
||||
char *msg = NULL;
|
||||
if ( find_arg_str ( argc, argv, "-e", &(msg) ) ) {
|
||||
if ( find_arg_str ( argc, argv, "-e", &( msg ) ) ) {
|
||||
textbox_setup (
|
||||
config.menu_bg, config.menu_fg,
|
||||
config.menu_hlbg,
|
||||
config.menu_hlfg );
|
||||
error_dialog(msg);
|
||||
error_dialog ( msg );
|
||||
textbox_cleanup ();
|
||||
exit (EXIT_SUCCESS);
|
||||
exit ( EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include "rofi.h"
|
||||
#include "helper.h"
|
||||
#include "history.h"
|
||||
#include "run-dialog.h"
|
||||
#ifdef TIMING
|
||||
|
@ -49,29 +50,25 @@
|
|||
|
||||
static inline void execsh ( const char *cmd, int run_in_term )
|
||||
{
|
||||
char **args = g_malloc_n ( 6, sizeof ( char* ) );
|
||||
int i = 0;
|
||||
char **args = NULL;
|
||||
int argc = 0;
|
||||
if ( run_in_term ) {
|
||||
args[i++] = g_strdup ( config.terminal_emulator );
|
||||
args[i++] = g_strdup ( "-e" );
|
||||
helper_parse_setup ( config.run_shell_command, &args, &argc, "{cmd}", cmd, NULL );
|
||||
}
|
||||
else {
|
||||
helper_parse_setup ( config.run_command, &args, &argc, "{cmd}", cmd, NULL );
|
||||
}
|
||||
args[i++] = g_strdup ( "sh" );
|
||||
args[i++] = g_strdup ( "-c" );
|
||||
args[i++] = g_strdup ( cmd );
|
||||
args[i++] = NULL;
|
||||
|
||||
GError *error = NULL;
|
||||
g_spawn_async ( NULL, args, NULL,
|
||||
G_SPAWN_SEARCH_PATH,
|
||||
NULL, NULL, NULL, &error );
|
||||
if( error != NULL )
|
||||
{
|
||||
char *msg = g_strdup_printf("Failed to execute: '%s'\nError: '%s'", cmd,
|
||||
error->message);
|
||||
error_dialog(msg);
|
||||
g_free(msg);
|
||||
if ( error != NULL ) {
|
||||
char *msg = g_strdup_printf ( "Failed to execute: '%s'\nError: '%s'", cmd,
|
||||
error->message );
|
||||
error_dialog ( msg );
|
||||
g_free ( msg );
|
||||
// print error.
|
||||
g_error_free(error);
|
||||
g_error_free ( error );
|
||||
}
|
||||
|
||||
// Free the args list.
|
||||
|
|
|
@ -36,16 +36,15 @@
|
|||
#include <assert.h>
|
||||
#include "rofi.h"
|
||||
#include "script-dialog.h"
|
||||
#include "helper.h"
|
||||
|
||||
|
||||
|
||||
pid_t execute_generator ( char * cmd )
|
||||
{
|
||||
char **args = g_malloc_n ( 4, sizeof ( char* ) );
|
||||
args[0] = g_strdup ( "sh" );
|
||||
args[1] = g_strdup ( "-c" );
|
||||
args[2] = g_strdup ( cmd );
|
||||
args[3] = NULL;
|
||||
char **args = NULL;
|
||||
int argv = 0;
|
||||
helper_parse_setup ( config.run_command, &args, &argv, "{cmd}", cmd, NULL );
|
||||
|
||||
int fd = -1;
|
||||
GError *error = NULL;
|
||||
|
@ -59,14 +58,13 @@ pid_t execute_generator ( char * cmd )
|
|||
NULL, &fd, NULL,
|
||||
&error );
|
||||
|
||||
if( error != NULL )
|
||||
{
|
||||
char *msg = g_strdup_printf("Failed to execute: '%s'\nError: '%s'", cmd,
|
||||
error->message);
|
||||
error_dialog(msg);
|
||||
g_free(msg);
|
||||
if ( error != NULL ) {
|
||||
char *msg = g_strdup_printf ( "Failed to execute: '%s'\nError: '%s'", cmd,
|
||||
error->message );
|
||||
error_dialog ( msg );
|
||||
g_free ( msg );
|
||||
// print error.
|
||||
g_error_free(error);
|
||||
g_error_free ( error );
|
||||
}
|
||||
g_strfreev ( args );
|
||||
return fd;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <helper.h>
|
||||
|
||||
#include "rofi.h"
|
||||
#include "history.h"
|
||||
|
@ -53,31 +54,22 @@ static inline int execshssh ( const char *host )
|
|||
/**
|
||||
* I am not happy about this code, it causes 7 mallocs and frees
|
||||
*/
|
||||
char **args = g_malloc_n ( 7, sizeof ( char* ) );
|
||||
int i = 0;
|
||||
args[i++] = g_strdup ( config.terminal_emulator );
|
||||
if ( config.ssh_set_title ) {
|
||||
args[i++] = g_strdup ( "-T" );
|
||||
args[i++] = g_strdup_printf ( "ssh %s", host );
|
||||
}
|
||||
args[i++] = g_strdup ( "-e" );
|
||||
args[i++] = g_strdup ( "ssh" );
|
||||
args[i++] = g_strdup ( host );
|
||||
args[i++] = NULL;
|
||||
char **args = NULL;
|
||||
int argsv = 0;
|
||||
helper_parse_setup ( config.ssh_command, &args, &argsv, "{host}", host, NULL );
|
||||
|
||||
GError *error = NULL;
|
||||
g_spawn_async ( NULL, args, NULL,
|
||||
G_SPAWN_SEARCH_PATH,
|
||||
NULL, NULL, NULL, &error );
|
||||
|
||||
if( error != NULL )
|
||||
{
|
||||
char *msg = g_strdup_printf("Failed to execute: 'ssh %s'\nError: '%s'", host,
|
||||
error->message);
|
||||
error_dialog(msg);
|
||||
g_free(msg);
|
||||
if ( error != NULL ) {
|
||||
char *msg = g_strdup_printf ( "Failed to execute: 'ssh %s'\nError: '%s'", host,
|
||||
error->message );
|
||||
error_dialog ( msg );
|
||||
g_free ( msg );
|
||||
// print error.
|
||||
g_error_free(error);
|
||||
g_error_free ( error );
|
||||
}
|
||||
// Free the args list.
|
||||
g_strfreev ( args );
|
||||
|
@ -154,7 +146,7 @@ static char ** get_ssh ( unsigned int *length )
|
|||
;
|
||||
}
|
||||
|
||||
for ( stop = start; !isspace(buffer[stop]) ; stop++ ) {
|
||||
for ( stop = start; !isspace ( buffer[stop] ); stop++ ) {
|
||||
// We do not want to show wildcard entries, as you cannot ssh to them.
|
||||
if ( buffer[stop] == '?' || buffer[stop] == '*' ) {
|
||||
stop = start;
|
||||
|
|
|
@ -321,10 +321,11 @@ void textbox_delete ( textbox *tb, int pos, int dlen )
|
|||
// move everything after pos+dlen down
|
||||
char *at = tb->text + pos;
|
||||
// Move remainder + closing \0
|
||||
memmove ( at, at + dlen, len - pos-dlen+1 );
|
||||
if ( tb->cursor >= pos && tb->cursor < (pos+dlen) ) {
|
||||
memmove ( at, at + dlen, len - pos - dlen + 1 );
|
||||
if ( tb->cursor >= pos && tb->cursor < ( pos + dlen ) ) {
|
||||
tb->cursor = pos;
|
||||
} else if ( tb->cursor >= (pos+dlen) ) {
|
||||
}
|
||||
else if ( tb->cursor >= ( pos + dlen ) ) {
|
||||
tb->cursor -= dlen;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,8 +98,11 @@ static XrmOption xrmOptions[] = {
|
|||
|
||||
|
||||
{ xrm_String, "terminal", { .str = &config.terminal_emulator }, NULL },
|
||||
{ xrm_String, "ssh-client", { .str = &config.ssh_client }, NULL },
|
||||
{ xrm_String, "ssh-command", { .str = &config.ssh_command }, NULL },
|
||||
{ xrm_String, "run-command", { .str = &config.run_command }, NULL },
|
||||
{ xrm_String, "run-shell-command", { .str = &config.run_shell_command }, NULL },
|
||||
|
||||
{ xrm_Boolean, "ssh-set-title", { .num = &config.ssh_set_title }, NULL },
|
||||
{ xrm_Boolean, "disable-history", { .num = &config.disable_history }, NULL },
|
||||
{ xrm_Boolean, "levenshtein-sort", { .num = &config.levenshtein_sort }, NULL },
|
||||
/* Key bindings */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
##
|
||||
# Rofi the program
|
||||
##
|
||||
bin_PROGRAMS=rofi_test textbox_test
|
||||
bin_PROGRAMS=rofi_test textbox_test helper_test
|
||||
|
||||
LIBS=\
|
||||
@xft_LIBS@\
|
||||
|
@ -33,9 +33,17 @@ textbox_test_SOURCES=\
|
|||
../include/textbox.h\
|
||||
textbox-test.c
|
||||
|
||||
helper_test_SOURCES=\
|
||||
helper-test.c\
|
||||
../config/config.c\
|
||||
../include/rofi.h\
|
||||
../source/helper.c\
|
||||
../include/helper.h
|
||||
|
||||
.PHONY: test
|
||||
test: ${bin_PROGRAMS}
|
||||
./rofi_test
|
||||
./helper_test
|
||||
$(top_srcdir)/test/run_test.sh 123 $(top_builddir)/test/textbox_test $(top_builddir)
|
||||
$(top_srcdir)/test/run_test.sh 200 $(top_srcdir)/test/run_errormsg_test.sh $(top_builddir)
|
||||
$(top_srcdir)/test/run_test.sh 201 $(top_srcdir)/test/run_switchdialog_test.sh $(top_builddir)
|
||||
|
|
31
test/helper-test.c
Normal file
31
test/helper-test.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <assert.h>
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <helper.h>
|
||||
#include <string.h>
|
||||
|
||||
static int test = 0;
|
||||
|
||||
#define TASSERT(a) {\
|
||||
assert ( a );\
|
||||
printf("Test %i passed (%s)\n", ++test, #a);\
|
||||
}
|
||||
|
||||
int main ( int argc, char ** argv )
|
||||
{
|
||||
char **list = NULL;
|
||||
int llength = 0;
|
||||
char * test_str = "{host} {terminal} -e bash -c \"{ssh-client} {host}; echo '{terminal} {host}'\"";
|
||||
helper_parse_setup( test_str, &list, &llength, "{host}", "chuck",
|
||||
"{terminal}", "x-terminal-emulator", NULL);
|
||||
|
||||
TASSERT ( llength == 6 );
|
||||
TASSERT ( strcmp(list[0], "chuck") == 0 );
|
||||
TASSERT ( strcmp(list[1], "x-terminal-emulator") == 0 );
|
||||
TASSERT ( strcmp(list[2], "-e") == 0 );
|
||||
TASSERT ( strcmp(list[3], "bash") == 0 );
|
||||
TASSERT ( strcmp(list[4], "-c") == 0 );
|
||||
TASSERT ( strcmp(list[5], "ssh chuck; echo 'x-terminal-emulator chuck'") == 0 );
|
||||
|
||||
g_strfreev(list);
|
||||
}
|
Loading…
Reference in a new issue