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 273c8456e2c92b9ee6ea7346c589418e6b589883

Added history ranking, filtering and blacklisting. Enabled by the implementation of hash map (based on hash set) and radix sort. Memory not freed.
Author: Martin Dvorak
Author date (UTC): 2013-12-15 00:00
Committer name: Martin Dvorak
Committer date (UTC): 2013-12-15 00:00
Parent(s): 87d4d5844c1628bc26aca5ea3aded8eaf441f35b
Signing key:
Tree: 67137f974628d531efe0560835d436d96388a251
File Lines added Lines deleted
src/hstr.c 9 10
src/hstr_history.c 85 3
src/hstr_utils.c 3 3
src/include/hashset.h 8 10
src/include/hstr_history.h 1 1
src/include/hstr_utils.h 1 1
File src/hstr.c changed (mode: 100644) (index ee0a8ea..c1beee4)
52 52 #endif #endif
53 53
54 54 static char **selection=NULL; static char **selection=NULL;
55 static int selectionSize=0;
55 static unsigned selectionSize=0;
56 56 static bool terminalHasColors=FALSE; static bool terminalHasColors=FALSE;
57 57
58 58
 
... ... void print_history_label(WINDOW *win) {
80 80
81 81 strcpy(message, LABEL_HISTORY); strcpy(message, LABEL_HISTORY);
82 82 width -= strlen(LABEL_HISTORY); width -= strlen(LABEL_HISTORY);
83 int i;
83 unsigned i;
84 84 for (i=0; i < width; i++) { for (i=0; i < width; i++) {
85 85 strcat(message, " "); strcat(message, " ");
86 86 } }
 
... ... void print_history_label(WINDOW *win) {
92 92 refresh(); refresh();
93 93 } }
94 94
95 int get_max_history_items(WINDOW *win) {
95 unsigned get_max_history_items(WINDOW *win) {
96 96 return (getmaxy(win)-(Y_OFFSET_ITEMS+2)); return (getmaxy(win)-(Y_OFFSET_ITEMS+2));
97 97 } }
98 98
99 99
100 void alloc_selection(int size) {
100 void alloc_selection(unsigned size) {
101 101 selectionSize=size; selectionSize=size;
102 102 if(selection!=NULL) { if(selection!=NULL) {
103 103 free(selection); free(selection);
 
... ... void alloc_selection(int size) {
108 108 } }
109 109 } }
110 110
111 int make_selection(char *prefix, HistoryItems *history, int maxSelectionCount) {
111 unsigned make_selection(char *prefix, HistoryItems *history, int maxSelectionCount) {
112 112 alloc_selection(sizeof(char*) * maxSelectionCount); // TODO realloc alloc_selection(sizeof(char*) * maxSelectionCount); // TODO realloc
113 int i, selectionCount=0;
113 unsigned i, selectionCount=0;
114 114
115 115 HashSet set; HashSet set;
116 116 hashset_init(&set); hashset_init(&set);
 
... ... int make_selection(char *prefix, HistoryItems *history, int maxSelectionCount) {
145 145 return selectionCount; return selectionCount;
146 146 } }
147 147
148 char *print_selection(WINDOW *win, int maxHistoryItems, char *prefix, HistoryItems *history) {
148 char *print_selection(WINDOW *win, unsigned maxHistoryItems, char *prefix, HistoryItems *history) {
149 149 char *result=""; char *result="";
150 int selectionCount=make_selection(prefix, history, maxHistoryItems);
150 unsigned selectionCount=make_selection(prefix, history, maxHistoryItems);
151 151 if (selectionCount > 0) { if (selectionCount > 0) {
152 152 result = selection[0]; result = selection[0];
153 153 } }
154 154
155 155 int height=get_max_history_items(win); int height=get_max_history_items(win);
156 int i;
156 unsigned i;
157 157 int y=Y_OFFSET_ITEMS; int y=Y_OFFSET_ITEMS;
158 158
159 159 move(Y_OFFSET_ITEMS, 0); move(Y_OFFSET_ITEMS, 0);
 
... ... char *selection_loop(HistoryItems *history) {
245 245 break; break;
246 246 case 91: case 91:
247 247 // TODO 91 killed > debug to determine how to distinguish \e and [ // TODO 91 killed > debug to determine how to distinguish \e and [
248 //mvprintw(Y_OFFSET_HELP, 0, "91 killed");
249 248 break; break;
250 249 case KEY_BACKSPACE: case KEY_BACKSPACE:
251 250 case 127: case 127:
File src/hstr_history.c changed (mode: 100644) (index 7253c22..c6baa03)
1 1 #include "include/hstr_history.h" #include "include/hstr_history.h"
2 #include "include/hashset.h"
3 #include "include/hashmap.h"
4 #include "include/radixsort.h"
5
6 typedef struct {
7 char *item;
8 unsigned rank;
9 } RankedHistoryItem;
2 10
3 11 static HistoryItems *history; static HistoryItems *history;
4 12 static HistoryItems *prioritizedHistory; static HistoryItems *prioritizedHistory;
 
... ... char *get_history_file() {
13 21 return fileName; return fileName;
14 22 } }
15 23
24 #define history_ranking_function(RANK, NEWORDEROCCURENCE) (RANK?RANK+NEWORDEROCCURENCE:NEWORDEROCCURENCE)
25
26 void dump_prioritized_history(HistoryItems *ph) {
27 printf("\n\nPrioritized history:");
28 int i;
29 for(i=0; i<ph->count; i++) {
30 if(ph->items[i]!=NULL) {
31 printf("\n%s",ph->items[i]); fflush(stdout);
32 } else {
33 printf("\n %d NULL",i); fflush(stdout);
34 }
35 }
36 printf("\n"); fflush(stdout);
37 }
38
16 39 HistoryItems *prioritize_history(HistoryItems *historyFileItems) { HistoryItems *prioritize_history(HistoryItems *historyFileItems) {
17 return historyFileItems;
40 HashMap rankmap;
41 hashmap_init(&rankmap);
42
43 HashSet blacklist;
44 hashset_init(&blacklist);
45 hashset_add(&blacklist, "ls");
46 hashset_add(&blacklist, "pwd");
47 hashset_add(&blacklist, "cd");
48 hashset_add(&blacklist, "hh");
49
50 RadixSorter rs;
51 radixsort_init(&rs);
52
53 RankedHistoryItem *r;
54 RadixItem *radixItem;
55 int i;
56 for(i=0; i<historyFileItems->count; i++) {
57 if(hashset_contains(&blacklist, historyFileItems->items[i])) {
58 continue;
59 }
60 if((r=hashmap_get(&rankmap, historyFileItems->items[i]))==NULL) {
61 r=(RankedHistoryItem *)malloc(sizeof(RankedHistoryItem));
62 r->rank=history_ranking_function(0, i);
63 r->item=historyFileItems->items[i];
64
65 hashmap_put(&rankmap, historyFileItems->items[i], r);
66
67 radixItem=(RadixItem *)malloc(sizeof(RadixItem));
68 radixItem->key=r->rank;
69 radixItem->data=r;
70 radixItem->next=NULL;
71 radixsort_add(&rs, radixItem);
72 } else {
73 //printf("\n>>> %s ", r->item); fflush(stdout);
74 radixItem=radix_cut(&rs, r->rank, r);
75
76 if(radixItem!=NULL) {
77 r->rank=history_ranking_function(r->rank, i);
78 radixItem->key=r->rank;
79 radixsort_add(&rs, radixItem);
80 } // TODO else assert
81 }
82 }
83
84 RadixItem **prioritizedRadix=radixsort_dump(&rs);
85 prioritizedHistory=(HistoryItems *)malloc(sizeof(HistoryItems));
86 prioritizedHistory->count=rs.size;
87 prioritizedHistory->items=malloc(rs.size * sizeof(char*));
88 for(i=0; i<rs.size; i++) {
89 printf("\n %d %p ",i,prioritizedRadix[i]->data);
90 if(prioritizedRadix[i]->data) {
91 prioritizedHistory->items[i]=((RankedHistoryItem *)(prioritizedRadix[i]->data))->item;
92 }
93 printf("\n %d %s ",i,((RankedHistoryItem *)(prioritizedRadix[i]->data))->item);
94 }
95
96 radixsort_destroy(&rs);
97
98 return prioritizedHistory;
18 99 } }
19 100
20 101 void free_prioritized_history() { void free_prioritized_history() {
21 //free(prioritizedHistory->items);
22 //free(prioritizedHistory);
102 // TODO free(prioritizedHistory->items);
103 // TODO free(prioritizedHistory);
23 104 } }
24 105
25 106
107
26 108 #ifdef GET_HISTORY_FROM_FILE #ifdef GET_HISTORY_FROM_FILE
27 109
28 110 static char *historyAsString; static char *historyAsString;
File src/hstr_utils.c changed (mode: 100644) (index 527dbbe..650f161)
... ... void tiocsti() {
12 12
13 13 void fill_terminal_input(char *cmd){ void fill_terminal_input(char *cmd){
14 14 size_t size = strlen(cmd); size_t size = strlen(cmd);
15 int i;
15 unsigned i;
16 16 char *c; char *c;
17 17 for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
18 18 // terminal I/O control, simulate terminal input // terminal I/O control, simulate terminal input
 
... ... void fill_terminal_input(char *cmd){
22 22 printf("\n"); printf("\n");
23 23 } }
24 24
25 void reverse_char_pointer_array(char **array, int length) {
26 int i;
25 void reverse_char_pointer_array(char **array, unsigned length) {
27 26 char *temp; char *temp;
27 unsigned i;
28 28 for (i=0; i<length/2; i++) { for (i=0; i<length/2; i++) {
29 29 temp = array[i]; temp = array[i];
30 30 array[i] = array[length-i-1]; array[i] = array[length-i-1];
File src/include/hashset.h changed (mode: 100644) (index e938b29..7df422b)
... ... struct HashNode {
12 12 struct HashNode *next; struct HashNode *next;
13 13 }; };
14 14
15 struct HashSetStruct {
15 typedef struct {
16 16 struct HashNode * lists[TABLE_SIZE]; struct HashNode * lists[TABLE_SIZE];
17 17 int currentSize; int currentSize;
18 };
19
20 typedef struct HashSetStruct HashSet;
18 } HashSet;
21 19
22 void hashset_init( HashSet * hs );
23 int hashset_contains( const HashSet * hs, const char *key );
24 int hashset_add( HashSet * hs, const char *key );
25 int hashset_remove( HashSet * hs, const char *key );
26 int hashset_size( const HashSet * hs );
27 void hashset_print( const HashSet * hs );
20 void hashset_init( HashSet *hs );
21 int hashset_contains( const HashSet *hs, const char *key );
22 int hashset_add( HashSet *hs, const char *key );
23 int hashset_remove( HashSet *hs, const char *key );
24 int hashset_size( const HashSet *hs );
25 void hashset_print( const HashSet *hs );
28 26
29 27 #endif #endif
File src/include/hstr_history.h changed (mode: 100644) (index 9fa3540..617aeb3)
20 20
21 21 typedef struct { typedef struct {
22 22 char **items; char **items;
23 int count;
23 unsigned count;
24 24 } HistoryItems; } HistoryItems;
25 25
26 26 HistoryItems *get_history_items(); HistoryItems *get_history_items();
File src/include/hstr_utils.h changed (mode: 100644) (index e8a9c53..2828c79)
8 8
9 9 void tiocsti(); void tiocsti();
10 10 void fill_terminal_input(char* cmd); void fill_terminal_input(char* cmd);
11 void reverse_char_pointer_array(char **array, int length);
11 void reverse_char_pointer_array(char **array, unsigned length);
12 12
13 13 #endif #endif
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