Browse Source

The field 'filter' can has true/false/dual values

Serj Kalichev 6 months ago
parent
commit
2aabd7de65
7 changed files with 70 additions and 21 deletions
  1. 10 1
      klish.xsd
  2. 25 4
      klish/ischeme/ientry.c
  3. 9 2
      klish/kentry.h
  4. 4 4
      klish/kscheme/kentry.c
  5. 3 2
      klish/kscheme/kscheme.c
  6. 7 4
      klish/ksession/ksession_parse.c
  7. 12 4
      klish/xml-helper/load.c

+ 10 - 1
klish.xsd

@@ -269,6 +269,14 @@
 		</xs:restriction>
 	</xs:simpleType>
 
+	<xs:simpleType name="entry_filter_t">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="true"/>
+			<xs:enumeration value="false"/>
+			<xs:enumeration value="dual"/>
+		</xs:restriction>
+	</xs:simpleType>
+
 	<xs:group name="entry_group_t">
 		<xs:choice>
 			<xs:element ref="HOTKEY" minOccurs="0" maxOccurs="unbounded"/>
@@ -304,7 +312,7 @@
 		<xs:attribute name="value" type="xs:string" use="optional"/>
 		<xs:attribute name="restore" type="xs:boolean" use="optional" default="false"/>
 		<xs:attribute name="order" type="xs:boolean" use="optional" default="false"/>
-		<xs:attribute name="filter" type="xs:boolean" use="optional" default="false"/>
+		<xs:attribute name="filter" type="entry_filter_t" use="optional" default="false"/>
 	</xs:complexType>
 
 
@@ -438,6 +446,7 @@
 		<xs:attribute name="ref" type="xs:string" use="optional"/>
 		<xs:attribute name="value" type="xs:string" use="optional"/>
 		<xs:attribute name="restore" type="xs:boolean" use="optional" default="false"/>
+		<xs:attribute name="filter" type="entry_filter_t" use="optional" default="false"/>
 	</xs:complexType>
 
 </xs:schema>

+ 25 - 4
klish/ischeme/ientry.c

