forked from CESNET/libyang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompletion.c
138 lines (120 loc) · 3.8 KB
/
completion.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
* @file completion.c
* @author Michal Vasko <[email protected]>
* @brief libyang's yanglint tool auto completion
*
* Copyright (c) 2015 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include "commands.h"
#include "../../linenoise/linenoise.h"
#include "libyang.h"
extern struct ly_ctx *ctx;
static void
get_cmd_completion(const char *hint, char ***matches, unsigned int *match_count)
{
int i;
void *p;
*match_count = 0;
*matches = NULL;
for (i = 0; commands[i].name; i++) {
if (!strncmp(hint, commands[i].name, strlen(hint))) {
++(*match_count);
p = realloc(*matches, *match_count * sizeof **matches);
if (!p) {
fprintf(stderr, "Memory allocation failed (%s:%d, %s)", __FILE__, __LINE__, strerror(errno));
return;
}
*matches = p;
(*matches)[*match_count-1] = strdup(commands[i].name);
}
}
}
static int
last_is_opt(const char *hint)
{
const char *ptr;
/* last is option */
if (hint[0] == '-') {
return 1;
}
do {
--hint;
} while (hint[0] == ' ');
/* last is option argument */
ptr = strrchr(hint, ' ');
if (ptr) {
++ptr;
if (ptr[0] == '-') {
return 1;
}
}
return 0;
}
static void
get_model_completion(const char *hint, char ***matches, unsigned int *match_count)
{
int i;
uint32_t idx = 0;
const struct lys_module *module;
void *p;
*match_count = 0;
*matches = NULL;
while ((module = ly_ctx_get_module_iter(ctx, &idx))) {
if (!strncmp(hint, module->name, strlen(hint))) {
++(*match_count);
p = realloc(*matches, *match_count * sizeof **matches);
if (!p) {
fprintf(stderr, "Memory allocation failed (%s:%d, %s)", __FILE__, __LINE__, strerror(errno));
return;
}
*matches = p;
(*matches)[*match_count-1] = strdup(module->name);
}
for (i = 0; i < module->inc_size; ++i) {
if (!strncmp(hint, module->inc[i].submodule->name, strlen(hint))) {
++(*match_count);
p = realloc(*matches, *match_count * sizeof **matches);
if (!p) {
fprintf(stderr, "Memory allocation failed (%s:%d, %s)", __FILE__, __LINE__, strerror(errno));
return;
}
*matches = p;
(*matches)[*match_count-1] = strdup(module->inc[i].submodule->name);
}
}
}
}
void
complete_cmd(const char *buf, const char *hint, linenoiseCompletions *lc)
{
char **matches = NULL;
unsigned int match_count = 0, i;
if (!strncmp(buf, "add ", 4)) {
linenoisePathCompletion(buf, hint, lc);
} else if ((!strncmp(buf, "searchpath ", 11) || !strncmp(buf, "data ", 5)
|| !strncmp(buf, "config ", 7) || !strncmp(buf, "filter ", 7)
|| !strncmp(buf, "xpath ", 6) || !strncmp(buf, "clear ", 6)) && !last_is_opt(hint)) {
linenoisePathCompletion(buf, hint, lc);
} else if ((!strncmp(buf, "print ", 6) || !strncmp(buf, "feature ", 8)) && !last_is_opt(hint)) {
get_model_completion(hint, &matches, &match_count);
} else if (!strchr(buf, ' ') && hint[0]) {
get_cmd_completion(hint, &matches, &match_count);
}
for (i = 0; i < match_count; ++i) {
linenoiseAddCompletion(lc, matches[i]);
free(matches[i]);
}
free(matches);
}