Browse Source

Unfinished implementation of the command aliases.

git-svn-id: https://klish.googlecode.com/svn/trunk@315 0eaa4687-2ee9-07dd-09d9-bcdd2d2dd5fb
Serj Kalichev 13 years ago
parent
commit
a13d8fe74d

+ 1 - 0
clish.xsd

@@ -233,6 +233,7 @@
             <xs:element ref="ACTION" minOccurs="0"/>
         </xs:sequence>
         <xs:attributeGroup ref="menu_item_g"/>
+        <xs:attribute name="ref" type="xs:string" use="optional"/>
         <xs:attribute name="view" type="xs:string" use="optional"/>
         <xs:attribute name="viewid" type="xs:string" use="optional"/>
         <xs:attribute name="access" type="xs:string" use="optional"/>

+ 9 - 2
clish/command.h

@@ -25,9 +25,10 @@ typedef enum {
 /*-----------------
  * meta functions
  *----------------- */
-clish_command_t *clish_command_new(const char *name, const char *text);
+clish_command_t *clish_command_new(const char *name, const char *help);
 clish_command_t *clish_command_new_link(const char *name,
-	const clish_command_t * ref);
+	const char *help, const clish_command_t * ref);
+clish_command_t *clish_command_new_link_from_alias(const clish_command_t * alias);
 int clish_command_bt_compare(const void *clientnode, const void *clientkey);
 void clish_command_bt_getkey(const void *clientnode, lub_bintree_key_t * key);
 size_t clish_command_bt_offset(void);
@@ -111,4 +112,10 @@ void clish_command__set_lock(clish_command_t * instance, bool_t lock);
 const char * clish_command__get_shebang(const clish_command_t * instance);
 void clish_command__set_shebang(clish_command_t * instance, const char * shebang);
 
+void clish_command__set_alias(clish_command_t * instance, const char * alias);
+const char * clish_command__get_alias(const clish_command_t * instance);
+void clish_command__set_alias_view(clish_command_t * instance,
+	clish_view_t * alias_view);
+clish_view_t * clish_command__get_alias_view(const clish_command_t * instance);
+
 #endif				/* _clish_command_h */

+ 54 - 5
clish/command/command.c

@@ -28,6 +28,8 @@ clish_command_init(clish_command_t * this, const char *name, const char *text)
 
 	/* set up defaults */
 	this->link = NULL;
+	this->alias = NULL;
+	this->alias_view = NULL;
 	this->paramv = clish_paramv_new();
 	this->viewid = NULL;
 	this->view = NULL;
@@ -58,6 +60,8 @@ static void clish_command_fini(clish_command_t * this)
 {
 	lub_string_free(this->name);
 	this->name = NULL;
+	lub_string_free(this->text);
+	this->text = NULL;
 
 	/* Link need not full cleanup */
 	if (this->link)
@@ -66,12 +70,12 @@ static void clish_command_fini(clish_command_t * this)
 	/* finalize each of the parameter instances */
 	clish_paramv_delete(this->paramv);
 
+	lub_string_free(this->alias);
+	this->alias = NULL;
 	lub_string_free(this->viewid);
 	this->viewid = NULL;
 	lub_string_free(this->action);
 	this->action = NULL;
-	lub_string_free(this->text);
-	this->text = NULL;
 	lub_string_free(this->detail);
 	this->detail = NULL;
 	lub_string_free(this->builtin);
@@ -124,19 +128,19 @@ void clish_command_bt_getkey(const void *clientnode, lub_bintree_key_t * key)
 }
 
 /*--------------------------------------------------------- */
