forked from vanessa-opensource/ovm
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathКомандаCompletions.os
More file actions
240 lines (181 loc) · 11.6 KB
/
Copy pathКомандаCompletions.os
File metadata and controls
240 lines (181 loc) · 11.6 KB
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#Использовать annotations
&ЛогOVM
Перем Лог;
&Пластилин(Тип = "ТаблицаЗначений", Значение = "КомандаПриложения")
Перем КомандыПриложения;
Перем Рефлектор;
&Опция(Имя = "shell s", Описание = "Тип оболочки для генерации автодополнения (поддерживается: bash)")
&ТСтрока
&ПоУмолчанию("bash")
&ВОкружении("OVM_COMPLETIONS_SHELL")
Перем ТипОболочки;
&КомандаПриложения(Имя = "completions", Описание = "Вывести скрипт автодополнения команд для выбранной оболочки")
Процедура ПриСозданииОбъекта()
Рефлектор = Новый Рефлектор();
КонецПроцедуры
&ВыполнениеКоманды
Процедура ВыполнениеКоманды() Экспорт
Если НРег(ТипОболочки) = "bash" Тогда
Лог.Информация(СкриптАвтодополненияBash());
Иначе
ВызватьИсключение СтрШаблон("Оболочка ""%1"" не поддерживается. Поддерживаемые оболочки: bash", ТипОболочки);
КонецЕсли;
КонецПроцедуры
Функция СкриптАвтодополненияBash()
ДеревоКоманд = ПолучитьДеревоКоманд();
МассивИменВсехКоманд = Новый Массив();
СтрокиCase = Новый Массив();
Для Каждого ОписаниеКоманды Из ДеревоКоманд Цикл
Для Каждого ИмяКоманды Из ОписаниеКоманды.Имена Цикл
МассивИменВсехКоманд.Добавить(ИмяКоманды);
КонецЦикла;
ПаттернCase = СтрСоединить(ОписаниеКоманды.Имена, "|");
Если ОписаниеКоманды.Подкоманды.Количество() > 0 Тогда
МассивИменПодкоманд = Новый Массив();
МассивПодкомандCase = Новый Массив();
Для Каждого ОписаниеПодкоманды Из ОписаниеКоманды.Подкоманды Цикл
Для Каждого ИмяПодкоманды Из ОписаниеПодкоманды.Имена Цикл
МассивИменПодкоманд.Добавить(ИмяПодкоманды);
КонецЦикла;
ПаттернПодкомандCase = СтрСоединить(ОписаниеПодкоманды.Имена, "|");
СтрокаОпцийПодкоманды = СтрСоединить(ОписаниеПодкоманды.Опции, " ");
МассивПодкомандCase.Добавить(" " + ПаттернПодкомандCase + ")");
МассивПодкомандCase.Добавить(" COMPREPLY=($(compgen -W """ + СтрокаОпцийПодкоманды + """ -- ""$cur""))");
МассивПодкомандCase.Добавить(" ;;");
КонецЦикла;
ИменаПодкоманд = СтрСоединить(МассивИменПодкоманд, " ");
СтрокаОпцийРодителя = СтрСоединить(ОписаниеКоманды.Опции, " ");
ТелоПодкомандCase = СтрСоединить(МассивПодкомандCase, Символы.ПС);
СтрокиCase.Добавить(" " + ПаттернCase + ")");
СтрокиCase.Добавить(" if [ $cword -eq 2 ]; then");
СтрокиCase.Добавить(" COMPREPLY=($(compgen -W """ + ИменаПодкоманд + " " + СтрокаОпцийРодителя + """ -- ""$cur""))");
СтрокиCase.Добавить(" else");
СтрокиCase.Добавить(" local subcommand=""${words[2]}""");
СтрокиCase.Добавить(" case ""$subcommand"" in");
СтрокиCase.Добавить(ТелоПодкомандCase);
СтрокиCase.Добавить(" esac");
СтрокиCase.Добавить(" fi");
СтрокиCase.Добавить(" ;;");
Иначе
СтрокаОпций = СтрСоединить(ОписаниеКоманды.Опции, " ");
СтрокиCase.Добавить(" " + ПаттернCase + ")");
СтрокиCase.Добавить(" COMPREPLY=($(compgen -W """ + СтрокаОпций + """ -- ""$cur""))");
СтрокиCase.Добавить(" ;;");
КонецЕсли;
КонецЦикла;
ВсеКоманды = СтрСоединить(МассивИменВсехКоманд, " ");
ТелоCase = СтрСоединить(СтрокиCase, Символы.ПС);
Скрипт =
"# ovm bash completions
# Добавьте строку ниже в ~/.bashrc для активации автодополнения:
# source <(ovm completions --shell bash)
_ovm_completions() {
local cur prev words cword
_init_completion 2>/dev/null || {
COMPREPLY=()
cur=""${COMP_WORDS[COMP_CWORD]}""
prev=""${COMP_WORDS[COMP_CWORD-1]}""
words=(""${COMP_WORDS[@]}"")
cword=$COMP_CWORD
}
local commands=""" + ВсеКоманды + """
if [ $cword -eq 1 ]; then
COMPREPLY=($(compgen -W ""$commands"" -- ""$cur""))
return 0
fi
local command=""${words[1]}""
case ""$command"" in
" + ТелоCase + "
*)
;;
esac
return 0
}
complete -F _ovm_completions ovm";
Возврат Скрипт;
КонецФункции
Функция ПолучитьДеревоКоманд()
// Первый проход: собрать все команды с их именами желудей и родителями
ВсеИнфо = Новый Соответствие();
Для Каждого ДанныеЖелудя Из КомандыПриложения Цикл
ИмяЖелудя = ДанныеЖелудя.Имя;
ОпределениеЖелудя = ДанныеЖелудя.ОпределениеЖелудя;
Желудь = ДанныеЖелудя.Желудь;
Конструктор = ОпределениеЖелудя.Завязь().ДанныеМетода();
АннотацияКоманды = РаботаСАннотациями.НайтиАннотацию(Конструктор.Аннотации, "КомандаПриложения");
Если АннотацияКоманды = Неопределено Тогда
Продолжить;
КонецЕсли;
ИмяКоманды = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияКоманды, "Имя");
Если НЕ ЗначениеЗаполнено(ИмяКоманды) Тогда
Продолжить;
КонецЕсли;
Родитель = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияКоманды, "Родитель", "");
ИнфоКоманды = Новый Структура("ИмяЖелудя, Родитель, Имена, Опции");
ИнфоКоманды.ИмяЖелудя = ИмяЖелудя;
ИнфоКоманды.Родитель = Родитель;
ИнфоКоманды.Имена = СтрРазделить(ИмяКоманды, " ");
ИнфоКоманды.Опции = ПолучитьОпцииКоманды(Желудь, ОпределениеЖелудя);
ВсеИнфо.Вставить(ИмяЖелудя, ИнфоКоманды);
КонецЦикла;
// Второй проход: собрать дерево — верхнеуровневые команды со своими подкомандами
Результат = Новый Массив();
Для Каждого КлючЗначение Из ВсеИнфо Цикл
ИнфоКоманды = КлючЗначение.Значение;
Если ЗначениеЗаполнено(ИнфоКоманды.Родитель) Тогда
Продолжить;
КонецЕсли;
Подкоманды = НайтиПодкоманды(ИнфоКоманды.ИмяЖелудя, ВсеИнфо);
ОписаниеКоманды = Новый Структура("Имена, Опции, Подкоманды");
ОписаниеКоманды.Имена = ИнфоКоманды.Имена;
ОписаниеКоманды.Опции = ИнфоКоманды.Опции;
ОписаниеКоманды.Подкоманды = Подкоманды;
Результат.Добавить(ОписаниеКоманды);
КонецЦикла;
Возврат Результат;
КонецФункции
Функция НайтиПодкоманды(ИмяРодителя, ВсеИнфо)
Результат = Новый Массив();
Для Каждого КлючЗначение Из ВсеИнфо Цикл
ИнфоКоманды = КлючЗначение.Значение;
Если НРег(ИнфоКоманды.Родитель) = НРег(ИмяРодителя) Тогда
ОписаниеПодкоманды = Новый Структура("Имена, Опции");
ОписаниеПодкоманды.Имена = ИнфоКоманды.Имена;
ОписаниеПодкоманды.Опции = ИнфоКоманды.Опции;
Результат.Добавить(ОписаниеПодкоманды);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПолучитьОпцииКоманды(Желудь, ОпределениеЖелудя)
Опции = Новый Массив();
Опции.Добавить("--help");
Если Рефлектор.МетодСуществует(Желудь, "ОписаниеКоманды") Тогда
Попытка
Сборщик = Новый СборщикОпций();
Желудь.ОписаниеКоманды(Сборщик);
Для Каждого ИмяОпции Из Сборщик.ПолучитьОпции() Цикл
Опции.Добавить(ИмяОпции);
КонецЦикла;
Исключение
Лог.Предупреждение("Не удалось получить опции команды через ОписаниеКоманды: %1", ОписаниеОшибки());
КонецПопытки;
Иначе
Свойства = ОпределениеЖелудя.Свойства();
Для Каждого Свойство Из Свойства Цикл
АннотацияОпции = РаботаСАннотациями.ПолучитьАннотацию(Свойство, "Опция");
Если АннотацияОпции = Неопределено Тогда
Продолжить;
КонецЕсли;
ИмяОпции = РаботаСАннотациями.ПолучитьЗначениеПараметраАннотации(АннотацияОпции, "Имя");
Для Каждого ЧастьОпции Из СтрРазделить(ИмяОпции, " ") Цикл
Если СтрДлина(ЧастьОпции) = 1 Тогда
Опции.Добавить("-" + ЧастьОпции);
Иначе
Опции.Добавить("--" + ЧастьОпции);
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
Возврат Опции;
КонецФункции