Browse Source

kentry: Add field 'purpose'

Serj Kalichev 2 years ago
parent
commit
f5266e6c07
6 changed files with 75 additions and 0 deletions
  1. 10 0
      klish.xsd
  2. 1 0
      klish/ientry.h
  3. 37 0
      klish/ischeme/ientry.c
  4. 13 0
      klish/kentry.h
  5. 7 0
      klish/kscheme/kentry.c
  6. 7 0
      klish/xml-helper/load.c

+ 10 - 0
klish.xsd

@@ -152,6 +152,15 @@
 		</xs:restriction>
 	</xs:simpleType>
 
+	<xs:simpleType name="entry_purpose_t">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="common"/>
+			<xs:enumeration value="prompt"/>
+			<xs:enumeration value="cond"/>
+			<xs:enumeration value="completion"/>
+		</xs:restriction>
+	</xs:simpleType>
+
 	<xs:group name="entry_group_t">
 		<xs:choice>
 			<xs:element ref="ENTRY" minOccurs="0" maxOccurs="unbounded"/>
@@ -168,6 +177,7 @@
 		<xs:attribute name="help" type="xs:string" use="optional"/>
 		<xs:attribute name="container" type="xs:boolean" use="optional" default="false"/>
 		<xs:attribute name="mode" type="param_mode_t" use="optional" default="switch"/>
+		<xs:attribute name="purpose" type="param_purpose_t" use="optional" default="common"/>
 		<xs:attribute name="min" type="xs:string" use="optional" default="1"/>
 		<xs:attribute name="max" type="xs:string" use="optional" default="1"/>
 		<xs:attribute name="ptype" type="xs:string" use="optional"/>

+ 1 - 0
klish/ientry.h

@@ -17,6 +17,7 @@ struct ientry_s {
 	char *help;
 	char *container;
 	char *mode;
+	char *purpose;
 	char *min;
 	char *max;
 	char *ptype;

+ 37 - 0
klish/ischeme/ientry.c

@@ -55,6 +55,23 @@ bool_t ientry_parse(const ientry_t *info, kentry_t *entry, faux_error_t *error)
 		}
 	}
 
+	// Purpose
+	if (!faux_str_is_empty(info->purpose)) {
+		kentry_purpose_e purpose = KENTRY_PURPOSE_NONE;
+		if (!faux_str_casecmp(info->purpose, "common"))
+			purpose = KENTRY_PURPOSE_COMMON;
+		else if (!faux_str_casecmp(info->purpose, "prompt"))
+			purpose = KENTRY_PURPOSE_PROMPT;
+		else if (!faux_str_casecmp(info->purpose, "cond"))
+			purpose = KENTRY_PURPOSE_COND;
+		else if (!faux_str_casecmp(info->purpose, "completion"))
+			purpose = KENTRY_PURPOSE_COMPLETION;
+		if ((KENTRY_PURPOSE_NONE == purpose) || !kentry_set_purpose(entry, purpose)) {
+			faux_error_add(error, TAG": Illegal 'purpose' attribute");
+			retcode = BOOL_FALSE;
+		}
+	}
+
 	// Min occurs
 	if (!faux_str_is_empty(info->min)) {
 		unsigned int i = 0;
@@ -262,6 +279,7 @@ char *ientry_deploy(const kentry_t *kentry, int level)
 	char *str = NULL;
 	char *tmp = NULL;
 	char *mode = NULL;
+	char *purpose = NULL;
 	kentry_entrys_node_t *entrys_iter = NULL;
 	kentry_actions_node_t *actions_iter = NULL;
 	char *num = NULL;
@@ -296,6 +314,25 @@ char *ientry_deploy(const kentry_t *kentry, int level)
 		}
 		attr2ctext(&str, "mode", mode, level + 1);
 
+		// Purpose
+		switch (kentry_purpose(kentry)) {
+		case KENTRY_PURPOSE_COMMON:
+			purpose = "common";
+			break;
+		case KENTRY_PURPOSE_PROMPT:
+			purpose = "prompt";
+			break;
+		case KENTRY_PURPOSE_COND:
+			purpose = "cond";
+			break;
+		case KENTRY_PURPOSE_COMPLETION:
+			purpose = "completion";
+			break;
+		default:
+			purpose = NULL;
+		}
+		attr2ctext(&str, "purpose", purpose, level + 1);
+
 		// Min occurs
 		num = faux_str_sprintf("%u", kentry_min(kentry));
 		attr2ctext(&str, "min", num, level + 1);

+ 13 - 0
klish/kentry.h

@@ -22,6 +22,16 @@ typedef enum {
 	KENTRY_MODE_EMPTY, // Entry must not have a nested entrys
 } kentry_mode_e;
 
