-
Notifications
You must be signed in to change notification settings - Fork 17
feat: built-in completions command with shell script generation #88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nixel2007
wants to merge
12
commits into
oscript-library:develop
Choose a base branch
from
nixel2007:feature/completions
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
24d19c5
feat: built-in completions command with shell script generation
nixel2007 0c50f50
refactor(completion): promote КомандаДополнения to top-level class
nixel2007 767078c
refactor(completion): use existing ПолучитьТаблицуОпций/Аргументов fo…
nixel2007 80072b9
refactor(completion): flatten completion values into table row
nixel2007 84a86ac
refactor(completion): use builtin Действие instead of delegate package
nixel2007 26a8800
refactor(completion): trust the provider contract
nixel2007 ff92eb9
refactor: drop delegate package dependency in favor of native Действие
nixel2007 2d721ac
refactor(completions): normalize command model and simplify shell gen…
nixel2007 2e57bf2
refactor(completions): generators as visitors over command tree
nixel2007 e442264
fix(completions): предлагать только канонические имена команд
nixel2007 a762093
fix(completions/zsh): предлагать опции при вводе флага
nixel2007 024b5dc
fix(completions/pwsh): tokenize via extent.Text and use $wordToComplete
nixel2007 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
200 changes: 200 additions & 0 deletions
200
src/core/Классы/internal/completion/Классы/ГенераторДополненияBash.os
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,200 @@ | ||
| // Генератор скрипта автодополнения для GNU Bash. | ||
|
|
||
| Функция Оболочка() Экспорт | ||
| Возврат "bash"; | ||
| КонецФункции | ||
|
|
||
| Функция СформироватьСкрипт(ИмяПриложения, Модель) Экспорт | ||
|
|
||
| ИмяФункции = "_" + ИмяФункцииИзИмени(ИмяПриложения) + "_completions"; | ||
|
|
||
| СтрокиСкрипта = Новый Массив(); | ||
| СтрокиСкрипта.Добавить("# " + ИмяПриложения + " bash completions"); | ||
| СтрокиСкрипта.Добавить("# Добавьте строку ниже в ~/.bashrc для активации:"); | ||
| СтрокиСкрипта.Добавить("# source <(" + ИмяПриложения + " completions --shell bash)"); | ||
| СтрокиСкрипта.Добавить(""); | ||
| СтрокиСкрипта.Добавить(ИмяФункции + "() {"); | ||
| СтрокиСкрипта.Добавить(" 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"); | ||
|
|
||
| Для Каждого Описание Из Модель Цикл | ||
| ДобавитьВеткуКоманды(СтрокиСкрипта, Описание, " "); | ||
| КонецЦикла; | ||
|
|
||
| СтрокиСкрипта.Добавить(" *)"); | ||
| СтрокиСкрипта.Добавить(" ;;"); | ||
| СтрокиСкрипта.Добавить(" esac"); | ||
| СтрокиСкрипта.Добавить(""); | ||
| СтрокиСкрипта.Добавить(" return 0"); | ||
| СтрокиСкрипта.Добавить("}"); | ||
| СтрокиСкрипта.Добавить(""); | ||
| СтрокиСкрипта.Добавить("complete -F " + ИмяФункции + " " + ИмяПриложения); | ||
|
|
||
| Возврат СтрСоединить(СтрокиСкрипта, Символы.ПС); | ||
|
|
||
| КонецФункции | ||
|
|
||
| Процедура ДобавитьВеткуКоманды(СтрокиСкрипта, Описание, Отступ) | ||
|
|
||
| ПаттернCase = СтрСоединить(Описание.Имена, "|"); | ||
| СтрокиСкрипта.Добавить(Отступ + ПаттернCase + ")"); | ||
|
|
||
| ИменаОпций = ИменаПараметровДляКомплита(Описание.Опции); | ||
|
|
||
| Для Каждого Опция Из Описание.Опции Цикл | ||
| Если Опция.Значения.Количество() = 0 Тогда | ||
| Продолжить; | ||
| КонецЕсли; | ||
|
|
||
| Для Каждого ИмяОпции Из Опция.Имена Цикл | ||
| СтрокиСкрипта.Добавить(Отступ + " if [ ""$prev"" = """ + ИмяОпции + """ ]; then"); | ||
| СтрокиСкрипта.Добавить(Отступ + " COMPREPLY=($(compgen -W """ + СтрСоединить(Опция.Значения, " ") + """ -- ""$cur""))"); | ||
| СтрокиСкрипта.Добавить(Отступ + " return 0"); | ||
| СтрокиСкрипта.Добавить(Отступ + " fi"); | ||
| КонецЦикла; | ||
| КонецЦикла; | ||
|
|
||
| СтрокиСкрипта.Добавить(Отступ + " if [[ ""$cur"" == -* ]]; then"); | ||
| СтрокиСкрипта.Добавить(Отступ + " COMPREPLY=($(compgen -W """ + СтрСоединить(ИменаОпций, " ") + """ -- ""$cur""))"); | ||
| СтрокиСкрипта.Добавить(Отступ + " return 0"); | ||
| СтрокиСкрипта.Добавить(Отступ + " fi"); | ||
|
|
||
| Если Описание.Подкоманды.Количество() > 0 Тогда | ||
|
|
||
| ИменаПодкоманд = Новый Массив(); | ||
| Для Каждого Под Из Описание.Подкоманды Цикл | ||
| Для Каждого Имя Из Под.Имена Цикл | ||
| ИменаПодкоманд.Добавить(Имя); | ||
| КонецЦикла; | ||
| КонецЦикла; | ||
|
|
||
| СтрокиСкрипта.Добавить(Отступ + " if [ $cword -eq 2 ]; then"); | ||
| СтрокиСкрипта.Добавить(Отступ + " COMPREPLY=($(compgen -W """ + СтрСоединить(ИменаПодкоманд, " ") + """ -- ""$cur""))"); | ||
| СтрокиСкрипта.Добавить(Отступ + " return 0"); | ||
| СтрокиСкрипта.Добавить(Отступ + " fi"); | ||
|
|
||
| СтрокиСкрипта.Добавить(Отступ + " local subcommand=""${words[2]}"""); | ||
| СтрокиСкрипта.Добавить(Отступ + " case ""$subcommand"" in"); | ||
| Для Каждого Под Из Описание.Подкоманды Цикл | ||
| ДобавитьВеткуПодкоманды(СтрокиСкрипта, Под, Отступ + " "); | ||
| КонецЦикла; | ||
| СтрокиСкрипта.Добавить(Отступ + " *)"); | ||
| СтрокиСкрипта.Добавить(Отступ + " ;;"); | ||
| СтрокиСкрипта.Добавить(Отступ + " esac"); | ||
|
|
||
| Иначе | ||
|
|
||
| ЗначенияАргументов = СобратьЗначенияАргументов(Описание); | ||
| Если ЗначенияАргументов.Количество() > 0 Тогда | ||
| СтрокиСкрипта.Добавить(Отступ + " COMPREPLY=($(compgen -W """ + СтрСоединить(ЗначенияАргументов, " ") + """ -- ""$cur""))"); | ||
| КонецЕсли; | ||
|
|
||
| КонецЕсли; | ||
|
|
||
| СтрокиСкрипта.Добавить(Отступ + " ;;"); | ||
|
|
||
| КонецПроцедуры | ||
|
|
||
| Процедура ДобавитьВеткуПодкоманды(СтрокиСкрипта, Описание, Отступ) | ||
|
|
||
| ПаттернCase = СтрСоединить(Описание.Имена, "|"); | ||
| СтрокиСкрипта.Добавить(Отступ + ПаттернCase + ")"); | ||
|
|
||
| ИменаОпций = ИменаПараметровДляКомплита(Описание.Опции); | ||
|
|
||
| Для Каждого Опция Из Описание.Опции Цикл | ||
| Если Опция.Значения.Количество() = 0 Тогда | ||
| Продолжить; | ||
| КонецЕсли; | ||
| Для Каждого ИмяОпции Из Опция.Имена Цикл | ||
| СтрокиСкрипта.Добавить(Отступ + " if [ ""$prev"" = """ + ИмяОпции + """ ]; then"); | ||
| СтрокиСкрипта.Добавить(Отступ + " COMPREPLY=($(compgen -W """ + СтрСоединить(Опция.Значения, " ") + """ -- ""$cur""))"); | ||
| СтрокиСкрипта.Добавить(Отступ + " return 0"); | ||
| СтрокиСкрипта.Добавить(Отступ + " fi"); | ||
| КонецЦикла; | ||
| КонецЦикла; | ||
|
|
||
| СтрокиСкрипта.Добавить(Отступ + " if [[ ""$cur"" == -* ]]; then"); | ||
| СтрокиСкрипта.Добавить(Отступ + " COMPREPLY=($(compgen -W """ + СтрСоединить(ИменаОпций, " ") + """ -- ""$cur""))"); | ||
| СтрокиСкрипта.Добавить(Отступ + " return 0"); | ||
| СтрокиСкрипта.Добавить(Отступ + " fi"); | ||
|
|
||
| ЗначенияАргументов = СобратьЗначенияАргументов(Описание); | ||
| Если ЗначенияАргументов.Количество() > 0 Тогда | ||
| СтрокиСкрипта.Добавить(Отступ + " COMPREPLY=($(compgen -W """ + СтрСоединить(ЗначенияАргументов, " ") + """ -- ""$cur""))"); | ||
| КонецЕсли; | ||
|
|
||
| СтрокиСкрипта.Добавить(Отступ + " ;;"); | ||
|
|
||
| КонецПроцедуры | ||
|
|
||
| Функция ИменаПараметровДляКомплита(Опции) | ||
|
|
||
| Результат = Новый Массив(); | ||
| Результат.Добавить("--help"); | ||
|
|
||
| Для Каждого Опция Из Опции Цикл | ||
| Для Каждого Имя Из Опция.Имена Цикл | ||
| Результат.Добавить(Имя); | ||
| КонецЦикла; | ||
| КонецЦикла; | ||
|
|
||
| Возврат Результат; | ||
|
|
||
| КонецФункции | ||
|
|
||
| Функция СобратьЗначенияАргументов(Описание) | ||
|
|
||
| Результат = Новый Массив(); | ||
| Для Каждого Аргумент Из Описание.Аргументы Цикл | ||
| Для Каждого Значение Из Аргумент.Значения Цикл | ||
| Результат.Добавить(Значение); | ||
| КонецЦикла; | ||
| КонецЦикла; | ||
|
|
||
| Возврат Результат; | ||
|
|
||
| КонецФункции | ||
|
|
||
| Функция ИмяФункцииИзИмени(ИмяПриложения) | ||
|
|
||
| Результат = ""; | ||
| Для Инд = 1 По СтрДлина(ИмяПриложения) Цикл | ||
| Символ = Сред(ИмяПриложения, Инд, 1); | ||
| Если (Символ >= "a" И Символ <= "z") | ||
| Или (Символ >= "A" И Символ <= "Z") | ||
| Или (Символ >= "0" И Символ <= "9") | ||
| Или Символ = "_" Тогда | ||
| Результат = Результат + Символ; | ||
| Иначе | ||
| Результат = Результат + "_"; | ||
| КонецЕсли; | ||
| КонецЦикла; | ||
|
|
||
| Возврат Результат; | ||
|
|
||
| КонецФункции |
159 changes: 159 additions & 0 deletions
159
src/core/Классы/internal/completion/Классы/ГенераторДополненияPwsh.os
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| // Генератор скрипта автодополнения для PowerShell. | ||
|
|
||
| Функция Оболочка() Экспорт | ||
| Возврат "pwsh"; | ||
| КонецФункции | ||
|
|
||
| Функция СформироватьСкрипт(ИмяПриложения, Модель) Экспорт | ||
|
|
||
| Строки = Новый Массив(); | ||
| Строки.Добавить("# " + ИмяПриложения + " PowerShell completions"); | ||
| Строки.Добавить("# Активируйте строкой в профиле PowerShell ($PROFILE):"); | ||
| Строки.Добавить("# " + ИмяПриложения + " completions --shell pwsh | Out-String | Invoke-Expression"); | ||
| Строки.Добавить(""); | ||
| Строки.Добавить("Register-ArgumentCompleter -Native -CommandName '" + ИмяПриложения + "' -ScriptBlock {"); | ||
| Строки.Добавить(" param($wordToComplete, $commandAst, $cursorPosition)"); | ||
| Строки.Добавить(""); | ||
| Строки.Добавить(" $tokens = $commandAst.CommandElements | ForEach-Object { $_.Extent.Text }"); | ||
| Строки.Добавить(" $command = if ($tokens.Count -ge 2) { $tokens[1] } else { '' }"); | ||
| Строки.Добавить(" $subcommand = if ($tokens.Count -ge 3) { $tokens[2] } else { '' }"); | ||
| Строки.Добавить(" $prev = if ($tokens.Count -ge 2) { $tokens[$tokens.Count - 2] } else { '' }"); | ||
| Строки.Добавить(" $position = $tokens.Count - 1"); | ||
| Строки.Добавить(" if (-not [string]::IsNullOrEmpty($wordToComplete)) { $position = $position - 1 }"); | ||
| Строки.Добавить(""); | ||
|
|
||
| СтрокаКоманд = " $commands = @("; | ||
| ПерваяКоманда = Истина; | ||
| Для Каждого Описание Из Модель Цикл | ||
| Для Каждого Имя Из Описание.Имена Цикл | ||
| Если Не ПерваяКоманда Тогда | ||
| СтрокаКоманд = СтрокаКоманд + ", "; | ||
| КонецЕсли; | ||
| СтрокаКоманд = СтрокаКоманд + "'" + Имя + "'"; | ||
| ПерваяКоманда = Ложь; | ||
| КонецЦикла; | ||
| КонецЦикла; | ||
| СтрокаКоманд = СтрокаКоманд + ")"; | ||
| Строки.Добавить(СтрокаКоманд); | ||
|
|
||
| Строки.Добавить(""); | ||
| Строки.Добавить(" if ($position -le 1) {"); | ||
| Строки.Добавить(" return $commands | Where-Object { $_ -like ""$wordToComplete*"" } | ForEach-Object {"); | ||
| Строки.Добавить(" [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)"); | ||
| Строки.Добавить(" }"); | ||
| Строки.Добавить(" }"); | ||
| Строки.Добавить(""); | ||
| Строки.Добавить(" switch ($command) {"); | ||
|
|
||
| Для Каждого Описание Из Модель Цикл | ||
| ДобавитьВеткуКоманды(Строки, Описание, " "); | ||
| КонецЦикла; | ||
|
|
||
| Строки.Добавить(" default { }"); | ||
| Строки.Добавить(" }"); | ||
| Строки.Добавить("}"); | ||
|
|
||
| Возврат СтрСоединить(Строки, Символы.ПС); | ||
|
|
||
| КонецФункции | ||
|
|
||
| Процедура ДобавитьВеткуКоманды(Строки, Описание, Отступ) | ||
|
|
||
| Для Каждого Имя Из Описание.Имена Цикл | ||
| Строки.Добавить(Отступ + "'" + Имя + "' {"); | ||
|
|
||
| Если Описание.Подкоманды.Количество() > 0 Тогда | ||
| ПодкомандыМассив = "@("; | ||
| ПерваяП = Истина; | ||
| Для Каждого Под Из Описание.Подкоманды Цикл | ||
| Для Каждого ИмяП Из Под.Имена Цикл | ||
| Если Не ПерваяП Тогда | ||
| ПодкомандыМассив = ПодкомандыМассив + ", "; | ||
| КонецЕсли; | ||
| ПодкомандыМассив = ПодкомандыМассив + "'" + ИмяП + "'"; | ||
| ПерваяП = Ложь; | ||
| КонецЦикла; | ||
| КонецЦикла; | ||
| ПодкомандыМассив = ПодкомандыМассив + ")"; | ||
|
|
||
| Строки.Добавить(Отступ + " $subs = " + ПодкомандыМассив); | ||
| Строки.Добавить(Отступ + " if ($position -le 2) {"); | ||
| Строки.Добавить(Отступ + " return $subs | Where-Object { $_ -like ""$wordToComplete*"" } | ForEach-Object {"); | ||
| Строки.Добавить(Отступ + " [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)"); | ||
| Строки.Добавить(Отступ + " }"); | ||
| Строки.Добавить(Отступ + " }"); | ||
|
|
||
| Строки.Добавить(Отступ + " switch ($subcommand) {"); | ||
| Для Каждого Под Из Описание.Подкоманды Цикл | ||
| ДобавитьВеткуПодкоманды(Строки, Под, Отступ + " "); | ||
| КонецЦикла; | ||
| Строки.Добавить(Отступ + " default { }"); | ||
| Строки.Добавить(Отступ + " }"); | ||
| Иначе | ||
| ДобавитьТелоПараметров(Строки, Описание, Отступ + " "); | ||
| КонецЕсли; | ||
|
|
||
| Строки.Добавить(Отступ + " return"); | ||
| Строки.Добавить(Отступ + "}"); | ||
| КонецЦикла; | ||
|
|
||
| КонецПроцедуры | ||
|
|
||
| Процедура ДобавитьВеткуПодкоманды(Строки, Описание, Отступ) | ||
|
|
||
| Для Каждого Имя Из Описание.Имена Цикл | ||
| Строки.Добавить(Отступ + "'" + Имя + "' {"); | ||
| ДобавитьТелоПараметров(Строки, Описание, Отступ + " "); | ||
| Строки.Добавить(Отступ + " return"); | ||
| Строки.Добавить(Отступ + "}"); | ||
| КонецЦикла; | ||
|
|
||
| КонецПроцедуры | ||
|
|
||
| Процедура ДобавитьТелоПараметров(Строки, Описание, Отступ) | ||
|
|
||
| Для Каждого Опция Из Описание.Опции Цикл | ||
| Если Опция.Значения.Количество() = 0 Тогда | ||
| Продолжить; | ||
| КонецЕсли; | ||
| Для Каждого ИмяОпции Из Опция.Имена Цикл | ||
| МассивЗначений = "@("; | ||
| ПерваяЗ = Истина; | ||
| Для Каждого Значение Из Опция.Значения Цикл | ||
| Если Не ПерваяЗ Тогда | ||
| МассивЗначений = МассивЗначений + ", "; | ||
| КонецЕсли; | ||
| МассивЗначений = МассивЗначений + "'" + Значение + "'"; | ||
| ПерваяЗ = Ложь; | ||
| КонецЦикла; | ||
| МассивЗначений = МассивЗначений + ")"; | ||
| Строки.Добавить(Отступ + "if ($prev -eq '" + ИмяОпции + "') {"); | ||
| Строки.Добавить(Отступ + " return " + МассивЗначений + " | Where-Object { $_ -like ""$wordToComplete*"" } | ForEach-Object {"); | ||
| Строки.Добавить(Отступ + " [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)"); | ||
| Строки.Добавить(Отступ + " }"); | ||
| Строки.Добавить(Отступ + "}"); | ||
| КонецЦикла; | ||
| КонецЦикла; | ||
|
|
||
| ЕстьЗначенияАргументов = Ложь; | ||
| МассивАргументов = "@("; | ||
| ПерваяА = Истина; | ||
| Для Каждого Аргумент Из Описание.Аргументы Цикл | ||
| Для Каждого Значение Из Аргумент.Значения Цикл | ||
| Если Не ПерваяА Тогда | ||
| МассивАргументов = МассивАргументов + ", "; | ||
| КонецЕсли; | ||
| МассивАргументов = МассивАргументов + "'" + Значение + "'"; | ||
| ПерваяА = Ложь; | ||
| ЕстьЗначенияАргументов = Истина; | ||
| КонецЦикла; | ||
| КонецЦикла; | ||
| МассивАргументов = МассивАргументов + ")"; | ||
|
|
||
| Если ЕстьЗначенияАргументов Тогда | ||
| Строки.Добавить(Отступ + "return " + МассивАргументов + " | Where-Object { $_ -like ""$wordToComplete*"" } | ForEach-Object {"); | ||
| Строки.Добавить(Отступ + " [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)"); | ||
| Строки.Добавить(Отступ + "}"); | ||
| КонецЕсли; | ||
|
|
||
| КонецПроцедуры |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.