From 6177c90a87ce3ace794651a58a6e8fb536338d4d Mon Sep 17 00:00:00 2001 From: Qball Cow Date: Sat, 1 Feb 2014 14:03:23 +0100 Subject: [PATCH] Restructure for and add option to delete entry from history. --- include/simpleswitcher.h | 14 ++++- source/dmenu-dialog.c | 15 +++--- source/mark-dialog.c | 11 ++-- source/profile-dialog.c | 11 ++-- source/run-dialog.c | 73 +++++++++++++++++++++++-- source/simpleswitcher.c | 114 +++++++++++++++++++++++---------------- source/ssh-dialog.c | 11 ++-- source/textbox.c | 1 + 8 files changed, 175 insertions(+), 75 deletions(-) diff --git a/include/simpleswitcher.h b/include/simpleswitcher.h index d4653428..0c72a87b 100644 --- a/include/simpleswitcher.h +++ b/include/simpleswitcher.h @@ -30,11 +30,21 @@ typedef enum { NEXT_DIALOG } SwitcherMode; +typedef enum { + MENU_OK = 0, + MENU_CANCEL = -1, + MENU_NEXT = -2, + MENU_CUSTOM_INPUT = -3, + MENU_ENTRY_DELETE = -4 + +} MenuReturn; typedef int ( *menu_match_cb )( char **tokens, const char *input, int index, void *data ); -int menu( char **lines, char **input, char *prompt, - Time *time, int *shift, menu_match_cb mmc, void *mmc_data ); +MenuReturn menu( char **lines, char **input, char *prompt, + Time *time, int *shift, + menu_match_cb mmc, void *mmc_data, + int *selected_line ); /** diff --git a/source/dmenu-dialog.c b/source/dmenu-dialog.c index 22f335f5..32019a76 100644 --- a/source/dmenu-dialog.c +++ b/source/dmenu-dialog.c @@ -66,8 +66,10 @@ static char **get_dmenu ( ) while ( fgets( buffer, 1024, stdin ) != NULL ) { retv = realloc( retv, ( index+2 )*sizeof( char* ) ); retv[index] = strdup( buffer ); - if( retv[index][strlen(buffer)-1] == '\n') + + if ( retv[index][strlen( buffer )-1] == '\n' ) retv[index][strlen( buffer )-1] = '\0'; + retv[index+1] = NULL; index++; } @@ -112,13 +114,14 @@ SwitcherMode dmenu_switcher_dialog ( char **input ) } int shift=0; - int n = menu( list, input, dmenu_prompt,NULL, &shift,token_match, NULL ); + int selected_line = 0; + int mretv = menu( list, input, dmenu_prompt,NULL, &shift,token_match, NULL, &selected_line ); - if ( n == -2 ) { + if ( mretv == MENU_NEXT ) { retv = DMENU_DIALOG; - } else if ( n >=0 && list[n] != NULL ) { - fputs( list[n],stdout ); - } else if ( n == -3 && *input != NULL && *input[0] != '\0' ) { + } else if ( mretv == MENU_OK && list[selected_line] != NULL ) { + fputs( list[selected_line],stdout ); + } else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) { fputs( *input, stdout ); } diff --git a/source/mark-dialog.c b/source/mark-dialog.c index ca003461..6495fa64 100644 --- a/source/mark-dialog.c +++ b/source/mark-dialog.c @@ -271,13 +271,14 @@ SwitcherMode mark_switcher_dialog ( char **input ) } int shift=0; - int n = menu( cmd_list, input, "mark:", NULL, &shift,token_match, NULL ); + int selected_line = 0; + int mretv = menu( cmd_list, input, "mark:", NULL, &shift,token_match,NULL, &selected_line ); - if ( n == -2 ) { + if ( mretv == MENU_NEXT ) { retv = NEXT_DIALOG; - } else if ( n >=0 && cmd_list[n] != NULL ) { - exec_mark( cmd_list[n] ); - } else if ( n == -3 && *input != NULL && *input[0] != '\0' ) { + } else if ( mretv == MENU_OK && cmd_list[selected_line] != NULL ) { + exec_mark( cmd_list[selected_line] ); + } else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) { exec_mark( *input ); } diff --git a/source/profile-dialog.c b/source/profile-dialog.c index 29bd73eb..f10c6896 100644 --- a/source/profile-dialog.c +++ b/source/profile-dialog.c @@ -178,14 +178,13 @@ SwitcherMode profile_switcher_dialog ( char **input ) } int shift=0; - int n = menu( cmd_list, input, "profile:", NULL, &shift,token_match, NULL ); + int selected_line = 0; + int retvm = menu( cmd_list, input, "profile:", NULL, &shift,token_match, NULL, &selected_line ); - if ( n == -2 ) { + if ( retvm == MENU_NEXT ) { retv = NEXT_DIALOG; - } else if ( n >=0 && cmd_list[n] != NULL ) { - exec_profile( cmd_list[n] ); - } else if ( n == -3 && *input != NULL && *input[0] != '\0' ) { - exec_profile( *input ); + } else if ( retvm == MENU_OK && cmd_list[selected_line] != NULL ) { + exec_profile( cmd_list[selected_line] ); } for ( int i=0; cmd_list[i] != NULL; i++ ) { diff --git a/source/run-dialog.c b/source/run-dialog.c index 8fe9c982..5f9eeacb 100644 --- a/source/run-dialog.c +++ b/source/run-dialog.c @@ -128,6 +128,66 @@ static pid_t exec_cmd( const char *cmd, int run_in_term ) return pid; } +// execute sub-process +static void delete_entry( const char *cmd ) +{ + int curr = -1; + unsigned int index = 0; + char **retv = NULL; + + printf( "Delete entry: %s\n", cmd ); + + /** + * This happens in non-critical time (After launching app) + * It is allowed to be a bit slower. + */ + char *path = allocate( strlen( cache_dir ) + strlen( RUN_CACHE_FILE )+3 ); + sprintf( path, "%s/%s", cache_dir, RUN_CACHE_FILE ); + FILE *fd = fopen ( path, "r" ); + char buffer[1024]; + + if ( fd != NULL ) { + while ( fgets( buffer,1024,fd ) != NULL ) { + retv = realloc( retv, ( index+2 )*sizeof( char* ) ); + buffer[strlen( buffer )-1] = '\0'; + retv[index] = strdup( buffer ); + retv[index+1] = NULL; + + if ( strcasecmp( retv[index], cmd ) == 0 ) { + curr = index; + } + + index++; + } + + fclose( fd ); + } + + /** + * Write out the last 25 results again. + */ + fd = fopen ( path, "w" ); + + if ( fd ) { + for ( int i = 0; i < ( int )index && i < 20; i++ ) { + if ( i != curr ) { + fputs( retv[i], fd ); + fputc( '\n', fd ); + } + } + + fclose( fd ); + } + + for ( int i=0; retv[i] != NULL; i++ ) { + free( retv[i] ); + } + + free( retv ); + + free( path ); + +} static int sort_func ( const void *a, const void *b ) { const char *astr = *( const char * const * )a; @@ -247,14 +307,17 @@ SwitcherMode run_switcher_dialog ( char **input ) } int shift=0; - int n = menu( cmd_list, input, "$", NULL, &shift,token_match, NULL ); + int selected_line = 0; + int mretv = menu( cmd_list, input, "$", NULL, &shift,token_match, NULL, &selected_line ); - if ( n == -2 ) { + if ( mretv == MENU_NEXT ) { retv = NEXT_DIALOG; - } else if ( n >=0 && cmd_list[n] != NULL ) { - exec_cmd( cmd_list[n], shift ); - } else if ( n == -3 && *input != NULL && *input[0] != '\0' ) { + } else if ( mretv == MENU_OK && cmd_list[selected_line] != NULL ) { + exec_cmd( cmd_list[selected_line], shift ); + } else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) { exec_cmd( *input, shift ); + } else if ( mretv == MENU_ENTRY_DELETE && cmd_list[selected_line] ) { + delete_entry ( cmd_list[selected_line] ); } for ( int i=0; cmd_list[i] != NULL; i++ ) { diff --git a/source/simpleswitcher.c b/source/simpleswitcher.c index 22f135e9..7929a73f 100644 --- a/source/simpleswitcher.c +++ b/source/simpleswitcher.c @@ -669,17 +669,19 @@ void menu_draw( textbox *text, textbox **boxes, int max_lines,int num_lines, int // selected row is always visible. // If selected is visible do not scroll. - if((selected - (*last_offset)) < (max_lines) &&(selected-(*last_offset)) >= 0) offset = *last_offset; + if ( ( selected - ( *last_offset ) ) < ( max_lines ) &&( selected-( *last_offset ) ) >= 0 ) offset = *last_offset; else { // If selected is above visible, scroll up. - if((selected-(*last_offset)) >= (max_lines)) { + if ( ( selected-( *last_offset ) ) >= ( max_lines ) ) { offset = selected-max_lines+1; - // Scroll down otherwise - }else if ((selected-(*last_offset)) < 0){ + // Scroll down otherwise + } else if ( ( selected-( *last_offset ) ) < 0 ) { offset = selected; } + // Sanitize - if(offset >= (num_lines)) offset = num_lines-max_lines-1; + if ( offset >= ( num_lines ) ) offset = num_lines-max_lines-1; + *last_offset = offset; } @@ -691,8 +693,8 @@ void menu_draw( textbox *text, textbox **boxes, int max_lines,int num_lines, int textbox_text( boxes[i], "" ); } else { textbox_font( boxes[i], config.menu_font, - (i+offset) == selected ? config.menu_hlfg: config.menu_fg, - (i+offset) == selected ? config.menu_hlbg: config.menu_bg ); + ( i+offset ) == selected ? config.menu_hlfg: config.menu_fg, + ( i+offset ) == selected ? config.menu_hlbg: config.menu_bg ); textbox_text( boxes[i], filtered[i+offset] ); } @@ -761,10 +763,10 @@ int window_match ( char **tokens, __attribute__( ( unused ) )const char *input, return match; } -int menu( char **lines, char **input, char *prompt, Time *time, int *shift, - menu_match_cb mmc, void *mmc_data ) +MenuReturn menu( char **lines, char **input, char *prompt, Time *time, int *shift, + menu_match_cb mmc, void *mmc_data, int *selected_line ) { - int line = -1, chosen = 0; + int retv = MENU_CANCEL; unsigned int i,j; workarea mon; monitor_active( &mon ); @@ -963,8 +965,16 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, if ( ( ( ev.xkey.state&ShiftMask ) == ShiftMask ) && key == XK_slash ) { - line = -2; + retv = MENU_NEXT; + *selected_line = 0; break; + } else if ( ( ( ev.xkey.state&ShiftMask ) == ShiftMask ) && + key == XK_Delete ) { + if ( filtered[selected] != NULL ) { + *selected_line = line_map[selected]; + retv = MENU_ENTRY_DELETE; + break; + } } int rc = textbox_keypress( text, &ev ); @@ -973,7 +983,13 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, if ( shift != NULL ) ( *shift ) = ( ( ev.xkey.state&ShiftMask ) == ShiftMask ); - chosen = 1; + if ( filtered[selected] ) { + retv = MENU_OK; + *selected_line = line_map[selected]; + } else { + retv = MENU_CUSTOM_INPUT; + } + break; } else if ( rc ) { char **tokens = tokenize( text->text ); @@ -997,7 +1013,14 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, filtered[j] = NULL; if ( config.zeltak_mode && filtered_lines == 1 ) { - chosen = 1; + if ( filtered[selected] ) { + retv = MENU_OK; + *selected_line = line_map[selected]; + } else { + fprintf( stderr, "We should never hit this." ); + abort(); + } + break; } @@ -1012,11 +1035,9 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, || ( ( rundialog_modmask == AnyModifier || ev.xkey.state & rundialog_modmask ) && key == rundialog_keysym ) || ( ( sshdialog_modmask == AnyModifier || ev.xkey.state & sshdialog_modmask ) && key == sshdialog_keysym ) ) { + retv = MENU_CANCEL; break; - } - - else - + } else { // Up or Shift-Tab if ( key == XK_Up || ( key == XK_Tab && ev.xkey.state & ShiftMask ) || ( key == XK_j && ev.xkey.state& ControlMask ) ) { @@ -1026,20 +1047,28 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, } else if ( key == XK_Down || ( key == XK_k && ev.xkey.state& ControlMask ) ) { selected = selected < filtered_lines-1 ? MIN( filtered_lines-1, selected+1 ): 0; - } else if ( key == XK_Page_Up) { - if(selected < max_lines) selected = 0; + } else if ( key == XK_Page_Up ) { + if ( selected < max_lines ) selected = 0; else - selected -= (max_lines-1); - } else if ( key == XK_Page_Down) { - selected += (max_lines-1); - if(selected >= num_lines) selected = num_lines-1; - } else if ( key == XK_Home || key == XK_KP_Home) { + selected -= ( max_lines-1 ); + } else if ( key == XK_Page_Down ) { + selected += ( max_lines-1 ); + + if ( selected >= num_lines ) selected = num_lines-1; + } else if ( key == XK_Home || key == XK_KP_Home ) { selected = 0; - } else if ( key == XK_End || key == XK_KP_End) { + } else if ( key == XK_End || key == XK_KP_End ) { selected = num_lines-1; } else if ( key == XK_Tab ) { if ( filtered_lines == 1 ) { - chosen = 1; + if ( filtered[selected] ) { + retv = MENU_OK; + *selected_line = line_map[selected]; + } else { + fprintf( stderr, "We should never hit this." ); + abort(); + } + break; } @@ -1052,10 +1081,11 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, textbox_text( text, str ); textbox_cursor_end( text ); free( str ); - } else{ + } else { selected = selected < filtered_lines-1 ? MIN( filtered_lines-1, selected+1 ): 0; - } - } + } + } + } } menu_draw( text, boxes, max_lines,num_lines, &last_offset, selected, filtered ); @@ -1064,19 +1094,10 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, release_keyboard(); - if ( chosen && filtered[selected] ) { - line = line_map[selected]; - } + if ( *input != NULL ) free( *input ); - if ( line < 0 && input ) { - if ( *input != NULL ) free( *input ); + *input = strdup( text->text ); - *input = strdup( text->text ); - - // If chosen and the like. - if ( chosen ) - line = -3; - } textbox_free( text ); @@ -1089,7 +1110,7 @@ int menu( char **lines, char **input, char *prompt, Time *time, int *shift, free( filtered ); free( line_map ); - return line; + return retv; } #define FORK 1 @@ -1158,20 +1179,21 @@ SwitcherMode run_switcher_window ( char **input ) } } Time time; - int n = menu( list, input, ">", &time, NULL,window_match, ids ); + int selected_line = 0; + MenuReturn mretv = menu( list, input, ">", &time, NULL,window_match, ids ,&selected_line ); - if ( n == -2 ) { + if ( mretv == MENU_NEXT ) { retv = NEXT_DIALOG; - } else if ( n >= 0 && list[n] ) { + } else if ( mretv == MENU_OK && list[selected_line] ) { #ifdef I3 if ( config.i3_mode ) { // Hack for i3. - focus_window_i3( i3_socket_path,ids->array[n] ); + focus_window_i3( i3_socket_path,ids->array[selected_line] ); } else #endif { - window_send_message( root, ids->array[n], netatoms[_NET_ACTIVE_WINDOW], 2, // 2 = pager + window_send_message( root, ids->array[selected_line], netatoms[_NET_ACTIVE_WINDOW], 2, // 2 = pager SubstructureNotifyMask | SubstructureRedirectMask, time ); } } diff --git a/source/ssh-dialog.c b/source/ssh-dialog.c index 4a92c3de..f379af98 100644 --- a/source/ssh-dialog.c +++ b/source/ssh-dialog.c @@ -245,13 +245,14 @@ SwitcherMode ssh_switcher_dialog ( char **input ) } int shift=0; - int n = menu( cmd_list, input, "ssh", NULL, &shift,token_match, NULL ); + int selected_line = 0; + int mretv = menu( cmd_list, input, "ssh", NULL, &shift,token_match, NULL , &selected_line ); - if ( n == -2 ) { + if ( mretv == MENU_NEXT ) { retv = NEXT_DIALOG; - } else if ( n >=0 && cmd_list[n] != NULL ) { - exec_ssh( cmd_list[n] ); - } else if ( n == -3 && *input != NULL && *input[0] != '\0' ) { + } else if ( mretv == MENU_OK && cmd_list[selected_line] != NULL ) { + exec_ssh( cmd_list[selected_line] ); + } else if ( mretv == MENU_CUSTOM_INPUT && *input != NULL && *input[0] != '\0' ) { exec_ssh( *input ); } diff --git a/source/textbox.c b/source/textbox.c index 846f02dc..088025d3 100644 --- a/source/textbox.c +++ b/source/textbox.c @@ -374,6 +374,7 @@ int textbox_keypress( textbox *tb, XEvent *ev ) textbox_cursor_inc( tb ); return 1; } /*else if ( key == XK_Home ) { + textbox_cursor_home( tb ); return 1; } else if ( key == XK_End ) {