Browse Source

Fix help/completion due to existing entries

Serj Kalichev 2 months ago
parent
commit
61da62ebc3
2 changed files with 115 additions and 66 deletions
  1. 1 1
      src/klish_plugin_sysrepo.h
  2. 114 65
      src/pline.c

+ 1 - 1
src/klish_plugin_sysrepo.h

@@ -214,7 +214,7 @@ pexpr_t *pline_current_expr(pline_t *pline);
 
 void pline_free(pline_t *pline);
 
-void pline_debug(pline_t *pline);
+void pline_debug(const pline_t *pline);
 void pline_print_completions(const pline_t *pline, bool_t help,
 	pt_e enabled_types, bool_t existing_nodes_only);
 

+ 114 - 65
src/pline.c

@@ -337,7 +337,7 @@ static const char *pat2str(pat_e pat)
 }
 
 
-void pline_debug(pline_t *pline)
+void pline_debug(const pline_t *pline)
 {
 	faux_list_node_t *iter = NULL;
 	pexpr_t *pexpr = NULL;
@@ -1304,6 +1304,29 @@ static void pline_print_type_help(const struct lysc_node *node,
 }
 
 
+static bool_t pline_node_exists(sr_session_ctx_t* sess, const char *xpath)
+{
+	sr_val_t *vals = NULL;
+	size_t val_num = 0;
+	bool_t found = BOOL_FALSE;
+	size_t i = 0;
+
+	if (!xpath)
+		return BOOL_FALSE;
+	sr_get_items(sess, xpath, 0, 0, &vals, &val_num);
+	for (i = 0; i < val_num; i++) {
+		// Engine can find defaults for entries but not entries themself
+		if (!vals[i].dflt) {
+			found = BOOL_TRUE;
+			break;
+		}
+	}
+	sr_free_values(vals, val_num);
+
+	return found;
+}
+
+
 void pline_print_completions(const pline_t *pline, bool_t help,
 	pt_e enabled_types, bool_t existing_nodes_only)
 {
@@ -1319,80 +1342,106 @@ void pline_print_completions(const pline_t *pline, bool_t help,
 		if (!(pcompl->pat & enabled_types))
 			continue;
 
-		if (pcompl->xpath && !help) {
-			sr_val_t *vals = NULL;
-			size_t val_num = 0;
-			size_t i = 0;
+		// Switch to necessary DS
+		if (pcompl->xpath && (current_ds != pcompl->xpath_ds)) {
+			sr_session_switch_ds(pline->sess, pcompl->xpath_ds);
+			current_ds = pcompl->xpath_ds;
+		}
+
+		// Help
+		if (help) {
 
-			// Switch to necessary DS
-			if (current_ds != pcompl->xpath_ds) {
-				sr_session_switch_ds(pline->sess, pcompl->xpath_ds);
-				current_ds = pcompl->xpath_ds;
+			// Note we can't show help without valid node
+			if (!node)
+				continue;
+
+			// Type (help)
+			if (pcompl->type == PCOMPL_TYPE) {
+				if (node->nodetype & LYS_LEAF)
+					type = ((struct lysc_node_leaf *)node)->type;
+				else if (node->nodetype & LYS_LEAFLIST)
+					type = ((struct lysc_node_leaflist *)node)->type;
+				else
+					continue;
+				pline_print_type_help(node, type);
+				continue;
 			}
 
-			if (PCOMPL_TYPE == pcompl->type) {
-				sr_get_items(pline->sess, pcompl->xpath,
-					0, 0, &vals, &val_num);
-				for (i = 0; i < val_num; i++) {
-					char *tmp = sr_val_to_str(&vals[i]);
-					char *esc_tmp = NULL;
-					if (!tmp)
-						continue;
-					esc_tmp = faux_str_c_esc_space(tmp);
-					free(tmp);
-					printf("%s\n", esc_tmp);
-					free(esc_tmp);
-				}
-				sr_free_values(vals, val_num);
-			} else if (existing_nodes_only) {
-				bool_t dflt = BOOL_TRUE;
-				sr_get_items(pline->sess, pcompl->xpath,
-					0, 0, &vals, &val_num);
-				for (i = 0; i < val_num; i++) {
-					if (!vals[i].dflt) {
-						dflt = BOOL_FALSE;
-						break;
+			// Check node for existing if necessary
+			if (existing_nodes_only &&
+				!pline_node_exists(pline->sess, pcompl->xpath)) {
+					continue;
+			}
+
+			// Node (help)
+			if (!node->dsc) {
+				printf("%s\n%s\n", node->name, node->name);
+			} else {
+				char *dsc = faux_str_getline(node->dsc,
+					NULL);
+				printf("%s\n%s\n", node->name, dsc);
+				faux_str_free(dsc);
+			}
+
+		// Completion
+		} else {
+
+			// Type (completion)
+			if (pcompl->type == PCOMPL_TYPE) {
+
+				// Existing entries
+				if (pcompl->xpath) {
+					size_t i = 0;
+					sr_val_t *vals = NULL;
+					size_t val_num = 0;
+
+					sr_get_items(pline->sess, pcompl->xpath,
+						0, 0, &vals, &val_num);
+					for (i = 0; i < val_num; i++) {
+						char *tmp = sr_val_to_str(&vals[i]);
+						char *esc_tmp = NULL;
+						if (!tmp)
+							continue;
+						esc_tmp = faux_str_c_esc_space(tmp);
+						free(tmp);
+						printf("%s\n", esc_tmp);
+						free(esc_tmp);
 					}
+					sr_free_values(vals, val_num);
+					continue;
 				}
-				if (!dflt)
-					printf("%s\n", node->name);
-				sr_free_values(vals, val_num);
+
+				if (!node)
+					continue;
+				if (existing_nodes_only)
+					continue;
+
+				// All entries
+				if (node->nodetype & LYS_LEAF)
+					type = ((struct lysc_node_leaf *)node)->type;
+				else if (node->nodetype & LYS_LEAFLIST)
+					type = ((struct lysc_node_leaflist *)node)->type;
+				else
+					continue;
+				pline_print_type_completions(type);
+				continue;
 			}
-		}
 
-		if (!node)
-			continue;
-		if (existing_nodes_only)
-			continue;
+			// Node (completion)
+			if (!node)
+				continue;
 
-		// Node
-		if (PCOMPL_NODE == pcompl->type) {
-			printf("%s\n", node->name);
-			if (help) {
-				if (!node->dsc) {
-					printf("%s\n", node->name);
-				} else {
-					char *dsc = faux_str_getline(node->dsc,
-						NULL);
-					printf("%s\n", dsc);
-					faux_str_free(dsc);
-				}
+			// Existing entries
+			if (existing_nodes_only &&
+				!pline_node_exists(pline->sess, pcompl->xpath)) {
+					continue;
 			}
-			continue;
-		}
 
-		// Type
-		if (node->nodetype & LYS_LEAF)
-			type = ((struct lysc_node_leaf *)node)->type;
-		else if (node->nodetype & LYS_LEAFLIST)
-			type = ((struct lysc_node_leaflist *)node)->type;
-		else
-			continue;
-		if (help)
-			pline_print_type_help(node, type);
-		else
-			pline_print_type_completions(type);
-	}
+			printf("%s\n", node->name);
+
+		} // Completion
+
+	} // while
 
 	// Restore default DS
 	if (current_ds != SRP_REPO_EDIT)