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 9984ad7376cb2682e09ba22f39526089a927717a

Split: view, match and case parameters. Compilable source, but functionally not complete yet.
Author: Martin Dvorak
Author date (UTC): 2014-04-22 06:21
Committer name: Martin Dvorak
Committer date (UTC): 2014-04-22 06:21
Parent(s): 634fed2911b036f06767844a202b5e5fd7c22b1c
Signing key:
Tree: 8e02ee050a1927044bc0aa5d37dc2319ed70b519
File Lines added Lines deleted
src/hashset.c 21 10
src/hstr.c 27 14
src/hstr_regexp.c 60 0
src/include/hashset.h 7 5
src/include/hstr_regexp.h 29 0
tests/src/test_regexp.c 16 5
tests/test_regexp.sh 1 0
File src/hashset.c changed (mode: 100644) (index ba4333f..0f79a2a)
... ... int hashset_contains(const HashSet * hs, const char *key)
47 47 return (hashset_get(hs, key) != NULL); return (hashset_get(hs, key) != NULL);
48 48 } }
49 49
50 int hashset_put(HashSet * hs, const char *key, void *value)
50 int hashset_put(HashSet *hs, const char *key, void *value)
51 51 { {
52 52 struct HashSetNode *newNode; struct HashSetNode *newNode;
53 53 int listNum; int listNum;
 
... ... int hashset_put(HashSet * hs, const char *key, void *value)
58 58 listNum = hashmap_hash( key ); listNum = hashmap_hash( key );
59 59
60 60
61 newNode = (struct HashSetNode *) malloc( sizeof ( struct HashSetNode ) );
61 newNode=(struct HashSetNode *)malloc(sizeof(struct HashSetNode));
62 62 if( newNode == NULL ) { if( newNode == NULL ) {
63 fprintf( stderr, "Error allocating node" );
63 fprintf( stderr,"Error allocating node");
64 64 return 0; return 0;
65 65 } }
66 66
67 newNode->key = malloc(strlen(key)+1);
67 newNode->key=malloc(strlen(key)+1);
68 68 strcpy(newNode->key, key); strcpy(newNode->key, key);
69 newNode->value = value;
70 newNode->next = hs->lists[ listNum ];
71 hs->lists[ listNum ] = newNode;
69 newNode->value=value;
70 newNode->next=hs->lists[listNum];
71 hs->lists[listNum]=newNode;
72 72 hs->currentSize++; hs->currentSize++;
73 73
74 74 return 1; return 1;
75 75 } }
76 76
77 int hashset_add(HashSet * hs, const char *key)
77 int hashset_add(const HashSet * hs, const char *key)
78 78 { {
79 79 return hashset_put(hs, key, "nil"); return hashset_put(hs, key, "nil");
80 80 } }
81 81
82 int hashset_size(const HashSet * hs)
82 int hashset_size(const HashSet *hs)
83 83 { {
84 84 return hs->currentSize; return hs->currentSize;
85 85 } }
86 86
87 void hashset_stat( const HashSet * hs )
87 void hashset_stat(const HashSet *hs)
88 88 { {
89 89 int i; int i;
90 90 struct HashSetNode *ptr; struct HashSetNode *ptr;
 
... ... void hashset_stat( const HashSet * hs )
93 93 for( ptr = hs->lists[ i ]; ptr != NULL; ptr = ptr->next ) for( ptr = hs->lists[ i ]; ptr != NULL; ptr = ptr->next )
94 94 printf( "%s\n", ptr->key ); printf( "%s\n", ptr->key );
95 95 } }
96
97 char** hashset_keys(const HashSet *hs)
98 {
99 // TODO to be implemented
100 return NULL;
101 }
102
103 void hashset_destroy(const HashSet *hs)
104 {
105 // TODO to be implemented
106 }
File src/hstr.c changed (mode: 100644) (index b63a5fa..fd8c5fb)
25 25 #include "include/hstr_curses.h" #include "include/hstr_curses.h"
26 26 #include "include/hstr_favorites.h" #include "include/hstr_favorites.h"
27 27 #include "include/hstr_history.h" #include "include/hstr_history.h"
28 #include "include/hstr_regexp.h"
28 29 #include "include/hstr_utils.h" #include "include/hstr_utils.h"
29 30
30 31 #define SELECTION_CURSOR_IN_PROMPT -1 #define SELECTION_CURSOR_IN_PROMPT -1
 
