Browse Source

klish: Add callback for help. Unfinished

Serj Kalichev 1 year ago
parent
commit
93d94b42a7
1 changed files with 87 additions and 0 deletions
  1. 87 0
      bin/klish/interactive.c

+ 87 - 0
bin/klish/interactive.c

@@ -25,6 +25,7 @@ typedef struct ctx_s {
 
 bool_t cmd_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata);
 bool_t completion_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata);
+bool_t help_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata);
 static bool_t stdin_cb(faux_eloop_t *eloop, faux_eloop_type_e type,
 	void *associated_data, void *user_data);
 
@@ -67,8 +68,10 @@ int klish_interactive_shell(ktp_session_t *ktp, struct options *opts)
 
 	// Don't stop interactive loop on each answer
 	ktp_session_set_stop_on_answer(ktp, BOOL_FALSE);
+
 	ktp_session_set_cb(ktp, KTP_SESSION_CB_CMD_ACK, cmd_ack_cb, &ctx);
 	ktp_session_set_cb(ktp, KTP_SESSION_CB_COMPLETION_ACK, completion_ack_cb, &ctx);
+	ktp_session_set_cb(ktp, KTP_SESSION_CB_HELP_ACK, help_ack_cb, &ctx);
 	eloop = ktp_session_eloop(ktp);
 	faux_eloop_add_fd(eloop, STDIN_FILENO, POLLIN, stdin_cb, &ctx);
 	faux_eloop_loop(eloop);
@@ -295,3 +298,87 @@ bool_t completion_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
 
 	return BOOL_TRUE;
 }
+
+
+bool_t help_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
+{
+	ctx_t *ctx = (ctx_t *)udata;
+	faux_list_node_t *iter = NULL;
+	uint32_t param_len = 0;
+	char *param_data = NULL;
+	uint16_t param_type = 0;
+	char *prefix = NULL;
+	faux_list_t *completions = NULL;
+	size_t completions_num = 0;
+	size_t max_compl_len = 0;
+
+	tinyrl_set_busy(ctx->tinyrl, BOOL_FALSE);
+
+	prefix = faux_msg_get_str_param_by_type(msg, KTP_PARAM_PREFIX);
+
+	completions = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
+		NULL, NULL, (void (*)(void *))faux_str_free);
+
+	iter = faux_msg_init_param_iter(msg);
+	while (faux_msg_get_param_each(&iter, &param_type, (void **)&param_data, &param_len)) {
+		char *compl = NULL;
+		if (KTP_PARAM_LINE != param_type)
+			continue;
+		compl = faux_str_dupn(param_data, param_len);
+		faux_list_add(completions, compl);
+		if (param_len > max_compl_len)
+			max_compl_len = param_len;
+	}
+
+	completions_num = faux_list_len(completions);
+
+	// Single possible completion
+	if (1 == completions_num) {
+		char *compl = (char *)faux_list_data(faux_list_head(completions));
+		tinyrl_line_insert(ctx->tinyrl, compl, strlen(compl));
+		tinyrl_redisplay(ctx->tinyrl);
+
+	// Multi possible completions
+	} else if (completions_num > 1) {
+		faux_list_node_t *eq_iter = NULL;
+		size_t eq_part = 0;
+		char *str = NULL;
+		char *compl = NULL;
+
+		// Try to find equal part for all possible completions
+		eq_iter = faux_list_head(completions);
+		str = (char *)faux_list_data(eq_iter);
+		eq_part = strlen(str);
+		eq_iter = faux_list_next_node(eq_iter);
+
+		while ((compl = (char *)faux_list_each(&eq_iter)) && (eq_part > 0)) {
+			size_t cur_eq = 0;
+			cur_eq = tinyrl_equal_part(ctx->tinyrl, str, compl);
+			if (cur_eq < eq_part)
+				eq_part = cur_eq;
+		}
+
+		// The equal part was found
+		if (eq_part > 0) {
+			tinyrl_line_insert(ctx->tinyrl, str, eq_part);
+			tinyrl_redisplay(ctx->tinyrl);
+
+		// There is no equal part for all completions
+		} else {
+			tinyrl_multi_crlf(ctx->tinyrl);
+			tinyrl_reset_line_state(ctx->tinyrl);
+			display_completions(ctx->tinyrl, completions,
+				prefix, max_compl_len);
+			tinyrl_redisplay(ctx->tinyrl);
+		}
+	}
+
+	faux_list_free(completions);
+	faux_str_free(prefix);
+
+	// Happy compiler
+	ktp = ktp;
+	msg = msg;
+
+	return BOOL_TRUE;
+}