@@ -134,9 +134,14 @@ bool_t ientry_parse(const ientry_t *info, kentry_t *entry, faux_error_t *error)
 
 	// Filter
 	if (!faux_str_is_empty(info->filter)) {
-		bool_t b = BOOL_FALSE;
-		if (!faux_conv_str2bool(info->filter, &b) ||
-			!kentry_set_filter(entry, b)) {
+		kentry_filter_e filter = KENTRY_FILTER_NONE;
+		if (!faux_str_casecmp(info->filter, "false"))
+			filter = KENTRY_FILTER_FALSE;
+		else if (!faux_str_casecmp(info->filter, "true"))
+			filter = KENTRY_FILTER_TRUE;
+		else if (!faux_str_casecmp(info->filter, "dual"))
+			filter = KENTRY_FILTER_DUAL;
+		if ((KENTRY_FILTER_NONE == filter) || !kentry_set_filter(entry, filter)) {
 			faux_error_add(error, TAG": Illegal 'filter' attribute");
 			retcode = BOOL_FALSE;
 		}
@@ -299,6 +304,7 @@ char *ientry_deploy(const kentry_t *kentry, int level)
 	char *tmp = NULL;
 	char *mode = NULL;
 	char *purpose = NULL;
+	char *filter = NULL;
 	kentry_entrys_node_t *entrys_iter = NULL;
 	kentry_actions_node_t *actions_iter = NULL;
 	kentry_hotkeys_node_t *hotkeys_iter = NULL;
@@ -374,7 +380,22 @@ char *ientry_deploy(const kentry_t *kentry, int level)
 		attr2ctext(&str, "value", kentry_value(kentry), level + 1);
 		attr2ctext(&str, "restore", faux_conv_bool2str(kentry_restore(kentry)), level + 1);
 		attr2ctext(&str, "order", faux_conv_bool2str(kentry_order(kentry)), level + 1);
-		attr2ctext(&str, "filter", faux_conv_bool2str(kentry_filter(kentry)), level + 1);
+
+		// Filter
+		switch (kentry_filter(kentry)) {
+		case KENTRY_FILTER_FALSE:
+			filter = "false";
+			break;
+		case KENTRY_FILTER_TRUE:
+			filter = "true";
+			break;
+		case KENTRY_FILTER_DUAL:
+			filter = "dual";
+			break;
+		default:
+			filter = NULL;
+		}
+		attr2ctext(&str, "filter", filter, level + 1);
 
 		// ENTRY list
 		entrys_iter = kentry_entrys_iter(kentry);

+ 9 - 2
klish/kentry.h

@@ -36,6 +36,13 @@ typedef enum {
 	KENTRY_PURPOSE_MAX,
 } kentry_purpose_e;
 
+// Filter flag
+typedef enum {
+	KENTRY_FILTER_NONE, // Illegal
+	KENTRY_FILTER_FALSE, // Entry is not a filter
+	KENTRY_FILTER_TRUE, // Entry is a filter
+	KENTRY_FILTER_DUAL, // Entry can be filter or non-filter
+} kentry_filter_e;
 
 // Number of max occurs
 typedef enum {
@@ -89,8 +96,8 @@ bool_t kentry_set_restore(kentry_t *entry, bool_t restore);
 bool_t kentry_order(const kentry_t *entry);
 bool_t kentry_set_order(kentry_t *entry, bool_t order);
 // Filter
-bool_t kentry_filter(const kentry_t *entry);
-bool_t kentry_set_filter(kentry_t *entry, bool_t filter);
+kentry_filter_e kentry_filter(const kentry_t *entry);
+bool_t kentry_set_filter(kentry_t *entry, kentry_filter_e filter);
 // User data
 void *kentry_udata(const kentry_t *entry);
 bool_t kentry_set_udata(kentry_t *entry, void *data, kentry_udata_free_fn udata_free_fn);

+ 4 - 4
klish/kscheme/kentry.c

@@ -27,7 +27,7 @@ struct kentry_s {
 	char *value; // Additional info
 	bool_t restore; // Should entry restore its depth while execution
 	bool_t order; // Is entry ordered
-	bool_t filter; // Is entry filter. Filter can't have inline actions.
+	kentry_filter_e filter; // Is entry filter. Filter can't have inline actions.
 	faux_list_t *entrys; // Nested ENTRYs
 	faux_list_t *actions; // Nested ACTIONs
 	faux_list_t *hotkeys; // Hotkeys
@@ -88,8 +88,8 @@ KGET_BOOL(entry, order);
 KSET_BOOL(entry, order);
 
 // Filter
-KGET_BOOL(entry, filter);
-KSET_BOOL(entry, filter);
+KGET(entry, kentry_filter_e, filter);
+KSET(entry, kentry_filter_e, filter);
 
 // Nested ENTRYs list
 KGET(entry, faux_list_t *, entrys);
@@ -143,7 +143,7 @@ kentry_t *kentry_new(const char *name)
 	entry->value = NULL;
 	entry->restore = BOOL_FALSE;
 	entry->order = BOOL_FALSE;
-	entry->filter = BOOL_FALSE;
+	entry->filter = KENTRY_FILTER_FALSE;
 	entry->udata = NULL;
 	entry->udata_free_fn = NULL;
 

+ 3 - 2
klish/kscheme/kscheme.c

@@ -263,8 +263,9 @@ bool_t kscheme_prepare_action_list(kscheme_t *scheme, kentry_t *entry,
 		}
 		kaction_set_sym(action, sym);
 		kaction_set_plugin(action, plugin);
-		// Filter can't contain sync symbols.
-		if (kentry_filter(entry) && kaction_is_sync(action)) {
+		// Filter can't contain sync symbols
+		if ((kentry_filter(entry) != KENTRY_FILTER_FALSE) &&
+			kaction_is_sync(action)) {
 			faux_error_sprintf(error, "Filter \"%s\" can't contain "
 				"sync symbol \"%s\"",
 				kentry_name(entry), sym_ref);

+ 7 - 4
klish/ksession/ksession_parse.c

@@ -107,6 +107,7 @@ static kpargv_status_e ksession_parse_arg(ksession_t *session,
 	} else if (!kentry_container(entry)) {
 		const char *current_arg = NULL;
 		kparg_t *parg = NULL;
+		kentry_filter_e filter_flag = kentry_filter(entry);
 
 		// When purpose is COMPLETION or HELP then fill completion list.
 		// Additionally if it's last continuable argument then lie to
@@ -116,7 +117,9 @@ static kpargv_status_e ksession_parse_arg(ksession_t *session,
 		// filters or non-filters
 		if (((KPURPOSE_COMPLETION == purpose) ||
 			(KPURPOSE_HELP == purpose)) &&
-			((is_filter == kentry_filter(entry)) ||
+			((filter_flag == KENTRY_FILTER_DUAL) ||
+			(is_filter && (filter_flag == KENTRY_FILTER_TRUE)) ||
+			(!is_filter && (filter_flag == KENTRY_FILTER_FALSE)) ||
 			(is_filter && kpargv_pargs_len(pargv)))) {
 			if (!*argv_iter) {
 				// That's time to add entry to completions list.
@@ -483,8 +486,8 @@ static bool_t ksession_check_line(const kpargv_t *pargv, faux_error_t *error,
 	// First component
 	if (is_first) {
 
-		// First component can't be filter
-		if (kentry_filter(cmd)) {
+		// First component can't be a filter
+		if (kentry_filter(cmd) == KENTRY_FILTER_TRUE) {
 			faux_error_sprintf(error, "The filter \"%s\" "
 				"can't be used without previous pipeline",
 				kentry_name(cmd));
@@ -503,7 +506,7 @@ static bool_t ksession_check_line(const kpargv_t *pargv, faux_error_t *error,
 	} else {
 
 		// Only the first component can be non-filter
-		if (!kentry_filter(cmd)) {
+		if (kentry_filter(cmd) == KENTRY_FILTER_FALSE) {
 			faux_error_sprintf(error, "The non-filter command \"%s\" "
 				"can't be destination of pipe",
 				kentry_name(cmd));

+ 12 - 4
klish/xml-helper/load.c

@@ -798,6 +798,7 @@ static bool_t process_command(const kxml_node_t *element, void *parent,
 	bool_t res = BOOL_FALSE;
 	ktags_e tag = kxml_node_tag(element);
 	bool_t is_name = BOOL_FALSE;
+	bool_t is_filter = BOOL_FALSE;
 	kentry_entrys_node_t *iter = NULL;
 	kentry_t *nested_entry = NULL;
 	bool_t ptype_exists = BOOL_FALSE;
@@ -862,10 +863,15 @@ static bool_t process_command(const kxml_node_t *element, void *parent,
 	}
 	ientry.order = "false";
 	// Filter
-	if (KTAG_FILTER == tag)
-		ientry.filter = "true";
-	else
-		ientry.filter = "false";
+	ientry.filter = kxml_node_attr(element, "filter");
+	if (ientry.filter) {
+		is_filter = BOOL_TRUE;
+	} else {
+		if (KTAG_FILTER == tag)
+			ientry.filter = "true";
+		else
+			ientry.filter = "false";
+	}
 
 	if (!(entry = add_entry_to_hierarchy(element, parent, &ientry, error)))
 		goto err;
@@ -907,6 +913,8 @@ err:
 		kxml_node_attr_free(ientry.value);
 		kxml_node_attr_free(ientry.restore);
 	}
+	if (is_filter)
+		kxml_node_attr_free(ientry.filter);
 
 	return res;
 }