78 79 #define HH_DEBUG_LEVEL_WARN 1 #define HH_DEBUG_LEVEL_WARN 1
79 80 #define HH_DEBUG_LEVEL_DEBUG 2 #define HH_DEBUG_LEVEL_DEBUG 2
80 81
81 #define HH_VIEW_RANKING 0
82 #define HH_VIEW_HISTORY 1
83 #define HH_VIEW_FAVORITES 2
82 #define HH_VIEW_RANKING 0
83 #define HH_VIEW_HISTORY 1
84 #define HH_VIEW_FAVORITES 2
84 85
85 86 #define HH_MATCH_CASE_INSENSITIVE 0 #define HH_MATCH_CASE_INSENSITIVE 0
86 87 #define HH_MATCH_REGEXP 1 #define HH_MATCH_REGEXP 1
87 88 #define HH_MATCH_CASE_SENSITIVE 2 #define HH_MATCH_CASE_SENSITIVE 2
88 89
90 #define HH_CASE_INSENSITIVE 0
91 #define HH_CASE_SENSITIVE 1
92
89 93 #define SPACE_PADDING " " #define SPACE_PADDING " "
90 94
91 95 #ifdef DEBUG_KEYS #ifdef DEBUG_KEYS
 
... ... static const char *HH_VIEW_LABELS[]={
107 111 }; };
108 112
109 113 static const char *HH_MATCH_LABELS[]={ static const char *HH_MATCH_LABELS[]={
110 "case-insensitive",
111 "regexp",
112 "case-sensitive"};
114 "sensitive",
115 "insensitive"
116 };
117
118 static const char *HH_CASE_LABELS[]={
119 "exact",
120 "regexp"
121 };
113 122
114 123 static const char *INSTALL_STRING= static const char *INSTALL_STRING=
115 124 "\n# add this configuration to ~/.bashrc" "\n# add this configuration to ~/.bashrc"
 
... ... static const char *VERSION_STRING=
144 153 static const char *LABEL_HELP= static const char *LABEL_HELP=
145 154 "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";
146 155
147 // TODO makes this file non-reentrant
156 // TODO makes hstr.c non-reentrant
148 157 static char screenLine[CMDLINE_LNG]; static char screenLine[CMDLINE_LNG];
149 158
150 159 typedef struct { typedef struct {
 
... ... typedef struct {
154 163 char **selection; char **selection;
155 164 unsigned selectionSize; unsigned selectionSize;
156 165
157 int historyMatch;
158 int historyView;
166 int historyMatch; // TODO patternMatching: exact, regexp
167 int historyView; // TODO view: favs, ...
168 int caseSensitive;
159 169
160 170 bool hicolor; bool hicolor;
161 171 int debugLevel; int debugLevel;
162 172
163 HashSet regexpCache;
173 HstrRegexp regexp;
164 174
165 175 char cmdline[CMDLINE_LNG]; char cmdline[CMDLINE_LNG];
166 176 } Hstr; } Hstr;
 
... ... void hstr_init(Hstr *hstr)
172 182 hstr->selection=NULL; hstr->selection=NULL;
173 183 hstr->selectionSize=0; hstr->selectionSize=0;
174 184
175 hstr->debugLevel=HH_DEBUG_LEVEL_NONE;
176
177 185 hstr->historyMatch=HH_MATCH_CASE_INSENSITIVE; hstr->historyMatch=HH_MATCH_CASE_INSENSITIVE;
178 186 hstr->historyView=HH_VIEW_RANKING; hstr->historyView=HH_VIEW_RANKING;
187 hstr->caseSensitive=HH_CASE_INSENSITIVE;
179 188
180 189 hstr->hicolor=FALSE; hstr->hicolor=FALSE;
181 190
182 hashset_init(&hstr->regexpCache);
191 hstr->debugLevel=HH_DEBUG_LEVEL_NONE;
192
193 hstr_regexp_init(&hstr->regexp);
183 194 } }
184 195
185 196 void hstr_get_env_configuration(Hstr *hstr) void hstr_get_env_configuration(Hstr *hstr)
 
