File src/hstr.c changed (mode: 100644) (index 9ba350b..0d24c20) |
10 |
10 |
#define _GNU_SOURCE |
#define _GNU_SOURCE |
11 |
11 |
|
|
12 |
12 |
#include <curses.h> |
#include <curses.h> |
|
13 |
|
#include <getopt.h> |
13 |
14 |
#include <regex.h> |
#include <regex.h> |
14 |
15 |
#include <signal.h> |
#include <signal.h> |
15 |
16 |
#include <stdbool.h> |
#include <stdbool.h> |
|
... |
... |
static const char *HELP_STRING= |
136 |
137 |
"Usage: hh [option] [arg1] [arg2]..." |
"Usage: hh [option] [arg1] [arg2]..." |
137 |
138 |
"\nShell history suggest box:" |
"\nShell history suggest box:" |
138 |
139 |
"\n" |
"\n" |
139 |
|
"\n --favorites -f ... show command favorites" |
|
140 |
|
"\n --show-configuration ... show configuration to be added to ~/.bashrc" |
|
141 |
|
"\n --version ... show version details" |
|
142 |
|
"\n --help ... display this help and exit" |
|
|
140 |
|
"\n --favorites -f ... show favorites view" |
|
141 |
|
"\n --non-interactive -n ... print filtered history and exit" |
|
142 |
|
"\n --show-configuration -s ... show configuration to be added to ~/.bashrc" |
|
143 |
|
"\n --version -V ... show version details" |
|
144 |
|
"\n --help -h ... help" |
143 |
145 |
"\n" |
"\n" |
144 |
146 |
"\nReport bugs to martin.dvorak@mindforger.com" |
"\nReport bugs to martin.dvorak@mindforger.com" |
145 |
147 |
"\nHome page: https://github.com/dvorka/hstr" |
"\nHome page: https://github.com/dvorka/hstr" |
|
... |
... |
static const char *VERSION_STRING= |
154 |
156 |
static const char *LABEL_HELP= |
static const char *LABEL_HELP= |
155 |
157 |
"Type to filter, UP/DOWN move, DEL remove, TAB select, C-f add favorite, C-g cancel"; |
"Type to filter, UP/DOWN move, DEL remove, TAB select, C-f add favorite, C-g cancel"; |
156 |
158 |
|
|
|
159 |
|
#define GETOPT_NO_ARGUMENT 0 |
|
160 |
|
#define GETOPT_REQUIRED_ARGUMENT 1 |
|
161 |
|
#define GETOPT_OPTIONAL_ARGUMENT 2 |
|
162 |
|
|
|
163 |
|
static const struct option long_options[] = { |
|
164 |
|
{"favorites", GETOPT_NO_ARGUMENT, NULL, 'f'}, |
|
165 |
|
{"version", GETOPT_NO_ARGUMENT, NULL, 'V'}, |
|
166 |
|
{"help", GETOPT_NO_ARGUMENT, NULL, 'h'}, |
|
167 |
|
{"non-interactive", GETOPT_NO_ARGUMENT, NULL, 'n'}, |
|
168 |
|
{"show-configuration", GETOPT_NO_ARGUMENT, NULL, 's'}, |
|
169 |
|
{0, 0, NULL, 0 } |
|
170 |
|
}; |
|
171 |
|
|
157 |
172 |
typedef struct { |
typedef struct { |
158 |
173 |
HistoryItems *history; |
HistoryItems *history; |
159 |
174 |
FavoriteItems *favorites; |
FavoriteItems *favorites; |
|
... |
... |
typedef struct { |
166 |
181 |
int historyView; // TODO view: favs, ... |
int historyView; // TODO view: favs, ... |
167 |
182 |
int caseSensitive; |
int caseSensitive; |
168 |
183 |
|
|
|
184 |
|
bool interactive; |
|
185 |
|
|
169 |
186 |
bool hicolor; |
bool hicolor; |
170 |
187 |
int debugLevel; |
int debugLevel; |
171 |
188 |
|
|
|
... |
... |
void hstr_init(Hstr *hstr) |
186 |
203 |
hstr->historyView=HH_VIEW_RANKING; |
hstr->historyView=HH_VIEW_RANKING; |
187 |
204 |
hstr->caseSensitive=HH_CASE_INSENSITIVE; |
hstr->caseSensitive=HH_CASE_INSENSITIVE; |
188 |
205 |
|
|
|
206 |
|
hstr->interactive=true; |
|
207 |
|
|
189 |
208 |
hstr->hicolor=FALSE; |
hstr->hicolor=FALSE; |
190 |
209 |
|
|
191 |
210 |
hstr->debugLevel=HH_DEBUG_LEVEL_NONE; |
hstr->debugLevel=HH_DEBUG_LEVEL_NONE; |
192 |
|
|
|
193 |
211 |
hstr->cmdline[0]=0; |
hstr->cmdline[0]=0; |
194 |
|
|
|
195 |
212 |
hstr_regexp_init(&hstr->regexp); |
hstr_regexp_init(&hstr->regexp); |
196 |
213 |
} |
} |
197 |
214 |
|
|
|
... |
... |
void hstr_next_view(Hstr *hstr) |
626 |
643 |
hstr->historyView=hstr->historyView%3; |
hstr->historyView=hstr->historyView%3; |
627 |
644 |
} |
} |
628 |
645 |
|
|
|
646 |
|
void stdout_history_and_return(Hstr *hstr) { |
|
647 |
|
unsigned selectionCount=hstr_make_selection(hstr->cmdline, hstr->history, hstr->history->rawCount, hstr); |
|
648 |
|
if (selectionCount > 0) { |
|
649 |
|
int i; |
|
650 |
|
for(i=0; i<selectionCount; i++) { |
|
651 |
|
printf("%s\n",hstr->selection[i]); |
|
652 |
|
} |
|
653 |
|
} |
|
654 |
|
} |
|
655 |
|
|
629 |
656 |
void loop_to_select(Hstr *hstr) |
void loop_to_select(Hstr *hstr) |
630 |
657 |
{ |
{ |
631 |
658 |
signal(SIGINT, signal_callback_handler_ctrl_c); |
signal(SIGINT, signal_callback_handler_ctrl_c); |
|
... |
... |
void loop_to_select(Hstr *hstr) |
644 |
671 |
color_attr_on(COLOR_PAIR(HH_COLOR_NORMAL)); |
color_attr_on(COLOR_PAIR(HH_COLOR_NORMAL)); |
645 |
672 |
print_help_label(); |
print_help_label(); |
646 |
673 |
print_history_label(hstr); |
print_history_label(hstr); |
|
674 |
|
// TODO why do I print non-filtered selection when on command line there is a pattern? |
647 |
675 |
hstr_print_selection(get_max_history_items(stdscr), NULL, hstr); |
hstr_print_selection(get_max_history_items(stdscr), NULL, hstr); |
648 |
676 |
color_attr_off(COLOR_PAIR(HH_COLOR_NORMAL)); |
color_attr_off(COLOR_PAIR(HH_COLOR_NORMAL)); |
649 |
677 |
|
|
|
... |
... |
void loop_to_select(Hstr *hstr) |
656 |
684 |
char *result="", *msg, *delete; |
char *result="", *msg, *delete; |
657 |
685 |
char pattern[SELECTION_PREFIX_MAX_LNG]; |
char pattern[SELECTION_PREFIX_MAX_LNG]; |
658 |
686 |
pattern[0]=0; |
pattern[0]=0; |
|
687 |
|
// TODO this is too late! > don't render twice |
659 |
688 |
strcpy(pattern, hstr->cmdline); |
strcpy(pattern, hstr->cmdline); |
660 |
689 |
while (!done) { |
while (!done) { |
661 |
690 |
maxHistoryItems=get_max_history_items(stdscr); |
maxHistoryItems=get_max_history_items(stdscr); |
|
... |
... |
void loop_to_select(Hstr *hstr) |
869 |
898 |
} |
} |
870 |
899 |
} |
} |
871 |
900 |
|
|
872 |
|
// TODO support BASH substitutions: !!, !!ps, !$, !* |
|
873 |
|
void hstr_assemble_cmdline_pattern(int argc, char* argv[], Hstr* hstr) |
|
|
901 |
|
// TODO protection from line overflow (snprinf) |
|
902 |
|
void hstr_assemble_cmdline_pattern(int argc, char* argv[], Hstr* hstr, int startIndex) |
874 |
903 |
{ |
{ |
875 |
904 |
if(argc>0) { |
if(argc>0) { |
876 |
905 |
int i; |
int i; |
877 |
|
for(i=1; i<argc; i++) { |
|
|
906 |
|
for(i=startIndex; i<argc; i++) { |
878 |
907 |
if((strlen(hstr->cmdline)+strlen(argv[i])*2)>CMDLINE_LNG) break; |
if((strlen(hstr->cmdline)+strlen(argv[i])*2)>CMDLINE_LNG) break; |
879 |
908 |
if(strstr(argv[i], " ")) { |
if(strstr(argv[i], " ")) { |
880 |
909 |
strcat(hstr->cmdline, "\""); |
strcat(hstr->cmdline, "\""); |
|
... |
... |
void hstr_assemble_cmdline_pattern(int argc, char* argv[], Hstr* hstr) |
890 |
919 |
} |
} |
891 |
920 |
} |
} |
892 |
921 |
|
|
893 |
|
// TODO to be rewritten to getopt |
|
894 |
|
void hstr_get_cmdline_options(int argc, char *argv[], Hstr *hstr) |
|
895 |
|
{ |
|
896 |
|
if(argc>0) { |
|
897 |
|
if(argc==2) { |
|
898 |
|
if(strstr(argv[1], "--favorites") || strstr(argv[1], "-f")) { |
|
899 |
|
hstr->historyView=HH_VIEW_FAVORITES; |
|
900 |
|
return; |
|
901 |
|
} else { |
|
902 |
|
if(strstr(argv[1], "--show-configuration")) { |
|
903 |
|
printf("%s", INSTALL_STRING); |
|
904 |
|
exit(EXIT_SUCCESS); |
|
905 |
|
} else { |
|
906 |
|
if(strstr(argv[1], "--version")) { |
|
907 |
|
printf("%s", VERSION_STRING); |
|
908 |
|
exit(EXIT_SUCCESS); |
|
909 |
|
} else { |
|
910 |
|
if(strstr(argv[1], "--help")) { |
|
911 |
|
printf("Unknown option: %s\n", argv[1]); |
|
912 |
|
printf("%s", HELP_STRING); |
|
913 |
|
exit(EXIT_SUCCESS); |
|
914 |
|
} else { |
|
915 |
|
hstr_assemble_cmdline_pattern(argc, argv, hstr); |
|
916 |
|
} |
|
917 |
|
} |
|
918 |
|
} |
|
919 |
|
} |
|
920 |
|
} |
|
921 |
|
} |
|
922 |
|
|
|
923 |
|
} |
|
924 |
|
|
|
925 |
922 |
// TODO make favorites loading lazy (load on the first opening of favorites view) |
// TODO make favorites loading lazy (load on the first opening of favorites view) |
926 |
923 |
void hstr_init_favorites(Hstr *hstr) |
void hstr_init_favorites(Hstr *hstr) |
927 |
924 |
{ |
{ |
|
... |
... |
void hstr_main(Hstr *hstr) |
935 |
932 |
hstr->history=get_prioritized_history(); |
hstr->history=get_prioritized_history(); |
936 |
933 |
if(hstr->history) { |
if(hstr->history) { |
937 |
934 |
history_mgmt_open(); |
history_mgmt_open(); |
938 |
|
loop_to_select(hstr); |
|
|
935 |
|
if(hstr->interactive) { |
|
936 |
|
loop_to_select(hstr); |
|
937 |
|
} else { |
|
938 |
|
stdout_history_and_return(hstr); |
|
939 |
|
} |
939 |
940 |
hstr_on_exit(hstr); |
hstr_on_exit(hstr); |
940 |
941 |
} else { |
} else { |
941 |
942 |
printf("No history - nothing to suggest...\n"); |
printf("No history - nothing to suggest...\n"); |
942 |
943 |
} |
} |
943 |
944 |
} |
} |
944 |
945 |
|
|
|
946 |
|
void hstr_getopt(int argc, char **argv, Hstr *hstr) |
|
947 |
|
{ |
|
948 |
|
int option_index = 0; |
|
949 |
|
int option = getopt_long(argc, argv, "fVhns", long_options, &option_index); |
|
950 |
|
if(option != -1) { |
|
951 |
|
switch(option) { |
|
952 |
|
case 'f': |
|
953 |
|
hstr->historyView=HH_VIEW_FAVORITES; |
|
954 |
|
break; |
|
955 |
|
case 'n': |
|
956 |
|
hstr->interactive=false; |
|
957 |
|
break; |
|
958 |
|
case 'V': |
|
959 |
|
printf("%s", VERSION_STRING); |
|
960 |
|
exit(EXIT_SUCCESS); |
|
961 |
|
case 'h': |
|
962 |
|
printf("%s", HELP_STRING); |
|
963 |
|
exit(EXIT_SUCCESS); |
|
964 |
|
case 's': |
|
965 |
|
printf("%s", INSTALL_STRING); |
|
966 |
|
exit(EXIT_SUCCESS); |
|
967 |
|
|
|
968 |
|
case '?': |
|
969 |
|
default: |
|
970 |
|
printf("Unrecognized option: '%s'", HELP_STRING); |
|
971 |
|
printf("%s", HELP_STRING); |
|
972 |
|
exit(EXIT_SUCCESS); |
|
973 |
|
} |
|
974 |
|
} |
|
975 |
|
|
|
976 |
|
if(optind < argc) { |
|
977 |
|
hstr_assemble_cmdline_pattern(argc, argv, hstr, optind); |
|
978 |
|
} |
|
979 |
|
} |
|
980 |
|
|
945 |
981 |
int main(int argc, char *argv[]) |
int main(int argc, char *argv[]) |
946 |
982 |
{ |
{ |
947 |
983 |
hstr=malloc(sizeof(Hstr)); |
hstr=malloc(sizeof(Hstr)); |
948 |
984 |
|
|
949 |
985 |
hstr_init(hstr); |
hstr_init(hstr); |
950 |
|
hstr_get_env_configuration(hstr); |
|
951 |
|
hstr_get_cmdline_options(argc, argv, hstr); |
|
|
986 |
|
hstr_get_env_configuration(hstr); |
|
987 |
|
hstr_getopt(argc, argv, hstr); |
952 |
988 |
hstr_init_favorites(hstr); |
hstr_init_favorites(hstr); |
953 |
989 |
hstr_main(hstr); |
hstr_main(hstr); |
954 |
990 |
|
|