xaizek / hstr (License: Apachev2) (since 2018-12-07)
Bash and Zsh shell history suggest box - easily view, navigate, search and manage your command history.
Commit 8ba606e32fbfd4f75fa006d40a4191883c01b4e0

Restructures selectionCursorPosition to be an item index
selectionCursorPosition was a Y position which had to be
transformed into an index in many places. This resulted in
a number of bugs. This change updates it to be an index
into the displayed list.
Author: pknowles
Author date (UTC): 2017-06-05 00:40
Committer name: pknowles
Committer date (UTC): 2017-06-05 02:25
Parent(s): 6a6465286ca11e89bd6d6f6cca249c2d7a05436f
Signing key:
Tree: 15160cf554e7cc8d6f00ae029ad1c5077b9a3658
File Lines added Lines deleted
configure.ac 1 0
src/hstr.c 121 159
File configure.ac changed (mode: 100644) (index 2317a3e..e13527c)
... ... AC_CHECK_HEADER(sys/ioctl.h)
97 97 AC_CHECK_HEADER(termios.h) AC_CHECK_HEADER(termios.h)
98 98 AC_CHECK_HEADER(unistd.h) AC_CHECK_HEADER(unistd.h)
99 99 AC_CHECK_HEADER(wchar.h) AC_CHECK_HEADER(wchar.h)
100 AC_CHECK_HEADER(assert.h)
100 101
101 102 # Checks for typedefs, structures, and compiler characteristics. # Checks for typedefs, structures, and compiler characteristics.
102 103 AC_CHECK_HEADER_STDBOOL AC_CHECK_HEADER_STDBOOL
File src/hstr.c changed (mode: 100644) (index 87b2f71..cbe630e)
36 36 #include <termios.h> #include <termios.h>
37 37 #include <unistd.h> #include <unistd.h>
38 38 #include <wchar.h> #include <wchar.h>
39 #include <assert.h>
39 40
40 41 #include "include/hashset.h" #include "include/hashset.h"
41 42 #include "include/hstr_curses.h" #include "include/hstr_curses.h"
 
... ... int print_prompt()
425 426 } }
426 427 refresh(); refresh();
427 428
428 return promptLength;
429 return xoffset + promptLength;
429 430 } }
430 431
431 432 void add_to_selection(Hstr *hstr, char *line, unsigned int *index) void add_to_selection(Hstr *hstr, char *line, unsigned int *index)
 