-clish_command_t *clish_command_new(const char *name, const char *text)
+clish_command_t *clish_command_new(const char *name, const char *help)
 {
 	clish_command_t *this = malloc(sizeof(clish_command_t));
 
 	if (this) {
-		clish_command_init(this, name, text);
+		clish_command_init(this, name, help);
 	}
 	return this;
 }
 
 /*--------------------------------------------------------- */
 clish_command_t *clish_command_new_link(const char *name,
-	const clish_command_t * ref)
+	const char *help, const clish_command_t * ref)
 {
 	if (!ref)
 		return NULL;
@@ -148,6 +152,8 @@ clish_command_t *clish_command_new_link(const char *name,
 	*this = *ref;
 	/* Initialise the name (other than original name) */
 	this->name = lub_string_dup(name);
+	/* Initialise the name (other than original name) */
+	this->text = lub_string_dup(help);
 	/* Be a good binary tree citizen */
 	lub_bintree_node_init(&this->bt_node);
 	/* It a link to command so set the link flag */
@@ -156,6 +162,21 @@ clish_command_t *clish_command_new_link(const char *name,
 	return this;
 }
 
+/*--------------------------------------------------------- */
+clish_command_t *clish_command_new_link_from_alias(const clish_command_t * alias)
+{
+	clish_command_t * ref;
+
+	if (!alias->alias)
+		return NULL;
+	assert(alias->alias_view);
+	ref = clish_view_find_command(alias->alias_view, alias->alias, BOOL_FALSE);
+	if (!ref)
+		return NULL;
+
+	return clish_command_new_link(alias->name, alias->text, ref);
+}
+
 /*---------------------------------------------------------
  * PUBLIC METHODS
  *--------------------------------------------------------- */
@@ -634,3 +655,31 @@ void clish_command__set_shebang(clish_command_t * this, const char * shebang)
 		prog += strlen(prefix);
 	this->shebang = lub_string_dup(prog);
 }
+
+/*--------------------------------------------------------- */
+void clish_command__set_alias(clish_command_t * this, const char * alias)
+{
+	assert(NULL == this->alias);
+	this->alias = lub_string_dup(alias);
+}
+
+/*--------------------------------------------------------- */
+const char * clish_command__get_alias(const clish_command_t * this)
+{
+	return this->alias;
+}
+
+/*--------------------------------------------------------- */
+void clish_command__set_alias_view(clish_command_t * this,
+	clish_view_t * alias_view)
+{
+	this->alias_view = alias_view;
+}
+
+/*--------------------------------------------------------- */
+clish_view_t * clish_command__get_alias_view(const clish_command_t * this)
+{
+	return this->alias_view;
+}
+
+

+ 3 - 0
clish/command/command_dump.c

@@ -14,6 +14,9 @@ void clish_command_dump(const clish_command_t * this)
 	lub_dump_indent();
 	lub_dump_printf("name        : %s\n", this->name);
 	lub_dump_printf("text        : %s\n", this->text);
+	lub_dump_printf("alias       : %s\n", this->alias);
+	lub_dump_printf("alias_view  : %s\n",
+		this->alias_view ? clish_view__get_name(this->alias_view) : "(null)");
 	lub_dump_printf("action      : %s\n",
 			this->action ? this->action : "(null)");
 	lub_dump_printf("paramc      : %d\n", clish_paramv__get_count(this->paramv));

+ 2 - 0
clish/command/private.h

@@ -18,6 +18,8 @@ struct clish_command_s {
 	char *escape_chars;
 	clish_param_t *args;
 	const struct clish_command_s * link;
+	clish_view_t *alias_view;
+	char *alias;
 	clish_view_t *pview;
 	bool_t lock;
 

+ 4 - 1
clish/nspace/nspace.c

@@ -75,6 +75,7 @@ static clish_command_t *clish_nspace_find_create_command(clish_nspace_t * this,
 {
 	clish_command_t *cmd;
 	char *name = NULL;
+	const char *help = NULL;
 	clish_command_t *tmp = NULL;
 	const char *str = NULL;
 
@@ -83,11 +84,13 @@ static clish_command_t *clish_nspace_find_create_command(clish_nspace_t * this,
 		assert(this->prefix_cmd);
 		name = lub_string_dup(prefix);
 		ref = this->prefix_cmd;
+		help = clish_command__get_text(this->prefix_cmd);
 	} else {
 		lub_string_catn(&name, prefix, strlen(prefix));
 		lub_string_catn(&name, " ", 1);
 		lub_string_catn(&name, clish_command__get_name(ref),
 				strlen(clish_command__get_name(ref)));
+		help = clish_command__get_text(ref);
 	}
 
 	/* The command is cached already */
@@ -95,7 +98,7 @@ static clish_command_t *clish_nspace_find_create_command(clish_nspace_t * this,
 		free(name);
 		return cmd;
 	}
-	cmd = clish_command_new_link(name, ref);
+	cmd = clish_command_new_link(name, help, ref);
 	free(name);
 	assert(cmd);
 

+ 100 - 66
clish/shell/shell_tinyxml_read.cpp

@@ -181,8 +181,21 @@ process_command(clish_shell_t * shell, TiXmlElement * element, void *parent)
 {
 	clish_view_t *v = (clish_view_t *) parent;
 	clish_command_t *cmd = NULL;
-	const char *access = element->Attribute("access");
 	bool allowed = true;
+	clish_command_t *old;
+	char *alias_name = NULL;
+	clish_view_t *alias_view = NULL;
+
+	const char *access = element->Attribute("access");
+	const char *name = element->Attribute("name");
+	const char *help = element->Attribute("help");
+	const char *view = element->Attribute("view");
+	const char *viewid = element->Attribute("viewid");
+	const char *escape_chars = element->Attribute("escape_chars");
+	const char *args_name = element->Attribute("args");
+	const char *args_help = element->Attribute("args_help");
+	const char *lock = element->Attribute("lock");
+	const char *ref = element->Attribute("ref");
 
 	if (NULL != access) {
 		allowed = false;	// err on the side of caution
@@ -194,75 +207,96 @@ process_command(clish_shell_t * shell, TiXmlElement * element, void *parent)
 			    false;
 		}
 	}
+	if (!allowed)
+		return;
 
-	if (allowed) {
-		const char *name = element->Attribute("name");
-		const char *help = element->Attribute("help");
-		const char *view = element->Attribute("view");
-		const char *viewid = element->Attribute("viewid");
-		const char *escape_chars = element->Attribute("escape_chars");
-		const char *args_name = element->Attribute("args");
-		const char *args_help = element->Attribute("args_help");
-		const char *lock = element->Attribute("lock");
-
-		clish_command_t *old = clish_view_find_command(v, name, BOOL_FALSE);
-
-		// check this command doesn't already exist
-		if (NULL != old) {
-			// flag the duplication then ignore further definition
-			printf("DUPLICATE COMMAND: %s\n",
-			       clish_command__get_name(old));
-		} else {
-			assert(name);
-			assert(help);
-			/* create a command */
-			cmd = clish_view_new_command(v, name, help);
-			assert(cmd);
-			clish_command__set_pview(cmd, v);
-			if (NULL != escape_chars) {
-				/* define some specialist escape characters */
-				clish_command__set_escape_chars(cmd,
-								escape_chars);
-			}
-			if (NULL != args_name) {
-				/* define a "rest of line" argument */
-				clish_param_t *param;
-				clish_ptype_t *tmp = NULL;
-
-				assert(NULL != args_help);
-				tmp = clish_shell_find_create_ptype(shell,
-							  "internal_ARGS",
-							  "Arguments", "[^\\]+",
-							  CLISH_PTYPE_REGEXP,
-							  CLISH_PTYPE_NONE);
-				assert(tmp);
-				param =
-				    clish_param_new(args_name, args_help, tmp);
-
-				clish_command__set_args(cmd, param);
-			}
-			// define the view which this command changes to
-			if (NULL != view) {
-				clish_view_t *next =
-				    clish_shell_find_create_view(shell, view,
-								 NULL);
-
-				// reference the next view
-				clish_command__set_view(cmd, next);
-			}
-			// define the view id which this command changes to
-			if (NULL != viewid) {
-				clish_command__set_viewid(cmd, viewid);
-			}
-			/* lock field */
-			if (lock && (lub_string_nocasecmp(lock, "false") == 0))
-				clish_command__set_lock(cmd, BOOL_FALSE);
-			else
-				clish_command__set_lock(cmd, BOOL_TRUE);
+	old = clish_view_find_command(v, name, BOOL_FALSE);
+	// check this command doesn't already exist
+	if (old) {
+		// flag the duplication then ignore further definition
+		printf("DUPLICATE COMMAND: %s\n",
+		       clish_command__get_name(old));
+		return;
+	}
 
-			process_children(shell, element, cmd);
+	assert(name);
+	assert(help);
+
+	/* Reference 'ref' field */
+	if (ref) {
+		char *saveptr;
+		const char *delim = "@";
+		char *view_name = NULL;
+		char *str = lub_string_dup(ref);
+
+		alias_name = strtok_r(str, delim, &saveptr);
+		if (!alias_name) {
+			printf("EMPTY REFERENCE COMMAND: %s\n", name);
+			lub_string_free(str);
+			return;
 		}
+		view_name = strtok_r(NULL, delim, &saveptr);
+		if (!view_name)
+			alias_view = v;
+		else
+			alias_view = clish_shell_find_create_view(shell,
+				view_name, NULL);
+		lub_string_free(str);
+	}
+
+	/* create a command */
+	cmd = clish_view_new_command(v, name, help);
+	assert(cmd);
+	clish_command__set_pview(cmd, v);
+	if (NULL != escape_chars) {
+		/* define some specialist escape characters */
+		clish_command__set_escape_chars(cmd,
+						escape_chars);
+	}
+	if (NULL != args_name) {
+		/* define a "rest of line" argument */
+		clish_param_t *param;
+		clish_ptype_t *tmp = NULL;
+
+		assert(NULL != args_help);
+		tmp = clish_shell_find_create_ptype(shell,
+					  "internal_ARGS",
+					  "Arguments", "[^\\]+",
+					  CLISH_PTYPE_REGEXP,
+					  CLISH_PTYPE_NONE);
+		assert(tmp);
+		param =
+		    clish_param_new(args_name, args_help, tmp);
+
+		clish_command__set_args(cmd, param);
+	}
+	// define the view which this command changes to
+	if (NULL != view) {
+		clish_view_t *next =
+		    clish_shell_find_create_view(shell, view,
+						 NULL);
+
+		// reference the next view
+		clish_command__set_view(cmd, next);
 	}
+	// define the view id which this command changes to
+	if (NULL != viewid) {
+		clish_command__set_viewid(cmd, viewid);
+	}
+	/* lock field */
+	if (lock && (lub_string_nocasecmp(lock, "false") == 0))
+		clish_command__set_lock(cmd, BOOL_FALSE);
+	else
+		clish_command__set_lock(cmd, BOOL_TRUE);
+
+	/* Set alias */
+	if (alias_name) {
+		clish_command__set_alias(cmd, alias_name);
+		assert(alias_view);
+		clish_command__set_alias_view(cmd, alias_view);
+	}
+
+	process_children(shell, element, cmd);
 }
 
 ///////////////////////////////////////

+ 15 - 1
clish/view/view.c

@@ -209,7 +209,7 @@ clish_command_t *clish_view_resolve_command(clish_view_t * this,
 /*--------------------------------------------------------- */
 clish_command_t *clish_view_find_command(clish_view_t * this, const char *name, bool_t inherit)
 {
-	clish_command_t *cmd, *result;
+	clish_command_t *cmd, *link, *result = NULL;
 	clish_nspace_t *nspace;
 	unsigned cnt = clish_view__get_nspace_count(this);
 	int i;
@@ -217,6 +217,20 @@ clish_command_t *clish_view_find_command(clish_view_t * this, const char *name,
 	/* Search the current view */
 	result = lub_bintree_find(&this->tree, name);
 
+	/* Make command link from command alias */
+	if (result && clish_command__get_alias(result)) {
+		link = clish_command_new_link_from_alias(result);
+		/* remove the alias command from the tree */
+		lub_bintree_remove(&this->tree, result);
+		clish_command_delete(result);
+		if (-1 == lub_bintree_insert(&this->tree, link)) {
+			/* inserting a duplicate command is bad */
+			clish_command_delete(link);
+			link = NULL;
+		}
+		result = link;
+	}
+
 	if (!inherit)
 		return result;