... ... void print_cmd_added_favorite_label(char *cmd, Hstr *hstr)
275 286 void print_history_label(Hstr *hstr) void print_history_label(Hstr *hstr)
276 287 { {
277 288 int width=getmaxx(stdscr); int width=getmaxx(stdscr);
278 snprintf(screenLine, width, "- HISTORY - view:%s (C-/) - match:%s (C-t) - %d/%d ",
289
290 snprintf(screenLine, width, "- HISTORY - view:%s (C-/) - match:%s (C-t) - case:%s (C-.) - %d/%d ",
279 291 HH_VIEW_LABELS[hstr->historyView], HH_VIEW_LABELS[hstr->historyView],
280 292 HH_MATCH_LABELS[hstr->historyMatch], HH_MATCH_LABELS[hstr->historyMatch],
293 HH_CASE_LABELS[hstr->caseSensitive],
281 294 hstr->history->count, hstr->history->count,
282 295 hstr->history->rawCount); hstr->history->rawCount);
283 296 width -= strlen(screenLine); width -= strlen(screenLine);
File src/hstr_regexp.c added (mode: 100644) (index 0000000..eda1a8a)
1 /*
2 ============================================================================
3 Name : hstr_regexp.c
4 Author : martin.dvorak@mindforger.com
5 Copyright : Apache 2.0
6 Description : Simplified regexp that suits HSTR needs - matching and caching
7 ============================================================================
8 */
9
10 #include "include/hstr_regexp.h"
11
12 #define REGEXP_MATCH_BUFFER_SIZE 1
13
14 void hstr_regexp_init(HstrRegexp *hstrRegexp)
15 {
16 hashset_init(&hstrRegexp->cache);
17 }
18
19 bool hstr_match(HstrRegexp *hstrRegexp, char *regexp, char *text, regmatch_t *match)
20 {
21 regex_t* compiled=malloc(sizeof(regex_t));
22 if(hashset_contains(&hstrRegexp->cache,regexp)) {
23 compiled=hashset_get(&hstrRegexp->cache, regexp);
24 } else {
25 int compilationFlags=(hstrRegexp->caseSensitive?0:REG_ICASE);
26 //printf("Regular expressions matching:\n '%s'\n '%s'",text,regexp);
27 int compilationStatus=regcomp(compiled, regexp, compilationFlags);
28 //printf("\nCompilation: %d",compilationStatus);
29 if(!compilationStatus) {
30 hashset_put(&hstrRegexp->cache, strdup(regexp), compiled);
31 } else {
32 free(compiled);
33 // TODO error handling: regerror() to turn error codes to messages
34 return false;
35 }
36 }
37
38 int matches=REGEXP_MATCH_BUFFER_SIZE;
39 regmatch_t matchPtr[REGEXP_MATCH_BUFFER_SIZE];
40 int matchingFlags=0;
41 int matchingStatus=regexec(compiled, text, matches, matchPtr, matchingFlags);
42 //printf("\nMatching (status/matches): %s %d",(!matchingStatus?"match":"no-match"),matches);
43
44 if(!matchingStatus) {
45 //printf("\n %d %d",matchPtr[0].rm_so, matchPtr[0].rm_eo);
46 if(matchPtr[0].rm_so != -1) {
47 //printf("\n* %d %d",matchPtr[0].rm_so,matchPtr[0].rm_eo);
48 match->rm_so=matchPtr[0].rm_so;
49 match->rm_eo=matchPtr[0].rm_eo;
50 return true;
51 }
52 }
53 return false;
54 }
55
56 void hstr_regexp_destroy(HstrRegexp *hstrRegexp)
57 {
58 // TODO hashset_destroy();
59 }
60
File src/include/hashset.h changed (mode: 100644) (index 5b5f5af..43f4bd8)
... ... struct HashSetNode {
23 23 }; };
24 24
25 25 typedef struct { typedef struct {
26 struct HashSetNode * lists[HASH_MAP_SIZE];
26 struct HashSetNode *lists[HASH_MAP_SIZE];
27 27 int currentSize; int currentSize;
28 28 } HashSet; } HashSet;
29 29
30 30 void hashset_init(HashSet *hs); void hashset_init(HashSet *hs);
31 31
32 32 int hashset_contains(const HashSet *hs, const char *key); int hashset_contains(const HashSet *hs, const char *key);
33 int hashset_add(HashSet *hs, const char *key);
33 int hashset_add(const HashSet *hs, const char *key);
34 34 int hashset_size(const HashSet *hs); int hashset_size(const HashSet *hs);
35 char** hashset_keys(const HashSet *hs);
35 36
36 37 void *hashset_get(const HashSet *hm, const char *key); void *hashset_get(const HashSet *hm, const char *key);
37 38 int hashset_put(HashSet *hm, const char *key, void *value); int hashset_put(HashSet *hm, const char *key, void *value);
38 int hashset_remove(HashSet *hm, const char *key);
39
39 int hashset_remove(const HashSet *hm, const char *key);
40 40 void hashset_stat(const HashSet *hm); void hashset_stat(const HashSet *hm);
41 41
42 #endif /* HASHSET_H_ */
42 void hashset_destroy(const HashSet *hs);
43
44 #endif
File src/include/hstr_regexp.h added (mode: 100644) (index 0000000..3ae8238)
1 /*
2 ============================================================================
3 Name : hstr_regexp.h
4 Author : martin.dvorak@mindforger.com
5 Copyright : Apache 2.0
6 Description : Simplified regexp that suits HSTR needs - matching and caching
7 ============================================================================
8 */
9
10 #ifndef _HSTR_REGEXP_H
11 #define _HSTR_REGEXP_H
12
13 #include <regex.h>
14 #include <stdio.h>
15 #include <stdbool.h>
16
17 #include "hashset.h"
18
19 typedef struct {
20 bool caseSensitive;
21
22 HashSet cache;
23 } HstrRegexp;
24
25 void hstr_regexp_init(HstrRegexp *hstrRegexp);
26 bool hstr_match(HstrRegexp *hstrRegexp, char *regexp, char *text, regmatch_t *match);
27 void hstr_regexp_destroy(HstrRegexp *hstrRegexp);
28
29 #endif
File tests/src/test_regexp.c changed (mode: 100644) (index 6592c03..11a2f88)
11 11 #include <stdio.h> #include <stdio.h>
12 12 #include <stdbool.h> #include <stdbool.h>
13 13
14 #define REGEXP_MATCH_BUFFER_SIZE 10
15
14 16 void main() { void main() {
15 17 bool caseSensitive=false; bool caseSensitive=false;
16 18
17 char *regexp="a";
19 char *regexp="^b";
18 20 char *text="This is a command that I want to match: go.sh there"; char *text="This is a command that I want to match: go.sh there";
19 21
20 22 regex_t compiled; regex_t compiled;
 
... ... void main() {
23 25 int compilationStatus=regcomp(&compiled, regexp, compilationFlags); int compilationStatus=regcomp(&compiled, regexp, compilationFlags);
24 26 printf("\nCompilation: %d",compilationStatus); printf("\nCompilation: %d",compilationStatus);
25 27
26 int matches;
27 regmatch_t **matchPtr;
28 int matches=REGEXP_MATCH_BUFFER_SIZE;
29 regmatch_t matchPtr[REGEXP_MATCH_BUFFER_SIZE];
28 30 int matchingFlags=0; int matchingFlags=0;
29 31 int matchingStatus=regexec(&compiled, text, matches, matchPtr, matchingFlags); int matchingStatus=regexec(&compiled, text, matches, matchPtr, matchingFlags);
30 printf("\nMatching (status/matches/ptr): %d %d %p",matchingStatus,matches,matchPtr);
32 printf("\nMatching (status/matches): %s %d",(!matchingStatus?"match":"no-match"),matches);
33
34 if(!matchingStatus) {
35 int i;
36 for(i=0; i<REGEXP_MATCH_BUFFER_SIZE; i++) {
37 printf("\n %d %d",matchPtr[i].rm_so, matchPtr[i].rm_eo);
38 if(matchPtr[i].rm_so != -1) {
39 printf("\n* %d %d",matchPtr[i].rm_so,matchPtr[i].rm_eo);
40 }
41 }
42 }
31 43
32 44 printf("\n"); printf("\n");
33 45 } }
34
File tests/test_regexp.sh changed (mode: 100755) (index c222ac1..2bcc63c)
1 1 #!/bin/bash #!/bin/bash
2 2
3 clear
3 4 rm -vf _regexp rm -vf _regexp
4 5 gcc ./src/test_regexp.c -o _regexp gcc ./src/test_regexp.c -o _regexp
5 6 ./_regexp ./_regexp
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