... ... void print_status_label()
529 530 int width=getmaxx(stdscr); int width=getmaxx(stdscr);
530 531
531 532 char screenLine[CMDLINE_LNG]; char screenLine[CMDLINE_LNG];
532 snprintf(screenLine, width, "- HISTORY - view:%s (C-7) - match:%s (C-e) - case:%s (C-t) - %d/%d/%d ",
533 snprintf(screenLine, width, "- HISTORY - view:%s (C-/) - match:%s (C-e) - case:%s (C-t) - %d/%d/%d ",
533 534 HH_VIEW_LABELS[hstr->historyView], HH_VIEW_LABELS[hstr->historyView],
534 535 HH_MATCH_LABELS[hstr->historyMatch], HH_MATCH_LABELS[hstr->historyMatch],
535 536 HH_CASE_LABELS[hstr->caseSensitive], HH_CASE_LABELS[hstr->caseSensitive],
 
... ... void hstr_print_highlighted_selection_row(char *text, int y, int width, Hstr *hs
811 812 color_attr_off(A_BOLD); color_attr_off(A_BOLD);
812 813 } }
813 814
814 char *hstr_print_selection(unsigned maxHistoryItems, char *pattern, Hstr *hstr)
815 char *hstr_print_selection(char *pattern, Hstr *hstr)
815 816 { {
816 817 char *result=NULL; char *result=NULL;
817 unsigned selectionCount=hstr_make_selection(pattern, hstr->history, maxHistoryItems, hstr);
818 if (selectionCount > 0) {
818 if (hstr->selectionSize > 0) {
819 819 result=hstr->selection[0]; result=hstr->selection[0];
820 820 } }
821 821
822 int height=recalculate_max_history_items();
822 if (!strlen(pattern)) {
823 pattern = NULL;
824 }
825
823 826 int width=getmaxx(stdscr); int width=getmaxx(stdscr);
824 827 unsigned i; unsigned i;
825 828 int y; int y;
826 829
827 move(hstr->promptYItemsStart, 0);
828 clrtobot();
829 if(hstr->promptBottom) {
830 print_help_label();
831 print_status_label();
832 print_pattern(pattern, hstr->promptY, print_prompt());
833 y=hstr->promptYItemsEnd;
834 } else {
835 y=hstr->promptYItemsStart;
836 }
837
838 830 int start, count; int start, count;
839 831 char screenLine[CMDLINE_LNG]; char screenLine[CMDLINE_LNG];
840 for (i = 0; i<height; ++i) {
832 for (i = 0; i < hstr->promptItems; ++i) {
833 y = hstr->promptBottom ?
834 hstr->promptYItemsEnd - i :
835 hstr->promptYItemsStart + i;
841 836 if(i<hstr->selectionSize) { if(i<hstr->selectionSize) {
842 837 // TODO make this function // TODO make this function
843 if(pattern && strlen(pattern)) {
838 if(pattern) {
844 839 if(hstr->historyMatch==HH_MATCH_REGEXP) { if(hstr->historyMatch==HH_MATCH_REGEXP) {
845 840 start=hstr->selectionRegexpMatch[i].rm_so; start=hstr->selectionRegexpMatch[i].rm_so;
846 841 count=hstr->selectionRegexpMatch[i].rm_eo-start; count=hstr->selectionRegexpMatch[i].rm_eo-start;
 
... ... char *hstr_print_selection(unsigned maxHistoryItems, char *pattern, Hstr *hstr)
859 854 print_selection_row(hstr->selection[i], y, width, pattern); print_selection_row(hstr->selection[i], y, width, pattern);
860 855 } }
861 856 } else { } else {
862 mvprintw(y, 0, " ");
863 }
864
865 if(hstr->promptBottom) {
866 y--;
867 } else {
868 y++;
857 move(y, 0);
858 clrtoeol();
869 859 } }
870 860 } }
871 861 refresh(); refresh();
 
... ... char *hstr_print_selection(unsigned maxHistoryItems, char *pattern, Hstr *hstr)
873 863 return result; return result;
874 864 } }
875 865
866 char *hstr_make_and_print_selection(char *pattern, Hstr *hstr)
867 {
868 hstr_make_selection(pattern, hstr->history, hstr->promptItems, hstr);
869 return hstr_print_selection(pattern, hstr);
870 }
871
876 872 void highlight_selection(int selectionCursorPosition, int previousSelectionCursorPosition, char *pattern, Hstr *hstr) void highlight_selection(int selectionCursorPosition, int previousSelectionCursorPosition, char *pattern, Hstr *hstr)
877 873 { {
874 // sanity test to catch a recurring bug
875 assert(selectionCursorPosition >= 0 && selectionCursorPosition < hstr->selectionSize);
876 assert(previousSelectionCursorPosition == SELECTION_CURSOR_IN_PROMPT ||
877 (previousSelectionCursorPosition >= 0 && previousSelectionCursorPosition < hstr->selectionSize));
878
879 // restore previous selected row
878 880 if(previousSelectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) { if(previousSelectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) {
879 881 // TODO make this function // TODO make this function
880 882 char buffer[CMDLINE_LNG]; char buffer[CMDLINE_LNG];
 
... ... void highlight_selection(int selectionCursorPosition, int previousSelectionCurso
889 891 strcpy(buffer, pattern); strcpy(buffer, pattern);
890 892 } }
891 893
892 int text, y;
894 int y;
893 895 if(hstr->promptBottom) { if(hstr->promptBottom) {
894 text=hstr->promptItems-previousSelectionCursorPosition-1;
895 y=hstr->promptYItemsStart+previousSelectionCursorPosition;
896 y=hstr->promptYItemsEnd-previousSelectionCursorPosition;
896 897 } else { } else {
897 text=previousSelectionCursorPosition;
898 898 y=hstr->promptYItemsStart+previousSelectionCursorPosition; y=hstr->promptYItemsStart+previousSelectionCursorPosition;
899 899 } }
900 900 print_selection_row( print_selection_row(
901 hstr->selection[text],
901 hstr->selection[previousSelectionCursorPosition],
902 902 y, y,
903 903 getmaxx(stdscr), getmaxx(stdscr),
904 904 buffer); buffer);
905 905 } }
906
907 // highlight new selected row
906 908 if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) { if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) {
907 int text, y;
909 int y;
908 910 if(hstr->promptBottom) { if(hstr->promptBottom) {
909 text=hstr->promptItems-selectionCursorPosition-1;
910 y=hstr->promptYItemsStart+selectionCursorPosition;
911 y=hstr->promptYItemsEnd-selectionCursorPosition;
911 912 } else { } else {
912 text=selectionCursorPosition;
913 913 y=hstr->promptYItemsStart+selectionCursorPosition; y=hstr->promptYItemsStart+selectionCursorPosition;
914 914 } }
915 915 hstr_print_highlighted_selection_row( hstr_print_highlighted_selection_row(
916 hstr->selection[text],
916 hstr->selection[selectionCursorPosition],
917 917 y, y,
918 918 getmaxx(stdscr), getmaxx(stdscr),
919 919 hstr); hstr);
 
... ... void stdout_history_and_return(Hstr *hstr) {
969 969 } }
970 970 } }
971 971
972 char* getResultFromSelection(int selectionCursorPosition, Hstr* hstr, char* result) {
973 if (hstr->promptBottom) {
974 result=hstr->selection[hstr->promptYItemsEnd-selectionCursorPosition];
975 } else {
976 result=hstr->selection[selectionCursorPosition];
977 }
978 return result;
972 char* getSelectedText(int selectionCursorPosition, Hstr* hstr) {
973 assert(selectionCursorPosition >= 0 && selectionCursorPosition < hstr->selectionSize);
974 return hstr->selection[selectionCursorPosition];
979 975 } }
980 976
981 977 void loop_to_select(Hstr *hstr) void loop_to_select(Hstr *hstr)
 
... ... void loop_to_select(Hstr *hstr)
993 989 } }
994 990
995 991 color_attr_on(COLOR_PAIR(HH_COLOR_NORMAL)); color_attr_on(COLOR_PAIR(HH_COLOR_NORMAL));
996 // TODO why do I print non-filtered selection when on command line there is a pattern?
997 hstr_print_selection(recalculate_max_history_items(), NULL, hstr);
998 color_attr_off(COLOR_PAIR(HH_COLOR_NORMAL));
999 if(!hstr->promptBottom) {
1000 print_help_label();
1001 print_status_label();
1002 }
1003 992
1004 bool done=FALSE, skip=TRUE, executeResult=FALSE, lowercase=TRUE;
1005 bool printDefaultLabel=TRUE, fixCommand=FALSE, editCommand=FALSE;
1006 int basex=print_prompt();
1007 int x=basex, c, cc, cursorX=0, cursorY=0, maxHistoryItems, deletedOccurences;
993 bool done=FALSE, executeResult=FALSE, lowercase=TRUE;
994 bool dirtyStatusLabel=TRUE, fixCommand=FALSE, editCommand=FALSE;
995 int basex=0;
996 int c, cc, cursorX=0, cursorY=0, deletedOccurences;
1008 997 int width=getmaxx(stdscr); int width=getmaxx(stdscr);
1009 998 int selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT; int selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
1010 999 int previousSelectionCursorPosition=SELECTION_CURSOR_IN_PROMPT; int previousSelectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
 
