Browse Source

Rewrite command resolve function

Serj Kalichev 5 years ago
parent
commit
1d91d95e19
10 changed files with 118 additions and 89 deletions
  1. 4 4
      clish/command/command.c
  2. 7 7
      clish/nspace.h
  3. 5 4
      clish/nspace/nspace.c
  4. 0 2
      clish/shell/private.h
  5. 2 18
      clish/shell/shell_command.c
  6. 1 1
      clish/shell/shell_startup.c
  7. 11 11
      clish/view.h
  8. 53 31
      clish/view/view.c
  9. 6 2
      lub/list.h
  10. 29 9
      lub/list/list.c

+ 4 - 4
clish/command/command.c

@@ -149,11 +149,11 @@ int clish_command_help(const clish_command_t *this)
 }
 
 /*--------------------------------------------------------- */
-clish_command_t *clish_command_choose_longest(clish_command_t * cmd1,
-	clish_command_t * cmd2)
+clish_command_t *clish_command_choose_longest(clish_command_t *cmd1,
+	clish_command_t *cmd2)
 {
-	unsigned len1 = (cmd1 ? strlen(clish_command__get_name(cmd1)) : 0);
-	unsigned len2 = (cmd2 ? strlen(clish_command__get_name(cmd2)) : 0);
+	unsigned int len1 = (cmd1 ? strlen(clish_command__get_name(cmd1)) : 0);
+	unsigned int len2 = (cmd2 ? strlen(clish_command__get_name(cmd2)) : 0);
 
 	if (len2 < len1) {
 		return cmd1;

+ 7 - 7
clish/nspace.h

@@ -24,14 +24,14 @@ typedef enum {
 clish_nspace_t *clish_nspace_new(const char *view_name);
 
 void clish_nspace_delete(void *instance);
-const clish_command_t *clish_nspace_find_next_completion(clish_nspace_t *
-	instance, const char *iter_cmd, const char *line,
+const clish_command_t *clish_nspace_find_next_completion(clish_nspace_t *instance,
+	const char *iter_cmd, const char *line,
 	clish_nspace_visibility_e field);
-clish_command_t *clish_nspace_find_command(clish_nspace_t * instance, const char *name);
-void clish_nspace_dump(const clish_nspace_t * instance);
-clish_command_t * clish_nspace_create_prefix_cmd(clish_nspace_t * instance,
-	const char * name, const char * help);
-void clish_nspace_clean_proxy(clish_nspace_t * instance);
+clish_command_t *clish_nspace_resolve_prefix(clish_nspace_t *instance, const char *name);
+void clish_nspace_dump(const clish_nspace_t *instance);
+clish_command_t * clish_nspace_create_prefix_cmd(clish_nspace_t *instance,
+	const char *name, const char *help);
+void clish_nspace_clean_proxy(clish_nspace_t *instance);
 
 _CLISH_SET(nspace, bool_t, help);
 _CLISH_GET(nspace, bool_t, help);

+ 5 - 4
clish/nspace/nspace.c

@@ -5,6 +5,7 @@
  */
 #include "private.h"
 #include "lub/string.h"
+#include "lub/ctype.h"
 
 #include <assert.h>
 #include <stdlib.h>
@@ -170,7 +171,7 @@ static const char *clish_nspace_after_prefix(const regex_t *prefix_regex,
 }
 
 /*--------------------------------------------------------- */
-clish_command_t *clish_nspace_find_command(clish_nspace_t * this, const char *name)
+clish_command_t *clish_nspace_resolve_prefix(clish_nspace_t *this, const char *name)
 {
 	clish_command_t *cmd = NULL, *retval = NULL;
 	clish_view_t *view = clish_nspace__get_view(this);
@@ -178,18 +179,18 @@ clish_command_t *clish_nspace_find_command(clish_nspace_t * this, const char *na
 	char *real_prefix = NULL;
 
 	if (!clish_nspace__get_prefix(this))
-		return clish_view_find_command(view, name, this->inherit);
+		return clish_view_resolve_prefix(view, name);
 
 	if (!(in_line = clish_nspace_after_prefix(
 		clish_nspace__get_prefix_regex(this), name, &real_prefix)))
 		return NULL;
 
 	/* If prefix is followed by space */
-	if (in_line[0] == ' ')
+	while (lub_ctype_isspace(in_line[0]))
 		in_line++;
 
 	if (in_line[0] != '\0') {
-		cmd = clish_view_find_command(view, in_line, this->inherit);
+		cmd = clish_view_resolve_prefix(view, in_line);
 		if (!cmd) {
 			lub_string_free(real_prefix);
 			return NULL;

+ 0 - 2
clish/shell/private.h

@@ -127,8 +127,6 @@ char *clish_shell_word_generator(clish_shell_t * instance,
 	const char *line, unsigned offset, unsigned state);
 const clish_command_t *clish_shell_resolve_command(const clish_shell_t *
 	instance, const char *line);
-const clish_command_t *clish_shell_resolve_prefix(const clish_shell_t *
-	instance, const char *line);
 void clish_shell_tinyrl_history(clish_shell_t * instance, unsigned int *limit);
 tinyrl_t *clish_shell_tinyrl_new(FILE * instream,
 	FILE * outstream, unsigned stifle);

+ 2 - 18
clish/shell/shell_command.c

@@ -22,25 +22,9 @@ const clish_command_t *clish_shell_resolve_command(const clish_shell_t * this,
 	clish_command_t *cmd, *result;
 
 	/* Search the current view */
-	result = clish_view_resolve_command(clish_shell__get_view(this), line, BOOL_TRUE);
+	result = clish_view_resolve_command(clish_shell__get_view(this), line);
 	/* Search the global view */
-	cmd = clish_view_resolve_command(this->global, line, BOOL_TRUE);
-
-	result = clish_command_choose_longest(result, cmd);
-
-	return result;
-}
-
-/*--------------------------------------------------------- */
-const clish_command_t *clish_shell_resolve_prefix(const clish_shell_t * this,
-	const char *line)
-{
-	clish_command_t *cmd, *result;
-
-	/* Search the current view */
-	result = clish_view_resolve_prefix(clish_shell__get_view(this), line, BOOL_TRUE);
-	/* Search the global view */
-	cmd = clish_view_resolve_prefix(this->global, line, BOOL_TRUE);
+	cmd = clish_view_resolve_command(this->global, line);
 
 	result = clish_command_choose_longest(result, cmd);
 

+ 1 - 1
clish/shell/shell_startup.c

@@ -286,7 +286,7 @@ int clish_shell_prepare(clish_shell_t *this)
 				if (!aview /* Removed or broken VIEW */
 					||
 					/* Removed or broken referenced COMMAND */
-					!(cmdref = clish_view_find_command(aview, clish_command__get_alias(cmd), BOOL_FALSE))
+					!(cmdref = clish_view_find_command(aview, clish_command__get_alias(cmd)))
 					) {
 #ifdef DEBUG
 					fprintf(stderr, "Warning: Remove unresolved link \"%s\" from \"%s\" VIEW\n",

+ 11 - 11
clish/view.h

@@ -32,20 +32,20 @@ typedef enum {
 clish_view_t *clish_view_new(const char *name);
 int clish_view_compare(const void *clientnode, const void *clientkey);
 void clish_view_delete(void *instance);
-clish_command_t *clish_view_new_command(clish_view_t * instance,
+clish_command_t *clish_view_new_command(clish_view_t *instance,
 	const char *name, const char *text);
-clish_command_t *clish_view_find_command(clish_view_t * instance,
-	const char *name, bool_t inherit);
-const clish_command_t *clish_view_find_next_completion(clish_view_t * instance,
+clish_command_t *clish_view_find_command(clish_view_t *instance,
+	const char *name);
+const clish_command_t *clish_view_find_next_completion(clish_view_t *instance,
 	const char *iter_cmd, const char *line,
 	clish_nspace_visibility_e field, bool_t inherit);
-clish_command_t *clish_view_resolve_command(clish_view_t * instance,
-	const char *line, bool_t inherit);
-clish_command_t *clish_view_resolve_prefix(clish_view_t * instance,
-	const char *line, bool_t inherit);
-void clish_view_dump(clish_view_t * instance);
-void clish_view_insert_nspace(clish_view_t * instance, clish_nspace_t * nspace);
-void clish_view_clean_proxy(clish_view_t * instance);
+clish_command_t *clish_view_resolve_command(clish_view_t *instance,
+	const char *line);
+clish_command_t *clish_view_resolve_prefix(clish_view_t *instance,
+	const char *line);
+void clish_view_dump(clish_view_t *instance);
+void clish_view_insert_nspace(clish_view_t *instance, clish_nspace_t *nspace);
+void clish_view_clean_proxy(clish_view_t *instance);
 int clish_view_insert_hotkey(const clish_view_t *instance, const char *key, const char *cmd);
 const char *clish_view_find_hotkey(const clish_view_t *instance, int code);
 

+ 53 - 31
clish/view/view.c

@@ -100,6 +100,19 @@ clish_command_t *clish_view_new_command(clish_view_t *this,
 	return cmd;
 }
 
+/*--------------------------------------------------------- */
+static int cmd_resolve(const void *key, const void *data)
+{
+	const char *line = (const char *)key;
+	const clish_command_t *d = (const clish_command_t *)data;
+	const char *name = clish_command__get_name(d);
+	size_t eq = lub_string_equal_part(line, name, BOOL_FALSE);
+	if (eq == strlen(name))
+		if ((line[eq] == '\0') || lub_ctype_isspace(line[eq]))
+			return 0;
+	return lub_string_nocasecmp(line, name);
+}
+
 /*--------------------------------------------------------- */
 /* This method identifies the command (if any) which provides
  * the longest match with the specified line of text.
@@ -108,7 +121,36 @@ clish_command_t *clish_view_new_command(clish_view_t *this,
  *
  * this - the view instance upon which to operate
  * line - the command line to analyse 
+ *
+ * Begin to search from tail of sorted list of cmds. So
+ * the first match will be the longest command.
  */
+clish_command_t *clish_view_resolve_prefix(clish_view_t *this,
+	const char *line)
+{
+	lub_list_node_t *iter;
+	clish_command_t *res = NULL;
+
+	res = lub_list_rfind(this->cmds, cmd_resolve, line);
+
+	/* Iterate elements. It's important to iterate
+	 * items starting from tail because the next
+	 * NAMESPACE has higher priority than previous one
+	 * in a case then the both NAMESPACEs have the
+	 * commands with the same name.
+	 */
+	for (iter = lub_list__get_tail(this->nspaces);
+		iter; iter = lub_list_node__get_prev(iter)) {
+		clish_nspace_t *nspace = (clish_nspace_t *)lub_list_node__get_data(iter);
+		clish_command_t *cmd = clish_nspace_resolve_prefix(nspace, line);
+		/* Choose the longest match */
+		res = clish_command_choose_longest(res, cmd);
+	}
+
+	return res;
+}
+
+#if 0 // WORK
 clish_command_t *clish_view_resolve_prefix(clish_view_t *this,
 	const char *line, bool_t inherit)
 {
@@ -143,11 +185,15 @@ clish_command_t *clish_view_resolve_prefix(clish_view_t *this,
 	return result;
 }
 
+
+
+#endif
+
 /*--------------------------------------------------------- */
 clish_command_t *clish_view_resolve_command(clish_view_t *this,
-	const char *line, bool_t inherit)
+	const char *line)
 {
-	clish_command_t *result = clish_view_resolve_prefix(this, line, inherit);
+	clish_command_t *result = clish_view_resolve_prefix(this, line);
 
 	if (result) {
 		clish_action_t *action = clish_command__get_action(result);
@@ -168,40 +214,16 @@ clish_command_t *clish_view_resolve_command(clish_view_t *this,
 }
 
 /*--------------------------------------------------------- */
+/* Search for local (without NAMESPACEs) command by name */
 clish_command_t *clish_view_find_command(clish_view_t *this,
-	const char *name, bool_t inherit)
+	const char *name)
 {
-	clish_command_t *result = NULL;
-
-	/* Search the current view */
-	result = lub_list_find(this->cmds, clish_command_fn_find_by_name, name);
-
-	if (inherit) {
-		lub_list_node_t *iter;
-		clish_command_t *cmd;
-		clish_nspace_t *nspace;
-
-		/* Iterate elements. It's important to iterate
-		 * items starting from tail because the next
-		 * NAMESPACE has higher priority than previous one
-		 * in a case then the both NAMESPACEs have the
-		 * commands with the same name.
-		 */
-		for(iter = lub_list__get_tail(this->nspaces);
-			iter; iter = lub_list_node__get_prev(iter)) {
-			nspace = (clish_nspace_t *)lub_list_node__get_data(iter);
-			cmd = clish_nspace_find_command(nspace, name);
-			/* Choose the longest match */
-			result = clish_command_choose_longest(result, cmd);
-		}
-	}
-
-	return result;
+	return lub_list_find(this->cmds, clish_command_fn_find_by_name, name);
 }
 
 /*--------------------------------------------------------- */
-static const clish_command_t *find_next_completion(clish_view_t * this,
-		const char *iter_cmd, const char *line)
+static const clish_command_t *find_next_completion(clish_view_t *this,
+	const char *iter_cmd, const char *line)
 {
 #if 0 // WORK
 	clish_command_t *cmd;

+ 6 - 2
lub/list.h

@@ -37,14 +37,18 @@ void lub_list_del(lub_list_t *list, lub_list_node_t *node);
 unsigned int lub_list_len(lub_list_t *list);
 lub_list_node_t *lub_list_match_node(lub_list_t *list,
 	lub_list_match_fn matchFn, const void *userkey,
-	lub_list_node_t **saveptr);
+	lub_list_node_t **saveptr, bool_t reverse);
 void *lub_list_find_node(lub_list_t *list,
 	lub_list_match_fn matchFn, const void *userkey);
+void *lub_list_rfind_node(lub_list_t *list,
+	lub_list_match_fn matchFn, const void *userkey);
 void *lub_list_match(lub_list_t *list,
 	lub_list_match_fn matchFn, const void *userkey,
-	lub_list_node_t **saveptr);
+	lub_list_node_t **saveptr, bool_t reverse);
 void *lub_list_find(lub_list_t *list,
 	lub_list_match_fn matchFn, const void *userkey);
+void *lub_list_rfind(lub_list_t *list,
+	lub_list_match_fn matchFn, const void *userkey);
 
 _END_C_DECL
 #endif				/* _lub_list_h */

+ 29 - 9
lub/list/list.c

@@ -231,7 +231,7 @@ inline void lub_list_node_copy(lub_list_node_t *dst, lub_list_node_t *src)
 /*--------------------------------------------------------- */
 lub_list_node_t *lub_list_match_node(lub_list_t *this,
 	lub_list_match_fn matchFn, const void *userkey,
-	lub_list_node_t **saveptr)
+	lub_list_node_t **saveptr, bool_t reverse)
 {
 	lub_list_node_t *iter = NULL;
 	if (!this || !matchFn || !this->head)
@@ -239,18 +239,23 @@ lub_list_node_t *lub_list_match_node(lub_list_t *this,
 	if (saveptr)
 		iter = *saveptr;
 	if (!iter)
-		iter = this->head;
+		iter = reverse ? this->tail : this->head;
 	while (iter) {
 		int res;
 		lub_list_node_t *node = iter;
-		iter = lub_list_node__get_next(iter);
+		iter = reverse ? lub_list_node__get_prev(iter) : lub_list_node__get_next(iter);
 		if (saveptr)
 			*saveptr = iter;
 		res = matchFn(userkey, lub_list_node__get_data(node));
 		if (!res)
 			return node;
-		if (res < 0) // No chances to find match
-			return NULL;
+		if (reverse) {
+			if (res > 0) // No chances to find match
+				return NULL;
+		} else {
+			if (res < 0) // No chances to find match
+				return NULL;
+		}
 	}
 
 	return NULL;
@@ -260,15 +265,23 @@ lub_list_node_t *lub_list_match_node(lub_list_t *this,
 void *lub_list_find_node(lub_list_t *this,
 	lub_list_match_fn matchFn, const void *userkey)
 {
-	return lub_list_match_node(this, matchFn, userkey, NULL);
+	return lub_list_match_node(this, matchFn, userkey, NULL, BOOL_FALSE);
+}
+
+/*--------------------------------------------------------- */
+void *lub_list_rfind_node(lub_list_t *this,
+	lub_list_match_fn matchFn, const void *userkey)
+{
+	return lub_list_match_node(this, matchFn, userkey, NULL, BOOL_TRUE);
 }
 
 /*--------------------------------------------------------- */
 void *lub_list_match(lub_list_t *this,
 	lub_list_match_fn matchFn, const void *userkey,
-	lub_list_node_t **saveptr)
+	lub_list_node_t **saveptr, bool_t reverse)
 {
-	lub_list_node_t *res = lub_list_match_node(this, matchFn, userkey, saveptr);
+	lub_list_node_t *res = lub_list_match_node(this, matchFn,
+		userkey, saveptr, reverse);
 	if (!res)
 		return NULL;
 	return lub_list_node__get_data(res);
@@ -278,7 +291,14 @@ void *lub_list_match(lub_list_t *this,
 void *lub_list_find(lub_list_t *this,
 	lub_list_match_fn matchFn, const void *userkey)
 {
-	return lub_list_match(this, matchFn, userkey, NULL);
+	return lub_list_match(this, matchFn, userkey, NULL, BOOL_FALSE);
+}
+
+/*--------------------------------------------------------- */
+void *lub_list_rfind(lub_list_t *this,
+	lub_list_match_fn matchFn, const void *userkey)
+{
+	return lub_list_match(this, matchFn, userkey, NULL, BOOL_TRUE);
 }
 
 /*--------------------------------------------------------- */