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 35513e47d0dd567a824e01d981e2b8b8d7cd5815

Polishing, Apache license headers, history from file loading removal, radix sort optimization impl started.
Author: Martin Dvorak
Author date (UTC): 2013-12-15 10:21
Committer name: Martin Dvorak
Committer date (UTC): 2013-12-15 10:21
Parent(s): 98d93e846eeb7123949a3283e2505de895d30440
Signing key:
Tree: 8ec7cb7b0f4693ad54b8c9e8ce02f08964b4b50c
File Lines added Lines deleted
README.md 0 5
src/hashmap.c 9 0
src/hashset.c 9 0
src/hstr.c 2 4
src/hstr_history.c 14 81
src/hstr_utils.c 9 0
src/include/hashmap.h 9 0
src/include/hashset.h 9 0
src/include/hstr_history.h 11 3
src/include/hstr_utils.h 9 0
src/include/radixsort.h 22 2
src/radixsort.c 28 6
File README.md changed (mode: 100644) (index bec98a5..3948310)
... ... BUGS
41 41 ---- ----
42 42 https://github.com/dvorka/hstr/issues https://github.com/dvorka/hstr/issues
43 43
44
45 AUTHOR
46 ------
47 martin.dvorak@mindforger.com
48
File src/hashmap.c changed (mode: 100644) (index 060751c..b90016e)
1 /*
2 ============================================================================
3 Name : hashmap.c
4 Author : martin.dvorak@midforger.com
5 Copyright : Apache 2.0
6 Description : Hash map
7 ============================================================================
8 */
9
1 10 #include "include/hashmap.h" #include "include/hashmap.h"
2 11
3 12 unsigned int hashmap_hash( const char *str ) { unsigned int hashmap_hash( const char *str ) {
File src/hashset.c changed (mode: 100644) (index 6f174be..1838543)
1 /*
2 ============================================================================
3 Name : hashset.h
4 Author : martin.dvorak@midforger.com
5 Copyright : Apache 2.0
6 Description : Hash set
7 ============================================================================
8 */
9
1 10 #include "include/hashset.h" #include "include/hashset.h"
2 11
3 12 unsigned int hash( const char *str ) { unsigned int hash( const char *str ) {
File src/hstr.c changed (mode: 100644) (index c1beee4..15ac6f1)
1 1 /* /*
2 2 ============================================================================ ============================================================================
3 3 Name : hstr.c Name : hstr.c
4 Author : Martin Dvorak
5 Version : 0.2
4 Author : martin.dvorak@midforger.com
6 5 Copyright : Apache 2.0 Copyright : Apache 2.0
7 6 Description : Shell history completion utility Description : Shell history completion utility
8 7 ============================================================================ ============================================================================
 
... ... char *selection_loop(HistoryItems *history) {
325 324 } }
326 325
327 326 void hstr() { void hstr() {
328 HistoryItems *historyFileItems=get_history_items();
329 HistoryItems *history=prioritize_history(historyFileItems);
327 HistoryItems *history=get_prioritized_history();
330 328 char *command = selection_loop(history); char *command = selection_loop(history);
331 329 fill_terminal_input(command); fill_terminal_input(command);
332 330 free_prioritized_history(); free_prioritized_history();
File src/hstr_history.c changed (mode: 100644) (index 6393bf3..a4731c5)
1 /*
2 ============================================================================
3 Name : hstr_history.h
4 Author : martin.dvorak@midforger.com
5 Copyright : Apache 2.0
6 Description : Loading and processing of BASH history
7 ============================================================================
8 */
9
1 10 #include "include/hstr_history.h" #include "include/hstr_history.h"
2 11 #include "include/hashset.h" #include "include/hashset.h"
3 12 #include "include/hashmap.h" #include "include/hashmap.h"
 
... ... void free_prioritized_history() {
101 110 // TODO free(prioritizedHistory); // TODO free(prioritizedHistory);
102 111 } }
103 112
104
105
106 #ifdef GET_HISTORY_FROM_FILE
107
108 static char *historyAsString;
109
110 char *load_history_file() {
111 char *fileName = get_history_file();
112 if(access(fileName, F_OK) != -1) {
113 char *file_contents;
114 long input_file_size;
115
116 FILE *input_file = fopen(fileName, "rb");
117 fseek(input_file, 0, SEEK_END);
118 input_file_size = ftell(input_file);
119 rewind(input_file);
120 file_contents = malloc((input_file_size + 1) * (sizeof(char)));
121 if(fread(file_contents, sizeof(char), input_file_size, input_file)==-1) {
122 exit(EXIT_FAILURE);
123 }
124 fclose(input_file);
125 file_contents[input_file_size] = 0;
126
127 return file_contents;
128 } else {
129 fprintf(stderr,"\nHistory file not found: %s\n",fileName);
130 exit(EXIT_FAILURE);
131 }
132 }
133
134 int count_history_lines(char *history) {
135 int i = 0;
136 char *p=strchr(history,'\n');
137 while (p!=NULL) {
138 i++;
139 p=strchr(p+1,'\n');
140 }
141 return i;
142 }
143
144 char **get_tokenized_history(char *history, int lines) {
145 char **tokens = malloc(sizeof(char*) * lines);
146
147 int i = 0;
148 char *pb=history, *pe;
149 pe=strchr(history, '\n');
150 while(pe!=NULL) {
151 tokens[i]=pb;
152 *pe=0;
153
154 pb=pe+1;
155 pe=strchr(pb, '\n');
156 i++;
157 }
158
159 return tokens;
160 }
161
162 char **get_history_items() {
163 historyAsString = load_history_file(FILE_HISTORY);
164 historyItemsCount = count_history_lines(historyAsString);
165 historyItems = get_tokenized_history(historyAsString, historyItemsCount);
166 reverse_char_pointer_array(historyItems, historyItemsCount);
167 return historyItems;
168 }
169
170 int get_history_items_size() {
171 return historyItemsCount;
172 }
173
174 void free_history_items() {
175 free(historyAsString);
176 free(historyItems);
177 }
178
179
180
181 #else
182
183
184 113 void flush_history() { void flush_history() {
185 114 const char *filename = "history"; const char *filename = "history";
186 115 char *const args[1] = {"-a"}; char *const args[1] = {"-a"};
 
... ... void free_history_items() {
235 164 free(history); free(history);
236 165 } }
237 166
167 HistoryItems *get_prioritized_history() {
168 HistoryItems *fileItems=get_history_items();
169 return prioritize_history(fileItems);
170 }
171
238 172
239 #endif
File src/hstr_utils.c changed (mode: 100644) (index 650f161..fb1bcb2)
1 /*
2 ============================================================================
3 Name : hstr_utils.c
4 Author : martin.dvorak@midforger.com
5 Copyright : Apache 2.0
6 Description : Utilities
7 ============================================================================
8 */
9
1 10 #include "include/hstr_utils.h" #include "include/hstr_utils.h"
2 11
3 12 #define DEFAULT_COMMAND "pwd" #define DEFAULT_COMMAND "pwd"
File src/include/hashmap.h changed (mode: 100644) (index 28b9eaa..ee522a6)
1 /*
2 ============================================================================
3 Name : hashmap.h
4 Author : martin.dvorak@midforger.com
5 Copyright : Apache 2.0
6 Description : Hash map
7 ============================================================================
8 */
9
1 10 #ifndef _HASHMAP_H_ #ifndef _HASHMAP_H_
2 11 #define _HASHMAP_H_ #define _HASHMAP_H_
3 12
File src/include/hashset.h changed (mode: 100644) (index 7df422b..1299a9f)
1 /*
2 ============================================================================
3 Name : hashset.h
4 Author : martin.dvorak@midforger.com
5 Copyright : Apache 2.0
6 Description : Hash set
7 ============================================================================
8 */
9
1 10 #ifndef _HASHSET_H #ifndef _HASHSET_H
2 11 #define _HASHSET_H #define _HASHSET_H
3 12
File src/include/hstr_history.h changed (mode: 100644) (index 617aeb3..198c2c9)
1 /*
2 ============================================================================
3 Name : hstr_history.h
4 Author : martin.dvorak@midforger.com
5 Copyright : Apache 2.0
6 Description : Loading and processing of BASH history
7 ============================================================================
8 */
9
1 10 #ifndef _HSTR_HISTORY_H_ #ifndef _HSTR_HISTORY_H_
2 11 #define _HSTR_HISTORY_H_ #define _HSTR_HISTORY_H_
3 12
 
9 18 #include <unistd.h> #include <unistd.h>
10 19 #include "hstr_utils.h" #include "hstr_utils.h"
11 20
12 //#define GET_HISTORY_FROM_FILE
13 #define GET_HISTORY_USING_LIBRARY
14
15 21 #define ENV_VAR_USER "USER" #define ENV_VAR_USER "USER"
16 22 #define ENV_VAR_HOME "HOME" #define ENV_VAR_HOME "HOME"
17 23 #define ENV_VAR_HISTFILE "HISTFILE" #define ENV_VAR_HISTFILE "HISTFILE"
 
... ... typedef struct {
23 29 unsigned count; unsigned count;
24 30 } HistoryItems; } HistoryItems;
25 31
32 HistoryItems *get_prioritized_history();
33
26 34 HistoryItems *get_history_items(); HistoryItems *get_history_items();
27 35 void free_history_items(); void free_history_items();
28 36
File src/include/hstr_utils.h changed (mode: 100644) (index 2828c79..451f747)
1 /*
2 ============================================================================
3 Name : hstr_utils.h
4 Author : martin.dvorak@midforger.com
5 Copyright : Apache 2.0
6 Description : Utilities
7 ============================================================================
8 */
9
1 10 #ifndef _HSTR_UTILS_H #ifndef _HSTR_UTILS_H
2 11 #define _HSTR_UTILS_H #define _HSTR_UTILS_H
3 12
File src/include/radixsort.h changed (mode: 100644) (index 25a1088..b290762)
1 /*
2 ============================================================================
3 Name : radixsort.h
4 Author : martin.dvorak@midforger.com
5 Copyright : Apache 2.0
6 Description : Radix sort
7 ============================================================================
8 */
9
1 10 #ifndef RADIXSORT_H_ #ifndef RADIXSORT_H_
2 11 #define RADIXSORT_H_ #define RADIXSORT_H_
3 12
13 #define SIX2FOUR_SIZE 1000
14
4 15 typedef struct radixitem { typedef struct radixitem {
5 16 unsigned key; unsigned key;
6 17 void *data; void *data;
7 18 struct radixitem *next; struct radixitem *next;
8 19 } RadixItem; } RadixItem;
9 20
10 #define SIX2FOUR_SIZE 1000
21 typedef struct radixslot {
22 unsigned key;
23 unsigned min;
24 unsigned max;
25 struct radixslot *next;
26 } RadixSlot;
11 27
12 28 typedef struct { typedef struct {
13 29 unsigned size; unsigned size;
14 unsigned maxValue;
30 unsigned maxKey;
15 31 RadixItem **six2four[SIX2FOUR_SIZE]; RadixItem **six2four[SIX2FOUR_SIZE];
32
33 unsigned _keyLimit;
34 RadixSlot *_slots;
35 unsigned _slotsCount;
16 36 } RadixSorter; } RadixSorter;
17 37
18 38 void radixsort_init(RadixSorter *rs); void radixsort_init(RadixSorter *rs);
File src/radixsort.c changed (mode: 100644) (index e64d060..5fa94a8)
1 /*
2 ============================================================================
3 Name : radixsort.c
4 Author : martin.dvorak@midforger.com
5 Copyright : Apache 2.0
6 Description : Radix sort
7 ============================================================================
8 */
9
1 10 #include "include/radixsort.h" #include "include/radixsort.h"
2 11 #include <stdlib.h> #include <stdlib.h>
3 12 #include <stdio.h> #include <stdio.h>
 
5 14 #include <string.h> #include <string.h>
6 15 #include <stddef.h> #include <stddef.h>
7 16
8 RadixItem **radixsort_get_slot() {
17 RadixItem **radixsort_get_slot(RadixSorter *rs, unsigned key) {
9 18 RadixItem **slot=malloc(SIX2FOUR_SIZE * sizeof(RadixItem*)); RadixItem **slot=malloc(SIX2FOUR_SIZE * sizeof(RadixItem*));
10 19 memset(slot, 0, SIX2FOUR_SIZE * sizeof(RadixItem*)); memset(slot, 0, SIX2FOUR_SIZE * sizeof(RadixItem*));
20 RadixSlot *slotDescriptor=malloc(sizeof(RadixSlot));
21 slotDescriptor->key=key;
22 slotDescriptor->min=0;
23 slotDescriptor->max=SIX2FOUR_SIZE;
24 if(rs->_slots) {
25 slotDescriptor->next=rs->_slots->next;
26 }
27 rs->_slots=slotDescriptor;
28 rs->_slotsCount++;
11 29 return slot; return slot;
12 30 } }
13 31
14 32 void radixsort_init(RadixSorter *rs) { void radixsort_init(RadixSorter *rs) {
15 33 rs->size=0; rs->size=0;
16 34 memset(rs->six2four, 0, SIX2FOUR_SIZE * sizeof(RadixItem*)); memset(rs->six2four, 0, SIX2FOUR_SIZE * sizeof(RadixItem*));
17 rs->maxValue=0;
35 rs->maxKey=0;
36 rs->_keyLimit=SIX2FOUR_SIZE*SIX2FOUR_SIZE;
37 rs->_slots=NULL;
38 rs->_slotsCount=0;
18 39 } }
19 40
20 41 void radixsort_add(RadixSorter *rs, RadixItem *item) { void radixsort_add(RadixSorter *rs, RadixItem *item) {
 
... ... void radixsort_add(RadixSorter *rs, RadixItem *item) {
23 44 unsigned three2zero=item->key-six2four*1000; unsigned three2zero=item->key-six2four*1000;
24 45
25 46 if(rs->six2four[six2four]==NULL) { if(rs->six2four[six2four]==NULL) {
26 rs->six2four[six2four]=radixsort_get_slot();
47 rs->six2four[six2four]=radixsort_get_slot(rs, six2four);
27 48 } }
28 49
29 50 RadixItem *chain=rs->six2four[six2four][three2zero]; RadixItem *chain=rs->six2four[six2four][three2zero];
 
... ... void radixsort_add(RadixSorter *rs, RadixItem *item) {
35 56 } }
36 57
37 58 rs->size++; rs->size++;
38 rs->maxValue=(rs->maxValue>item->key?rs->maxValue:item->key);
59 rs->maxKey=(rs->maxKey>item->key?rs->maxKey:item->key);
39 60 } }
40 61
41 62 RadixItem **radixsort_dump(RadixSorter *rs) { RadixItem **radixsort_dump(RadixSorter *rs) {
42 63 if(rs->size>0) { if(rs->size>0) {
43 64 RadixItem **result=malloc(rs->size * sizeof(RadixItem *)); RadixItem **result=malloc(rs->size * sizeof(RadixItem *));
44 double d = ((double)rs->maxValue)/1000.0;
65 double d = ((double)rs->maxKey)/1000.0;
45 66 int six2four = (int)trunc(d); int six2four = (int)trunc(d);
46 67
47 68 int s, t, i=0; int s, t, i=0;
48 69 s=six2four; s=six2four;
49 70 do { do {
71 // TODO optimization: iterate only _slots chain
50 72 t=SIX2FOUR_SIZE-1; t=SIX2FOUR_SIZE-1;
51 73 do { do {
52 74 if(rs->six2four[s]!=NULL) { if(rs->six2four[s]!=NULL) {
 
... ... RadixItem **radixsort_dump(RadixSorter *rs) {
69 91 } }
70 92
71 93 RadixItem *radix_cut(RadixSorter *rs, unsigned key, void *data) { RadixItem *radix_cut(RadixSorter *rs, unsigned key, void *data) {
72 if(key<=rs->maxValue) {
94 if(key<=rs->maxKey) {
73 95 double d = ((double) key)/1000.0; double d = ((double) key)/1000.0;
74 96 unsigned six2four = (unsigned)trunc(d); unsigned six2four = (unsigned)trunc(d);
75 97 unsigned three2zero=key-six2four*1000; unsigned three2zero=key-six2four*1000;
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