... ... void loop_to_select(Hstr *hstr)
1015 1004 // TODO overflow // TODO overflow
1016 1005 strcpy(pattern, hstr->cmdline); strcpy(pattern, hstr->cmdline);
1017 1006
1018 while (!done) {
1019 maxHistoryItems=recalculate_max_history_items();
1007 recalculate_max_history_items();
1020 1008
1021 if(!skip) {
1022 c = wgetch(stdscr);
1023 } else {
1024 if(strlen(pattern)) {
1025 color_attr_on(A_BOLD);
1026 mvprintw(hstr->promptY, basex, "%s", pattern);
1027 color_attr_off(A_BOLD);
1028 cursorX=getcurx(stdscr);
1029 cursorY=getcury(stdscr);
1030 result=hstr_print_selection(maxHistoryItems, pattern, hstr);
1031 move(cursorY, cursorX);
1032 }
1033 skip=FALSE;
1034 continue;
1035 }
1009 // print prompt before pattern
1010 basex=print_prompt();
1036 1011
1037 if(printDefaultLabel) {
1012 // print current pattern
1013 print_pattern(pattern, hstr->promptY, basex);
1014 cursorX=getcurx(stdscr);
1015 cursorY=getcury(stdscr);
1016
1017 // initialize history list
1018 result=hstr_make_and_print_selection(pattern, hstr);
1019 color_attr_off(COLOR_PAIR(HH_COLOR_NORMAL));
1020
1021 // initialize info rows
1022 print_status_label();
1023 print_help_label(); // help is static and almost never needs updating
1024
1025 // finally, put cursor back at the prompt
1026 move(cursorY, cursorX);
1027
1028 while (!done) {
1029 c = wgetch(stdscr);
1030
1031 // if a message was displayed on the status label, clear it on next keypress
1032 if(dirtyStatusLabel) {
1038 1033 print_status_label(); print_status_label();
1039 printDefaultLabel=FALSE;
1034 dirtyStatusLabel=FALSE;
1040 1035 } }
1041 1036
1042 1037 switch (c) { switch (c) {
 
... ... void loop_to_select(Hstr *hstr)
1048 1043 break; break;
1049 1044 case KEY_DC: // DEL case KEY_DC: // DEL
1050 1045 if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) { if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) {
1051 delete=getResultFromSelection(selectionCursorPosition, hstr, result);
1046 delete=getSelectedText(selectionCursorPosition, hstr);
1052 1047 msg=malloc(strlen(delete)+1); msg=malloc(strlen(delete)+1);
1053 1048 strcpy(msg,delete); strcpy(msg,delete);
1054 1049
 
... ... void loop_to_select(Hstr *hstr)
1056 1051 cc = wgetch(stdscr); cc = wgetch(stdscr);
1057 1052 if(cc == 'y') { if(cc == 'y') {
1058 1053 deletedOccurences=remove_from_history_model(msg, hstr); deletedOccurences=remove_from_history_model(msg, hstr);
1059 result=hstr_print_selection(maxHistoryItems, pattern, hstr);
1054 result=hstr_make_and_print_selection(pattern, hstr);
1060 1055 print_cmd_deleted_label(msg, deletedOccurences, hstr); print_cmd_deleted_label(msg, deletedOccurences, hstr);
1061 1056 } else { } else {
1062 1057 print_status_label(); print_status_label();
1063 1058 } }
1064 1059 free(msg); free(msg);
1065 1060 move(hstr->promptY, basex+strlen(pattern)); move(hstr->promptY, basex+strlen(pattern));
1066 printDefaultLabel=TRUE;
1061 dirtyStatusLabel=TRUE;
1067 1062
1068 if(hstr->promptBottom) {
1069 if(selectionCursorPosition <= hstr->promptYItemsEnd-hstr->selectionSize+1) {
1070 selectionCursorPosition=hstr->promptYItemsEnd-hstr->selectionSize+1;
1071 }
1072 } else {
1073 if(selectionCursorPosition>=hstr->selectionSize) {
1074 selectionCursorPosition=hstr->selectionSize-1;
1075 }
1076 }
1063 selectionCursorPosition = MIN(MAX(selectionCursorPosition, 0), hstr->selectionSize-1);
1077 1064 highlight_selection(selectionCursorPosition, SELECTION_CURSOR_IN_PROMPT, pattern, hstr); highlight_selection(selectionCursorPosition, SELECTION_CURSOR_IN_PROMPT, pattern, hstr);
1078 1065 move(hstr->promptY, basex+strlen(pattern)); move(hstr->promptY, basex+strlen(pattern));
1079 1066 } }
 
... ... void loop_to_select(Hstr *hstr)
1082 1069 hstr->historyMatch++; hstr->historyMatch++;
1083 1070 hstr->historyMatch=hstr->historyMatch%HH_NUM_HISTORY_MATCH; hstr->historyMatch=hstr->historyMatch%HH_NUM_HISTORY_MATCH;
1084 1071 // TODO make this a function // TODO make this a function
1085 result=hstr_print_selection(maxHistoryItems, pattern, hstr);
1072 result=hstr_make_and_print_selection(pattern, hstr);
1086 1073 print_status_label(); print_status_label();
1087 1074 selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT; selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
1088 1075 if(strlen(pattern)<(width-basex-1)) { if(strlen(pattern)<(width-basex-1)) {
 
... ... void loop_to_select(Hstr *hstr)
1094 1081 case K_CTRL_T: case K_CTRL_T:
1095 1082 hstr->caseSensitive=!hstr->caseSensitive; hstr->caseSensitive=!hstr->caseSensitive;
1096 1083 hstr->regexp.caseSensitive=hstr->caseSensitive; hstr->regexp.caseSensitive=hstr->caseSensitive;
1097 result=hstr_print_selection(maxHistoryItems, pattern, hstr);
1084 result=hstr_make_and_print_selection(pattern, hstr);
1098 1085 print_status_label(); print_status_label();
1099 1086 selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT; selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
1100 1087 if(strlen(pattern)<(width-basex-1)) { if(strlen(pattern)<(width-basex-1)) {
 
... ... void loop_to_select(Hstr *hstr)
1105 1092 break; break;
1106 1093 case K_CTRL_SLASH: case K_CTRL_SLASH:
1107 1094 hstr_next_view(hstr); hstr_next_view(hstr);
1108 result=hstr_print_selection(maxHistoryItems, pattern, hstr);
1095 result=hstr_make_and_print_selection(pattern, hstr);
1109 1096 print_status_label(); print_status_label();
1110 1097 // TODO function // TODO function
1111 1098 selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT; selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
 
... ... void loop_to_select(Hstr *hstr)
1117 1104 break; break;
1118 1105 case K_CTRL_F: case K_CTRL_F:
1119 1106 if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) { if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) {
1120 result=getResultFromSelection(selectionCursorPosition, hstr, result);
1107 result=getSelectedText(selectionCursorPosition, hstr);
1121 1108 if(hstr->historyView==HH_VIEW_FAVORITES) { if(hstr->historyView==HH_VIEW_FAVORITES) {
1122 1109 favorites_choose(hstr->favorites, result); favorites_choose(hstr->favorites, result);
1123 1110 } else { } else {
1124 1111 favorites_add(hstr->favorites, result); favorites_add(hstr->favorites, result);
1125 1112 } }
1126 hstr_print_selection(maxHistoryItems, pattern, hstr);
1113 hstr_make_and_print_selection(pattern, hstr);
1127 1114 selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT; selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
1128 1115 if(hstr->historyView!=HH_VIEW_FAVORITES) { if(hstr->historyView!=HH_VIEW_FAVORITES) {
1129 1116 print_cmd_added_favorite_label(result, hstr); print_cmd_added_favorite_label(result, hstr);
1130 printDefaultLabel=TRUE;
1117 dirtyStatusLabel=TRUE;
1131 1118 } }
1132 1119 // TODO code review // TODO code review
1133 1120 if(strlen(pattern)<(width-basex-1)) { if(strlen(pattern)<(width-basex-1)) {
 
... ... void loop_to_select(Hstr *hstr)
1138 1125 } }
1139 1126 break; break;
1140 1127 case KEY_RESIZE: case KEY_RESIZE:
1128 recalculate_max_history_items();
1129 print_help_label();
1141 1130 print_status_label(); print_status_label();
1142 result=hstr_print_selection(maxHistoryItems, pattern, hstr);
1143 print_status_label();
1131 result=hstr_make_and_print_selection(pattern, hstr);
1144 1132 selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT; selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
1145 1133 move(hstr->promptY, basex+strlen(pattern)); move(hstr->promptY, basex+strlen(pattern));
1146 1134 break; break;
 
... ... void loop_to_select(Hstr *hstr)
1160 1148 case KEY_BACKSPACE: case KEY_BACKSPACE:
1161 1149 if(hstr_strlen(pattern)>0) { if(hstr_strlen(pattern)>0) {
1162 1150 hstr_chop(pattern); hstr_chop(pattern);
1163 x--;
1164 1151 print_pattern(pattern, hstr->promptY, basex); print_pattern(pattern, hstr->promptY, basex);
1165 1152 } }
1166 1153
1167 // TODO why I make selection if it's done in print_selection?
1168 if(strlen(pattern)>0) {
1169 hstr_make_selection(pattern, hstr->history, maxHistoryItems, hstr);
1170 } else {
1171 hstr_make_selection(NULL, hstr->history, maxHistoryItems, hstr);
1172 }
1173 result=hstr_print_selection(maxHistoryItems, pattern, hstr);
1154 result=hstr_make_and_print_selection(pattern, hstr);
1174 1155
1175 1156 move(hstr->promptY, basex+hstr_strlen(pattern)); move(hstr->promptY, basex+hstr_strlen(pattern));
1176 1157 break; break;
1177 1158 case KEY_UP: case KEY_UP:
1178 1159 case K_CTRL_P: case K_CTRL_P:
1179 previousSelectionCursorPosition=selectionCursorPosition;
1180 if(selectionCursorPosition>0) {
1181 if(hstr->promptBottom) {
1182 if(selectionCursorPosition <= hstr->promptYItemsEnd-hstr->selectionSize+1) {
1183 selectionCursorPosition=hstr->promptYItemsEnd;
1184 } else {
1185 selectionCursorPosition--;
1186 }
1187 } else {
1188 selectionCursorPosition--;
1189 }
1190 } else {
1160 if (hstr->selectionSize > 0) {
1161 previousSelectionCursorPosition=selectionCursorPosition;
1191 1162 if(hstr->promptBottom) { if(hstr->promptBottom) {
1192 selectionCursorPosition=hstr->promptYItemsEnd;
1163 ++selectionCursorPosition;
1193 1164 } else { } else {
1194 selectionCursorPosition=hstr->selectionSize-1;
1165 --selectionCursorPosition;
1195 1166 } }
1167 selectionCursorPosition = (MAX(-1, selectionCursorPosition) + hstr->selectionSize) % hstr->selectionSize;
1168 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern, hstr);
1169 move(hstr->promptY, basex+strlen(pattern));
1196 1170 } }
1197 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern, hstr);
1198 move(hstr->promptY, basex+strlen(pattern));
1199 1171 break; break;
1200 1172 case KEY_PPAGE: case KEY_PPAGE:
1201 previousSelectionCursorPosition=selectionCursorPosition;
1202 if(selectionCursorPosition>=PG_JUMP_SIZE) {
1203 selectionCursorPosition=selectionCursorPosition-PG_JUMP_SIZE;
1204 } else {
1205 selectionCursorPosition=0;
1173 if (hstr->selectionSize > 0) {
1174 previousSelectionCursorPosition=selectionCursorPosition;
1175 if(hstr->promptBottom) {
1176 selectionCursorPosition+=PG_JUMP_SIZE;
1177 } else {
1178 selectionCursorPosition-=PG_JUMP_SIZE;
1179 }
1180 selectionCursorPosition = MIN(MAX(selectionCursorPosition, 0), hstr->selectionSize-1);
1181 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern, hstr);
1182 move(hstr->promptY, basex+strlen(pattern));
1206 1183 } }
1207 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern, hstr);
1208 move(hstr->promptY, basex+strlen(pattern));
1209 1184 break; break;
1210 1185 case K_CTRL_R: case K_CTRL_R:
1211 1186 case KEY_DOWN: case KEY_DOWN:
1212 1187 case K_CTRL_N: case K_CTRL_N:
1213 if(selectionCursorPosition==SELECTION_CURSOR_IN_PROMPT) {
1214 if(hstr->promptBottom) {
1215 selectionCursorPosition=hstr->promptYItemsEnd-hstr->selectionSize+1;
1216 } else {
1217 selectionCursorPosition=previousSelectionCursorPosition=0;
1218 }
1219 } else {
1188 if (hstr->selectionSize > 0) {
1220 1189 previousSelectionCursorPosition=selectionCursorPosition; previousSelectionCursorPosition=selectionCursorPosition;
1221 1190 if(hstr->promptBottom) { if(hstr->promptBottom) {
1222 if(selectionCursorPosition<hstr->promptYItemsEnd) {
1223 selectionCursorPosition++;
1224 } else {
1225 selectionCursorPosition=hstr->promptYItemsEnd-hstr->selectionSize+1;
1226 }
1191 --selectionCursorPosition;
1227 1192 } else { } else {
1228 if((selectionCursorPosition+1)<hstr->selectionSize) {
1229 selectionCursorPosition++;
1230 } else {
1231 selectionCursorPosition=0;
1232 }
1193 ++selectionCursorPosition;
1233 1194 } }
1234 }
1235 if(hstr->selectionSize) {
1195 selectionCursorPosition = (MAX(-1, selectionCursorPosition) + hstr->selectionSize) % hstr->selectionSize;
1236 1196 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern, hstr); highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern, hstr);
1197 move(hstr->promptY, basex+strlen(pattern));
1237 1198 } }
1238 move(hstr->promptY, basex+strlen(pattern));
1239 1199 break; break;
1240 1200 case KEY_NPAGE: case KEY_NPAGE:
1241 if(selectionCursorPosition==SELECTION_CURSOR_IN_PROMPT) {
1242 selectionCursorPosition=previousSelectionCursorPosition=0;
1243 } else {
1201 if (hstr->selectionSize > 0) {
1244 1202 previousSelectionCursorPosition=selectionCursorPosition; previousSelectionCursorPosition=selectionCursorPosition;
1245 if((selectionCursorPosition+PG_JUMP_SIZE)<hstr->selectionSize) {
1246 selectionCursorPosition = selectionCursorPosition+PG_JUMP_SIZE;
1203 if(hstr->promptBottom) {
1204 selectionCursorPosition-=PG_JUMP_SIZE;
1247 1205 } else { } else {
1248 selectionCursorPosition=hstr->selectionSize-1;
1206 selectionCursorPosition+=PG_JUMP_SIZE;
1249 1207 } }
1250 }
1251 if(hstr->selectionSize) {
1208 selectionCursorPosition = MIN(MAX(selectionCursorPosition, 0), hstr->selectionSize-1);
1252 1209 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern, hstr); highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern, hstr);
1210 move(hstr->promptY, basex+strlen(pattern));
1253 1211 } }
1254 move(hstr->promptY, basex+strlen(pattern));
1255 1212 break; break;
1256 1213 case K_ENTER: case K_ENTER:
1257 1214 case KEY_ENTER: case KEY_ENTER:
1258 1215 executeResult=TRUE; executeResult=TRUE;
1259 1216 if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) { if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) {
1260 result=getResultFromSelection(selectionCursorPosition, hstr, result);
1217 result=getSelectedText(selectionCursorPosition, hstr);
1261 1218 if(hstr->historyView==HH_VIEW_FAVORITES) { if(hstr->historyView==HH_VIEW_FAVORITES) {
1262 1219 favorites_choose(hstr->favorites,result); favorites_choose(hstr->favorites,result);
1263 1220 } }
 
... ... void loop_to_select(Hstr *hstr)
1273 1230 fixCommand=TRUE; fixCommand=TRUE;
1274 1231 executeResult=TRUE; executeResult=TRUE;
1275 1232 if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) { if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) {
1276 result=getResultFromSelection(selectionCursorPosition, hstr, result);
1233 result=getSelectedText(selectionCursorPosition, hstr);
1277 1234 if(hstr->historyView==HH_VIEW_FAVORITES) { if(hstr->historyView==HH_VIEW_FAVORITES) {
1278 1235 favorites_choose(hstr->favorites,result); favorites_choose(hstr->favorites,result);
1279 1236 } }
 
... ... void loop_to_select(Hstr *hstr)
1286 1243 case KEY_RIGHT: case KEY_RIGHT:
1287 1244 editCommand=TRUE; editCommand=TRUE;
1288 1245 if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) { if(selectionCursorPosition!=SELECTION_CURSOR_IN_PROMPT) {
1289 result=getResultFromSelection(selectionCursorPosition, hstr, result);
1246 result=getSelectedText(selectionCursorPosition, hstr);
1290 1247 if(hstr->historyView==HH_VIEW_FAVORITES) { if(hstr->historyView==HH_VIEW_FAVORITES) {
1291 1248 favorites_choose(hstr->favorites,result); favorites_choose(hstr->favorites,result);
1292 1249 } }
 
... ... void loop_to_select(Hstr *hstr)
1312 1269 LOGSELECTION(Y_OFFSET_HELP,getmaxy(stdscr),hstr->selectionSize); LOGSELECTION(Y_OFFSET_HELP,getmaxy(stdscr),hstr->selectionSize);
1313 1270
1314 1271 if(c>K_CTRL_Z) { if(c>K_CTRL_Z) {
1315 selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
1316
1317 1272 if(strlen(pattern)<(width-basex-1)) { if(strlen(pattern)<(width-basex-1)) {
1318 1273 strcat(pattern, (char*)(&c)); strcat(pattern, (char*)(&c));
1319 1274 print_pattern(pattern, hstr->promptY, basex); print_pattern(pattern, hstr->promptY, basex);
 
... ... void loop_to_select(Hstr *hstr)
1321 1276 cursorY=getcury(stdscr); cursorY=getcury(stdscr);
1322 1277 } }
1323 1278
1324 result = hstr_print_selection(maxHistoryItems, pattern, hstr);
1279 previousSelectionCursorPosition = SELECTION_CURSOR_IN_PROMPT;
1280 result = hstr_make_and_print_selection(pattern, hstr);
1281 if (hstr->selectionSize > 0) {
1282 selectionCursorPosition=0;
1283 highlight_selection(selectionCursorPosition, previousSelectionCursorPosition, pattern, hstr);
1284 } else {
1285 selectionCursorPosition=SELECTION_CURSOR_IN_PROMPT;
1286 }
1325 1287 move(cursorY, cursorX); move(cursorY, cursorX);
1326 1288 refresh(); refresh();
1327 1289 } }
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/hstr

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/hstr

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master