+// Purpose of ENTRY
+typedef enum {
+	KENTRY_PURPOSE_NONE,
+	KENTRY_PURPOSE_COMMON, // Common entry like view/command/param
+	KENTRY_PURPOSE_PROMPT, // Prompt for view
+	KENTRY_PURPOSE_COND, // Conditional expression
+	KENTRY_PURPOSE_COMPLETION, // Engine to generate completions
+	KENTRY_PURPOSE_MAX,
+} kentry_purpose_e;
+
 
 // Number of max occurs
 typedef enum {
@@ -50,6 +60,9 @@ bool_t kentry_set_container(kentry_t *entry, bool_t container);
 // Mode
 kentry_mode_e kentry_mode(const kentry_t *entry);
 bool_t kentry_set_mode(kentry_t *entry, kentry_mode_e mode);
+// Purpose
+kentry_purpose_e kentry_purpose(const kentry_t *entry);
+bool_t kentry_set_purpose(kentry_t *entry, kentry_purpose_e purpose);
 // Min occurs
 size_t kentry_min(const kentry_t *entry);
 bool_t kentry_set_min(kentry_t *entry, size_t min);

+ 7 - 0
klish/kscheme/kentry.c

@@ -17,6 +17,7 @@ struct kentry_s {
 	kentry_t *parent; // Parent kentry_t element
 	bool_t container; // Is entry container (element with hidden path)
 	kentry_mode_e mode; // Mode of nested ENTRYs list
+	kentry_purpose_e purpose; // Special purpose of ENTRY
 	size_t min; // Min occurs of entry
 	size_t max; // Max occurs of entry
 	char *ptype_str; // Text reference to PTYPE
@@ -52,6 +53,10 @@ KSET_BOOL(entry, container);
 KGET(entry, kentry_mode_e, mode);
 KSET(entry, kentry_mode_e, mode);
 
+// Purpose
+KGET(entry, kentry_purpose_e, purpose);
+KSET(entry, kentry_purpose_e, purpose);
+
 // Min occurs
 KGET(entry, size_t, min);
 KSET(entry, size_t, min);
@@ -124,6 +129,7 @@ kentry_t *kentry_new(const char *name)
 	entry->parent = NULL;
 	entry->container = BOOL_FALSE;
 	entry->mode = KENTRY_MODE_SEQUENCE;
+	entry->purpose = KENTRY_PURPOSE_COMMON;
 	entry->min = 1;
 	entry->max = 1;
 	entry->ptype_str = NULL;
@@ -209,6 +215,7 @@ bool_t kentry_link(kentry_t *dst, const kentry_t *src)
 	// parent - orig
 	// container - orig
 	dst->mode = src->mode;
+	// purpose - orig
 	// min - orig
 	// max - orig
 	dst->ptype_str = src->ptype_str;

+ 7 - 0
klish/xml-helper/load.c

@@ -324,6 +324,7 @@ static bool_t process_view(const kxml_node_t *element, void *parent,
 	ientry.help = kxml_node_attr(element, "help");
 	ientry.container = "true";
 	ientry.mode = "switch";
+	ientry.purpose = "common";
 	ientry.min = "1";
 	ientry.max = "1";
 	ientry.ptype = NULL;
@@ -395,6 +396,7 @@ static bool_t process_ptype(const kxml_node_t *element, void *parent,
 	ientry.help = kxml_node_attr(element, "help");
 	ientry.container = "true";
 	ientry.mode = "sequence";
+	ientry.purpose = "common";
 	ientry.min = "1";
 	ientry.max = "1";
 	ientry.ptype = NULL;
@@ -508,6 +510,7 @@ static bool_t process_param(const kxml_node_t *element, void *parent,
 	ientry.help = kxml_node_attr(element, "help");
 	ientry.container = kxml_node_attr(element, "container");
 	ientry.mode = kxml_node_attr(element, "mode");
+	ientry.purpose = "common";
 	ientry.min = kxml_node_attr(element, "min");
 	ientry.max = kxml_node_attr(element, "max");
 	ientry.ptype = kxml_node_attr(element, "ptype");
@@ -592,6 +595,7 @@ static bool_t process_command(const kxml_node_t *element, void *parent,
 	ientry.help = kxml_node_attr(element, "help");
 	ientry.container = "false";
 	ientry.mode = "switch";
+	ientry.purpose = "common";
 	ientry.min = "1";
 	ientry.max = "1";
 	ientry.ptype = kxml_node_attr(element, "ptype");
@@ -720,6 +724,7 @@ static bool_t process_nspace(const kxml_node_t *element, void *parent,
 	ientry.help = kxml_node_attr(element, "help");
 	ientry.container = kxml_node_attr(element, "container");
 	ientry.mode = kxml_node_attr(element, "mode");;
+	ientry.purpose = kxml_node_attr(element, "common");;
 	ientry.min = kxml_node_attr(element, "min");
 	ientry.max = kxml_node_attr(element, "max");
 	ientry.ptype = kxml_node_attr(element, "ptype");
@@ -792,6 +797,7 @@ static bool_t process_entry(const kxml_node_t *element, void *parent,
 	ientry.help = kxml_node_attr(element, "help");
 	ientry.container = kxml_node_attr(element, "container");
 	ientry.mode = kxml_node_attr(element, "mode");
+	ientry.purpose = kxml_node_attr(element, "purpose");
 	ientry.min = kxml_node_attr(element, "min");
 	ientry.max = kxml_node_attr(element, "max");
 	ientry.ptype = kxml_node_attr(element, "ptype");
@@ -863,6 +869,7 @@ err:
 	kxml_node_attr_free(ientry.help);
 	kxml_node_attr_free(ientry.container);
 	kxml_node_attr_free(ientry.mode);
+	kxml_node_attr_free(ientry.purpose);
 	kxml_node_attr_free(ientry.min);
 	kxml_node_attr_free(ientry.max);
 	kxml_node_attr_free(ientry.ptype);