1
0
mirror of https://github.com/alei1180/curlone.git synced 2025-11-26 23:10:24 +02:00

feat(cli): Добавление исходников библиотеки cli

This commit is contained in:
Dmitry Ivanov
2024-12-23 23:24:34 +03:00
parent b0959201fe
commit 996722c433
51 changed files with 9239 additions and 3 deletions

5
lib/cli/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
*.ospx
tests.xml
coverage/*
bdd-log.xml
tests-reports/*

77
lib/cli/.travis.yml Normal file
View File

@@ -0,0 +1,77 @@
sudo: required
language: generic
notifications:
email: false
env:
global:
- CHANNEL=dev
- PACKAGE_NAME=cli
matrix:
- OSCRIPT_VERSION=1_0_20
- OSCRIPT_VERSION=night-build
matrix:
allow_failures:
- env: OSCRIPT_VERSION=night-build
services:
- docker
addons:
sonarqube: true
jdk:
- openjdk11
before_install:
# Load cached docker images
- if [[ -d $HOME/docker ]]; then ls $HOME/docker/*.tar.gz | xargs -I {file} sh -c "zcat {file} | docker load"; fi
before_cache:
# Save tagged docker images
- >
mkdir -p $HOME/docker && docker images -a --filter='dangling=false' --format '{{.Repository}}:{{.Tag}} {{.ID}}'
| xargs -n 2 -t sh -c 'test -e $HOME/docker/$1.tar.gz || docker save $0 | gzip -2 > $HOME/docker/$1.tar.gz'
install:
- docker pull evilbeaver/onescript:1.0.19
script:
- docker version
- docker run -it -e OSCRIPT_VERSION=$OSCRIPT_VERSION -v $(pwd):/work_dir evilbeaver/onescript:1.0.19 sh -c 'cd /work_dir; sh /work_dir/travis-ci.sh; exit' | tee /tmp/test.log
- grep 'Результат прогона тестов <Да>' /tmp/test.log
after_success:
# - bash <(curl -s https://codecov.io/bash)
- ./sonar-qube.sh
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.sonar/cache'
- '$HOME/docker'
jobs:
include:
- stage: Сборка и публикация github & hub.oscript.io
script: skip
before_deploy:
- docker run -it -v $(pwd):/work_dir evilbeaver/onescript:1.0.19 sh -c 'cd /work_dir; opm build ./ ; exit'
deploy:
- provider: releases
api_key: "$GITHUB_OAUTH_TOKEN"
file_glob: true
file: $PACKAGE_NAME*.ospx
skip_cleanup: true
on:
branch: master
tags: true
- provider: script
skip_cleanup: true
script: docker run -it -v $(pwd):/work_dir evilbeaver/onescript:1.0.19 sh -c 'cd /work_dir; opm push --token $GITHUB_OAUTH_TOKEN --channel dev --file ./$PACKAGE_NAME-*.ospx; exit'
on:
branch: develop
- provider: script
skip_cleanup: true
script: docker run -it -v $(pwd):/work_dir evilbeaver/onescript:1.0.19 sh -c 'cd /work_dir; opm push --token $GITHUB_OAUTH_TOKEN --channel stable --file ./$PACKAGE_NAME-*.ospx; exit'
on:
branch: master
tags: true

View File

@@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at khorevaa@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

201
lib/cli/LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

602
lib/cli/README.md Normal file
View File

@@ -0,0 +1,602 @@
# `C`_ommand_ `L`_ine_ `I`_nterface_ для OScript
[![Stars](https://img.shields.io/github/stars/khorevaa/cli.svg?label=Github%20%E2%98%85&a)](https://github.com/khorevaa/cli/stargazers)
[![Release](https://img.shields.io/github/tag/khorevaa/cli.svg?label=Last%20release&a)](https://github.com/khorevaa/cli/releases)
[![Открытый чат проекта https://gitter.im//oscript-cli/Lobby](https://badges.gitter.im/khorevaa/cli.png)](https://gitter.im/oscript-cli/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/khorevaa/cli.svg?branch=master)](https://travis-ci.org/khorevaa/cli)
[![Coverage Status](https://coveralls.io/repos/github/khorevaa/cli/badge.svg?branch=master)](https://coveralls.io/github/khorevaa/cli?branch=master)
Короткое название библиотеки `cli`
Данная библиотека для языка OScript позволяет создавать консольные приложения с разбором и проверкой аргументов.
[Документация и описание публичного API](docs/readme.md)
## Быстрый старт
### Пример простого приложения
```bsl
#Использовать cli
Перем Лог;
///////////////////////////////////////////////////////////////////////////////
Процедура ВыполнитьПриложение()
Приложение = Новый КонсольноеПриложение(ПараметрыПриложения.ИмяПриложения(), "Помощник генерации приложения на основании шаблона cli");
Приложение.Версия("v version", ПараметрыПриложения.Версия());
Приложение.УстановитьОсновноеДействие(ЭтотОбъект)
Приложение.Запустить(АргументыКоманднойСтроки);
КонецПроцедуры
Процедура ВыполнитьКоманду(Знач Команда) Экспорт
Сообщить("Полезная работа");
КонецПроцедуры
///////////////////////////////////////////////////////
Попытка
ВыполнитьПриложение();
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
```
### Пример приложения с несколькими командами
```bsl
#Использовать cli
///////////////////////////////////////////////////////////////////////////////
Процедура ВыполнитьПриложение()
Приложение = Новый КонсольноеПриложение("cli", "Помощник генерации приложения на основании шаблона cli", ЭтотОбъект);
Приложение.Версия("v version","1.0.0");
Приложение.ДобавитьКоманду("i init", "Инициализация структуры нового приложения", Новый КомандаInit);
Приложение.ДобавитьКоманду("g generate", "Генерация элементов структуры приложения", Новый КомандаGenerate);
Приложение.Запустить(АргументыКоманднойСтроки);
КонецПроцедуры
Процедура ВыполнитьКоманду(Знач КомандаПриложения) Экспорт
КомандаПриложения.ВывестиСправку();
КонецПроцедуры
///////////////////////////////////////////////////////
Попытка
ВыполнитьПриложение();
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
```
### Пример приложения с вложенными командами
```bsl
#Использовать cli
///////////////////////////////////////////////////////////////////////////////
Процедура ВыполнитьПриложение()
Приложение = Новый КонсольноеПриложение("cli", "Помощник генерации приложения на основании шаблона cli");
Приложение.Версия("v version","1.0.0");
Приложение.ДобавитьКоманду("i init", "Инициализация структуры нового приложения", Новый КомандаInit);
Приложение.ДобавитьКоманду("g generate", "Генерация элементов структуры приложения", Новый КомандаGenerate);
Приложение.Запустить(АргументыКоманднойСтроки);
КонецПроцедуры
///////////////////////////////////////////////////////
Попытка
ВыполнитьПриложение();
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
```
Класс `КомандаGenerate`
Для добавления подкоманды в любую команду используются методы `ДобавитьПодкоманду` или `ДобавитьКоманду`
```bsl
Процедура ОписаниеКоманды(Команда) Экспорт
// Метод <ДобавитьПодкоманду>
Команда.ДобавитьПодкоманду("c command", "Генерация дополнительной вложенной команды", Новый КомандаGenerateCommand);
// Метод <ДобавитьКоманду>
Команда.ДобавитьКоманду("o option", "Генерация опции для команды", Новый КомандаGeneratOption);
Процедура ВыполнитьКоманду(Знач Команда) Экспорт
КонецПроцедуры
```
## Мотивация
Для PR в cmdline слишком большие изменения в API, т.е. обеспечить совместимость очень трудоемко.
Сравнительная таблица возможностей:
| | cli | cmdline |
|-----------------------------------------------------------------------------------|------|---------|
| Встроенная команда help | ✓ | ✓ |
| Автоматическая генерация справки по приложению и командам | ✓ | ✓ |
| Встроенная команда version | ✓ | ✓ |
| Команды | ✓ | ✓ |
| Подкоманды | ✓ | |
| Совмещение булевых (флаговых) опций `-xyz` | ✓ | |
| Совмещение опции и значения `-fValue` | ✓ | |
| Взаимоисключающие опции: `--start ❘ --stop` | ✓ | |
| Необязательные опции : `[-a -b]` or `[-a [-b]]` | ✓ | |
| Проверка аргументов : `FILE PATH` | ✓ | |
| Необязательные аргументы : `SRC [DST]` | ✓ | |
| Повторение аргументов : `SRC... DST` | ✓ | |
| Зависимость опций и аргументов друг от друга : `SRC [-f DST]` | ✓ | |
| Формирование своей строки выполнения: `[-d ❘ --rm] FILE [КОМАНДА [АРГУМЕНТЫ...]]` | ✓ | |
## Установка
Для установки необходимо:
* Скачать файл cli.ospx из раздела [releases](https://github.com/khorevaa/cli/releases)
* Воспользоваться командой:
```
$ opm install -f <ПутьКФайлу>
```
Либо скачать библиотеку с помощью opm:
opm install cli
## Базовые принципы
При создании приложения необходимо указать имя приложения и описание:
```bsl
Приложение = Новый КонсольноеПриложение("cli", "Помощник генерации приложения на основании шаблона cli");
```
Каждый возможный вариант выполнения - это "Команда". Команды могут создаваться явно, кроме того, само Приложение содержит в себе корневую (Основную) команду.
Каждая команда реализуется в виде отдельного класса. Каждый такой класс обязан иметь экспортную процедуру
```bsl
Процедура ВыполнитьКоманду(Знач Команда) Экспорт
КонецПроцедуры
```
Для установки основной функции выполнения приложения в приложении надо установить основное действие. В простейшем случае основным действием может выступать сам стартовый сценарий:
Передать данный класс через процедуру:
```bsl
Приложение.УстановитьОсновноеДействие(ЭтотОбъект)
```
### Встроенная команда "Версия"
Для добавления отображения версии через опции: ```-v, --version``` надо добавить строчку:
```bsl
Приложение.Версия("v version", "1.2.3");
```
Это позволит запускать приложение с ключом ``v`` или ``--version``:
my-app --version
### Запуск парсера аргументов и приложения в целом
Для запуска приложения необходимо добавить строчку:
```bsl
Приложение.Запустить(АргументыКоманднойСтроки);
```
Этот вызов является "точкой входа" в консольное приложение. В общем случае после него уже не идет никакого дополнительного кода. Парсер анализирует аргументы и запускает команды автоматически.
## Параметры команд/приложения
Все параметры разделяются на два типа:
* Опция
* Аргумент
В общем случае, опции имеют имена, аргументы являются позиционными. Кроме того, по умолчанию указание опций необязательно, а аргументов - обязательно. Это можно переопределить, но дефолтное поведение именно такое. Аргумент - обязателен, опция - нет.
## Опция
Опция может быть следующих простых типов:
* Булево
* Строка
* Число
* Дата
Также опция может принимать массивы данных типов, например:
* МассивЧисел
* МассивСтрок
* МассивДат
* МассивБулево
* Перечисление
Для простых типов поддерживается определение типа значения по умолчанию. Пример:
```bsl
Отладка = Команда.Опция("f force", ,"Описание опция")
.ТБулево() // тип опции Булево
;
// Можно заменить на вызов
Отладка = Команда.Опция("f force", Ложь ,"Описание опция");
```
Пример `булево` опции:
```bsl
Отладка = Команда.Опция("v debug", ложь ,"Описание опции")
.Флаговый() // тип опции булево
.ВОкружении("ИМЯ_ПЕРЕМЕННОЙ")
.ПоУмолчанию(Ложь)
.СкрытьВСправке(); // Любой тип
```
`ВОкружении` Возможна передача нескольких переменных окружения, разделенных через **пробел**
Пример `перечисления` опции:
```bsl
ЦветКонсоли = Команда.Опция("c color", "green" ,"Описание опции")
.ТПеречисление() // тип опции перечисление
.Перечисление("green", Новый ЗеленыйЦвет(), "Консоль будет зеленого цвета")
.Перечисление("red", Цвета.Красный, "Консоль будет красного цвета")
.Перечисление("Случайный", СлучайныйЦвет(), "Консоль будет случайного цвета")
;
```
Перечисление ограничивает пользователя в выборе значения опции, при этом разработчик для каждой опции может задавать свой тип значения
Подробное описание возможностей параметров команд и приложения [](./docs/ПараметрКоманды.md)
## Пример синтаксиса опций
### Для типа булево:
* `-f` : одно тире для коротких имен
* `-f=false` : одно тире для коротких имен и значение булево (true/false)
* `--force` : двойное тире для длинных имен
* `-it` : группировка булевых опций, будет эквивалентно: -i -t
### Для типа строка, число, дата, длительность:
* `-e=value` : одно тире для коротких имен, через **равно** значение опции
* `-e value` : одно тире для коротких имен, через **пробел** значение опции
* `-Ivalue` : одно тире для коротких имен, и сразу значение опции
* `--extra=value` : двойное тире для длинных имен, через **равно** значение опции
* `--extra value` : двойное тире для длинных имен, через **пробел** значение опции
### Для массивов опций (МассивСтрок, МассивЧисел, МассивДат):
повторение опции создаст массив данных указанного типа опций:
* `-e PATH:/bin -e PATH:/usr/bin` : Массив, содержащий `["/bin", "/usr/bin"]`
* `-ePATH:/bin -ePATH:/usr/bin` : Массив, содержащий `["/bin", "/usr/bin"]`
* `-e=PATH:/bin -e=PATH:/usr/bin` : Массив, содержащий `["/bin", "/usr/bin"]`
* `--env PATH:/bin --env PATH:/usr/bin` : Массив, содержащий `["/bin", "/usr/bin"]`
* `--env=PATH:/bin --env=PATH:/usr/bin` : Массив, содержащий `["/bin", "/usr/bin"]`
## Аргументы
Аргументы могут быть следующих простых типов:
* Булево
* Строка
* Число
* Дата
Для простых типов поддерживается определение типа значения по умолчанию. Пример:
```bsl
Отладка = Команда.Аргумент("PATH", "" ,"Описание аргумента")
.ТСтрока() // тип опции Строка
;
// Можно заменить на вызов
Отладка = Команда.Аргумент("PATH", "" ,"Описание аргумента");
```
Также аргументы могут принимать массивы данных типов, например:
* МассивЧисел
* МассивСтрок
* МассивДат
* Перечисление (см. пример опций)
Пример `Строки` аргумента:
```bsl
Отладка = Команда.Аргумент("PATH", "" ,"Описание аргумента")
.ТСтрока() // тип опции Строка
.ВОкружении("ИМЯ_ПЕРЕМЕННОЙ")
.ПоУмолчанию(Ложь)
.СкрытьВСправке(); // Любой тип
```
`ВОкружении` Возможна передача нескольких переменных окружения, разделенных через **пробел**
Подробное описание возможностей параметров команд и приложения [](./docs/ПараметрКоманды.md)
## Операторы
Оператор `--` устанавливает метку завершению любых опций.
Все, что следует за данным оператором, будет считаться аргументом, даже если начинается с **тире**
Для примера, если команда "ХочуФайл" принимает в качестве аргумента имя файла, но начинающегося с `-`, тогда строка запуска данной программы будет выглядеть так:
```bsl
ИмяФайла = Команда.Аргумент("FILE", "", "имя файла для создания")
```
Допустим, нужное нам имя файла равно `-f`, тогда если выполнить нашу команду:
```
ХочуФайл -f
```
то будет выдана ошибка, т.к. `-f` распознано как опция, а не аргумент.
Для того, чтобы решить данную проблему, необходимо объявить окончание опций через оператор `--`
```
ХочуФайл -- -f
```
Тогда определение аргументов будет работать корректно.
## Команды и подкоманды
cli поддерживает создание команд и подкоманд.
Неограниченное количество вложенных подкоманд.
А также установки синонимов для команд и подкоманд.
```bsl
Приложение = Новый КонсольноеПриложение("testapp", "Выполняет полезную работу");
КомандаAve = Приложение.ДобавитьКоманду("a ave", "Команда ave", КлассРеализацииПодкоманды);
```
* Первый аргумент, наименование команды, которое необходимо будет вводить для запуска
* Второй аргумент, описание команды, которое будет выводиться в справке
* Третий аргумент, КлассРеализацииКоманды
cli поддерживает указание псевдонимов команд. Для примера:
```bsl
КомандаAve = Приложение.ДобавитьКоманду("start run r", "Команда start", КлассРеализацииПодкоманды);
```
Псевдонимы для команды будут `start`, `run`, и`r` - можно использовать любой из них.
cli поддерживает автоматическую инициализацию параметров команд.
Переданный класс должен реализовывать процедуру:
```bsl
Процедура ОписаниеКоманды(Команда) Экспорт
Путь = Команда.Аргумент("PATH", "" ,"Описание аргумента")
.ТСтрока() / тип опции Строка
.ВОкружении("ИМЯ_ПЕРЕМЕННОЙ")
.ПоУмолчанию(Ложь)
.СкрытьВСправке(); // Любой тип
Отладка = Команда.Опция("o opt", Ложь ,"Описание опции")
.ТСтрока() / тип опции Строка
.ВОкружении("ИМЯ_ПЕРЕМЕННОЙ")
.ПоУмолчанию(Ложь)
.СкрытьВСправке(); // Любой тип
КонецПроцедуры
```
## Строка использования приложения (спек)
Синтаксис спек базируется на POSIX. Спек является грамматикой парсера аргументов и определяет порядок следования аргументов и опций в командной строке, а также вариативность параметров. Спек формируется либо вручную через указание в поле `Спек`, либо автоматически в момент вызова выполнения приложения / или команды.
### Опции
Для определения опций можно использовать длинные и короткие имена опций:
```bsl
Команда.Спек = "-f";
```
И/или:
```bsl
Команда.Спек = "--force";
```
Пример добавления аргументов в команду:
```bsl
Команд.Опция("f force", ...);
```
### Аргументы
Правила наименования аргументов, имя должно содержать только символы в верхнем регистре:
Пример использования аргументов в определении строки использования приложения
```bsl
Команда.Спек="SRC DST"
```
Пример добавления аргументов в команду:
```bsl
Команда.Аргумент("SRC", ...);
Команда.Аргумент("DST", ...);
```
### Сортировка строки использования
cli позволяет произвольно настраивать порядок использования опций и аргументов:
```bsl
Команда.Спек = "-f -g NAME -h PATH";
```
В примере выше задана грамматика: в командой строке могут идти сначала опции -f и -g, затем аргумент NAME, затем опция -h, затем аргумент PATH.
## Необязательность
Чтобы сделать аргументы или опции необязательными, их необходимо заключить в `[...]`:
```bsl
Команда.Спек = "[-x]";
```
### Выбор между
Для отражения выбора между несколькими опциями или аргументами используется символ `|`:
```bsl
Команда.Спек = "--server | --agent";
Команда.Спек = "-H | -L | -P";
Команда.Спек = "-f | PATH";
```
### Повторитель
Для повторения аргументов или опций необходимо использовать оператор `...`:
```bsl
Команда.Спек = "PATH...";
Команда.Спек = "-f...";
```
### Логические группы
Возможна логическая группировка опций и аргументов. Данную группировку стоит использовать и комбинировать с такими символами как `|` и `...`:
```bsl
Команда.Спек = "(-e КОМАНДА)... | (-x|-y)";
```
Приведенный пример настраивает строку использования следующим образом:
* Повторение опции -e и команды
* Или
* Выбор между -x и -y
### Группировка опций
Все короткие опции (типа булево) можно группировать в любом порядке вместе:
```bsl
Команда.Спек = "-abcd";
```
### Все опции
Для определение любой опции приложения:
```bsl
Команда.Спек = "[OPTIONS]";
```
Для примера, для команды с опциями a, b, c и d, указание `[OPTIONS]` или `[ОПЦИИ]` будет аналогично указанию:
```bsl
Команда.Спек = "[-a | -b | -c | -d]...";
```
### Аннотация к опциям в строке использования
Можно задавать в строке использования `=<очень хороший текст>` аннотации после указания опции в длинной или короткой форме, для того чтобы определить дополнительное описание или значение по умолчанию.
Для примера:
```bsl
Команда.Спек = "[ -a=<абсолютный путь к файлу> | --timeout=<в секундах> ] ARG";
```
Данные аннотации игнорируются парсером, и не влияют на работу приложения
### Операторы
Оператор `--` устанавливает метку завершению любых опций.
Все что следует за данным оператором считается аргументами.
Более, сложный пример:
```bsl
Приложение.Спек = "work -lp [-- CMD [ARG...]]";
```
## Грамматика строки использования
Используется упрощенная (EBNF grammar) грамматика при создании строки использования:
Описание символа | Символ и использование | Проверка
-------------------------|------------------------------|----------------------
Короткая опция | '-' | [A-Za-z]
Длинная опция | '--' | [A-Za-z][A-Za-z0-9]*
Соединенные опции | '-' | [A-Za-z]+
Все опции | '[OPTIONS]' или `[ОПЦИИ]` |
Логическая группа | '(' любые другие символы ')' |
Необязательная | '[' любые другие символы ']' |
Повтор аргумента | '...' |
Конец повтора аргументов | '--' |
Можно комбинировать в указанные символы как хочется, чтобы добиться любых необходимых проверок опций и аргументов.
## Строка использования по умолчанию
По умолчанию, если разработчиком не установлена иная, cli автоматически создает для приложения и каждой команды строки использования, используя следующую логику:
* Начало с пустой строки
* Если определена хоть одна опция, добавляется `[OPTIONS]` или `[ОПЦИИ]` к текущей строке использования
* Для каждого добавленного аргумента, добавляет его представление согласно очереди, объявления аргументов.
Для примера, при добавлении в команду следующих опций и аргументов:
```bsl
ИнициализацияГит = Команда.Опция("g git-init", Ложь, "инициализировать создание git репозитория").Флаговый();
ИнтерактивныйРежим = Команда.Опция("interactive", Ложь, "интерактивный режим ввода информации о приложении").Флаговый();
ИспользоватьПодкоманды = Команда.Опция("s support-subcommads", Ложь, "шаблон с поддержкой подкоманд").Флаговый();
ФайлКонфига = Команда.Опция("c config-file", "", "файл настроек генерации приложения");
НаименованиеПриложения = Команда.Аргумент("NAME", "", "наименование приложения");
ПутьКПапкеГенерации = Команда.Аргумент("PATH", "", "Путь к папке для генерации нового приложения");
```
Будет автоматически создана следующая строка использования данной команды:
```bsl
[OPTIONS] NAME PATH
```
## Доработка
Доработка проводится по git-flow. Жду ваших PR.
## Лицензия
Смотри файл `LICENSE`.

63
lib/cli/appveyor.yml Normal file
View File

@@ -0,0 +1,63 @@
version: 0.9.8-{build}
pull_requests:
do_not_increment_build_number: true
max_jobs: 1
init:
- ps: Set-WinSystemLocale ru-RU
#environment:
# oscript: C:\Program Files (x86)\OneScript\bin\oscript.exe
install:
- cmd: >-
@echo on
# git submodule update --init --recursive
set
curl -o %temp%\oscript-setup.exe http://oscript.io/downloads/latest/exe
%temp%\oscript-setup.exe /silent /log="%temp%\oscript-setup.log" /saveinf="%temp%\oscript-setup-settings.txt"
set OSCRIPT=%ProgramFiles(x86)%\OneScript
dir "%OSCRIPT%\bin"
dir "%OSCRIPT%\lib"
rem SET PATH=%CD%\engine\bin;%PATH%
SET PATH=%OSCRIPT%\bin;%PATH%
where oscript
oscript -version
chcp 65001
opm install opm
opm install 1testrunner
opm install 1bdd
opm install coverage
opm install
opm list
# to disable automatic builds
build: off
test_script:
- cmd: >-
opm run coverage
pushd %APPVEYOR_BUILD_FOLDER%
after_test:
- ps: # upload results to AppVeyor
- ps: Write-Host "Загружаю результаты тестов на CI"
- ps: $wc = New-Object 'System.Net.WebClient'
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests-reports\tests.xml))
artifacts:
- path: tests-reports\tests.xml

893
lib/cli/docs/readme.md Normal file
View File

@@ -0,0 +1,893 @@
Описание публичного интерфейса библиотеки
========================
<!-- TOC -->
- [Класс КонсольноеПриложение:](#класс-консольноеприложение)
- [Публичные свойства](#публичные-свойства)
- [ФлагВерсия](#флагверсия)
- [ВерсияПриложения](#версияприложения)
- [Версия](#версия)
- [УстановитьСпек](#установитьспек)
- [ПолучитьКоманду](#получитькоманду)
- [Запустить](#запустить)
- [ДобавитьКоманду](#добавитькоманду)
- [УстановитьОсновноеДействие](#установитьосновноедействие)
- [УстановитьДействиеПередВыполнением](#установитьдействиепередвыполнением)
- [УстановитьДействиеПослеВыполнения](#установитьдействиепослевыполнения)
- [Опция](#опция)
- [Аргумент](#аргумент)
- [ВыполнитьКоманду](#выполнитькоманду)
- [Класс КомандаПриложения:](#класс-командаприложения)
- [Публичные свойства](#публичные-свойства-1)
- [Спек](#спек)
- [ПодробноеОписание](#подробноеописание)
- [Приложение](#приложение)
- [КомандыРодители](#командыродители)
- [ДобавитьПодкоманду](#добавитьподкоманду)
- [ПолучитьПодкоманды](#получитьподкоманды)
- [ПолучитьИмяКоманды](#получитьимякоманды)
- [ПолучитьСинонимы](#получитьсинонимы)
- [ПолучитьОписание](#получитьописание)
- [ЗначениеОпции](#значениеопции)
- [ЗначениеАргумента](#значениеаргумента)
- [ПараметрыКоманды](#параметрыкоманды)
- [ПередВыполнениемКоманды](#передвыполнениемкоманды)
- [ПослеВыполненияКоманды](#послевыполнениякоманды)
- [ВывестиСправку](#вывестисправку)
- [Запуск](#запуск)
- [НачалоЗапуска](#началозапуска)
- [ЭтоСинонимКоманды](#этосинонимкоманды)
- [Опция](#опция-1)
- [Аргумент](#аргумент-1)
- [УстановитьДействиеВыполнения](#установитьдействиевыполнения)
- [УстановитьДействиеПередВыполнением](#установитьдействиепередвыполнением-1)
- [УстановитьДействиеПослеВыполнения](#установитьдействиепослевыполнения-1)
- [Класс ПараметрКоманды:](#класс-параметркоманды)
- [Публичные свойства](#публичные-свойства-2)
- [Имя](#имя)
- [Описание](#описание)
- [ПодробноеОписание](#подробноеописание-1)
- [ПеременнаяОкружения](#переменнаяокружения)
- [Синонимы](#синонимы)
- [НаименованияПараметров](#наименованияпараметров)
- [СкрытьЗначение](#скрытьзначение)
- [УстановленаИзПеременнойОкружения](#установленаизпеременнойокружения)
- [УстановленаПользователем](#установленапользователем)
- [ТребоватьУстановкиПользователем](#требоватьустановкипользователем)
- [Значение](#значение)
- [ТипОпции](#типопции)
- [ЭтоМассив](#этомассив)
- [Очистить](#очистить)
- [ЗначениеВСтроку](#значениевстроку)
- [ПолучитьОбязательностьВвода](#получитьобязательностьввода)
- [УстановитьЗначение](#установитьзначение)
- [ИзПеременнойОкружения](#изпеременнойокружения)
- [Текучие функции](#текучие-функции)
- [ВОкружении](#вокружении)
- [СкрытьВСправке](#скрытьвсправке)
- [ПоУмолчанию](#поумолчанию)
- [Флаговый](#флаговый)
- [Флаг](#флаг)
- [ТБулево](#тбулево)
- [ТДата](#тдата)
- [ТЧисло](#тчисло)
- [ТСтрока](#тстрока)
- [ТМассивДат](#тмассивдат)
- [ТМассивЧисел](#тмассивчисел)
- [ТМассивСтрок](#тмассивстрок)
- [ТМассивБулево](#тмассивбулево)
- [ТПеречисление](#тперечисление)
- [Перечисление](#перечисление)
- [Описание](#описание-1)
- [ПодробноеОписание](#подробноеописание-2)
- [Псевдоним](#псевдоним)
- [Обязательный](#обязательный)
- [ВФайле](#вфайле)
- [ПроизвольныйТип](#произвольныйтип)
<!-- /TOC -->
### Класс КонсольноеПриложение:
> Основной класс для реализации консольного приложения
#### Публичные свойства
##### ФлагВерсия
```bsl
// Класс ПараметрКоманды, для доступа к установленному значению из вне
```
##### ВерсияПриложения
```bsl
// Строковое представление версии приложения
```
#### Версия
```bsl
// Процедура добавляет версию приложения,
// при вызове данной опции, показывается установленная версия и
// завершается выполнение с кодом (0)
//
// Параметры:
// Наименование - строка - имя опции, в строке допустимо задавать синоним через пробел, например "v version"
// СтрокаВерсии - строка - версия, приложения
```
#### УстановитьСпек
```bsl
// Процедура позволяет переопределить стандартную строку использования приложения
//
// Параметры:
// СтрокаСпек - строка - переопределенная строка использования приложения
```
#### ПолучитьКоманду
```bsl
// Возвращает основную команду приложения
//
// Возвращаемое значение:
// Команда - класс КомандаПриложения
```
#### Запустить
```bsl
// Основная процедура запуска приложения
//
// Параметры:
// АргументыКоманднойСтрокиВходящие - Массив - Элементы <Строка>, необзательный,
// Если, не передано считывает из АргументыКоманднойСтроки
```
#### ДобавитьКоманду
```bsl
// Функция добавляет команду приложение и возвращает экземпляр данной команды
//
// Параметры:
// ИмяКоманды - строка - в строке допустимо задавать синоним через пробел, например "exec e"
// ОписаниеКоманды - строка - описание команды для справки
// КлассРеализацииКоманды - объект - класс, объект реализующий функции выполнения команды.
// Так же используется, для автоматической настройки опций и параметров команды
//
// Возвращаемое значение:
// Команда - класс КомандаПриложения
```
#### УстановитьОсновноеДействие
```bsl
// Процедура устанавливает процедуру "ВыполнитьКоманду" выполнения для приложения
//
// Параметры:
// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды.
// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ВыполнитьКоманду"
//
```
#### УстановитьДействиеПередВыполнением
```bsl
// Процедура устанавливает процедуру "ПередВыполнениемКоманды" выполнения для приложения
// запускаемую перед выполнением "ВыполнитьКоманду"
//
// Параметры:
// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды.
// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ПередВыполнениемКоманды"
//
```
#### УстановитьДействиеПослеВыполнения
```bsl
// Процедура устанавливает процедуру "ПослеВыполненияКоманды" выполнения для приложения
// запускаемую после выполнением "ВыполнитьКоманду"
//
// Параметры:
// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды.
// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ПослеВыполненияКоманды"
//
```
#### Опция
```bsl
// Функция добавляет опцию приложения и возвращает экземпляр данной опции
//
// Параметры:
// Имя - строка - имя опции, в строке допустимо задавать синоним через пробел, например "s some-opt"
// Значение - строка - значение опции по умолчанию
// Описание - объект - описание опции для справки.
//
// Возвращаемое значение:
// Команда - класс ПараметрКоманды
//
// Дополнительно смотри справку по классу ПараметрКоманды
```
#### Аргумент
```bsl
// Функция добавляет аргумент приложения и возвращает экземпляр данной аргумента
//
// Параметры:
// Имя - строка - имя аргумента, в строке допустимо использование только из БОЛЬШИХ латинских букв, например "ARG"
// Значение - строка - значение аргумента по умолчанию
// Описание - объект - описание аргумента для справки.
//
// Возвращаемое значение:
// Команда - класс ПараметрКоманды
//
// Дополнительно смотри справку по классу ПараметрКоманды
//
```
#### ВыполнитьКоманду
```bsl
// Предопределенная процедура выполнения приложения, если не задана процедура в классе.
// Выводит справку, по работе с приложением и завершает работу с кодом "1"
// Переопределяется, процедурой "УстановитьОсновноеДействие"
//
// Параметры:
// Команда - класс КомандаПриложения - инстанс класс, для доступа к опция и аргументам выполняемой команды
//
```
### Класс КомандаПриложения:
> Основной класс для реализации консольного приложения
#### Публичные свойства
##### Спек
```bsl
// Пользовательская строка использования текущей команды
```
##### ПодробноеОписание
```bsl
// (ЗАГОТОВКА) Содержит дополнительно подробное описания для справки по команде
```
##### Приложение
```bsl
// Содержит экземпляр класс КонсольноеПриложения, для возможности получения экспортных свойств приложения
```
##### КомандыРодители
```bsl
// Содержит входящий массив родителей текущей команды
// Устанавливается при выполнении команд родителей
```
#### ДобавитьПодкоманду
```bsl
// Функция добавляет под команду в текущую и возвращает экземпляр данной команды
//
// Параметры:
// ИмяКоманды - строка - в строке допустимо задавать синоним через пробел, например "exec e"
// ОписаниеКоманды - строка - описание команды для справки
// КлассРеализацииКоманды - объект - класс, объект реализующий функции выполнения команды.
// Так же используется, для автоматической настройки опций и параметров команды
//
// Возвращаемое значение:
// Команда - класс КомандаПриложения
```
#### ПолучитьПодкоманды
```bsl
// Функция массив вложенных команд, текущей команды
//
// Возвращаемое значение:
// массив, элементы класс КомандаПриложения
```
#### ПолучитьИмяКоманды
```bsl
// Функция возвращает текущее имя команды
//
// Возвращаемое значение:
// строка
```
#### ПолучитьСинонимы
```bsl
// Функция массив синонимов команды
//
// Возвращаемое значение:
// массив, элементы класс КомандаПриложения
```
#### ПолучитьОписание
```bsl
// Функция возвращает описание команды
//
// Возвращаемое значение:
// строка
```
#### ЗначениеОпции
```bsl
// Функция возвращает значение опции по переданному имени/синониму опции
//
// Параметры:
// ИмяОпции - строка - имя или синоним опции
//
// Возвращаемое значение:
// Произвольный - Значение - полученное значение в результате чтения строки использования или переменных окружения
```
#### ЗначениеАргумента
```bsl
// Функция возвращает значение аргумента по переданному имени аргумента
//
// Параметры:
// ИмяАргумента - строка - имя аргумента
//
// Возвращаемое значение:
// Произвольный - Значение - полученное значение в результате чтения строки использования или переменных окружения
```
#### ПараметрыКоманды
```bsl
// Функция возвращает все параметры команды, для доступа к ним по синонимам
//
// Возвращаемое значение:
// Соответствие
// Ключ - имя или синоним опции/аргумента команды
// Значение - полученное значение в результате чтения строки использования или переменных окружения
```
#### ПередВыполнениемКоманды
```bsl
// Предопределенная процедура ПередВыполнениемКоманды команды, если не задана процедура в классе.
// Содержит код определение необходимости вывода версии приложения
```
#### ПослеВыполненияКоманды
```bsl
// Предопределенная процедура ПослеВыполненияКоманды команды, если не задана процедура в классе.
```
#### ВывестиСправку
```bsl
Процедура выводит справку по команде в консоль
```
#### Запуск
```bsl
// Основная процедура запуска команды приложения
//
// Параметры:
// АргументыCLI - Массив - Элементы <Строка>
//
```
#### НачалоЗапуска
```bsl
// Процедура подготавливает команды к запуску
// Формирует строку использования и
// настраивает парсер для выполнения парсинга входящих параметров
// Обязательно вызывается пред выполнением команды
```
#### ЭтоСинонимКоманды
```bsl
// Функция проверяет строку, что она является ли синонимом текущей команды
//
// Параметры:
// СтрокаПроверки - строка - имя команды, для проверки
//
// Возвращаемое значение:
// булево - истина. если это синоним или имя текущей команды, иначе ложь
```
#### Опция
```bsl
// Функция добавляет опцию команды и возвращает экземпляр данной опции
//
// Параметры:
// Имя - строка - имя опции, в строке допустимо задавать синоним через пробел, например "s some-opt"
// Значение - строка - значение опции по умолчанию
// Описание - объект - описание опции для справки.
//
// Возвращаемое значение:
// Команда - класс ПараметрКоманды
//
// Дополнительно смотри справку по классу ПараметрКоманды
```
#### Аргумент
```bsl
// Функция добавляет аргумент команды и возвращает экземпляр данной аргумента
//
// Параметры:
// Имя - строка - имя аргумента, в строке допустимо использование только из БОЛЬШИХ латинских букв, например "ARG"
// Значение - строка - значение аргумента по умолчанию
// Описание - объект - описание аргумента для справки.
//
// Возвращаемое значение:
// Команда - класс ПараметрКоманды
//
// Дополнительно смотри справку по классу ПараметрКоманды
```
#### УстановитьДействиеВыполнения
```bsl
// Процедура устанавливает процедуру "ВыполнитьКоманду" выполнения для команды
//
// Параметры:
// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды.
// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ВыполнитьКоманду"
//
```
#### УстановитьДействиеПередВыполнением
```bsl
// Процедура устанавливает процедуру "ПередВыполнениемКоманды" выполнения для команды
// запускаемую перед выполнением "ВыполнитьКоманду"
//
// Параметры:
// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды.
// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ПередВыполнениемКоманды"
//
```
#### УстановитьДействиеПослеВыполнения
```bsl
// Процедура устанавливает процедуру "ПослеВыполненияКоманды" выполнения для команды
// запускаемую после выполнением "ВыполнитьКоманду"
//
// Параметры:
// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды.
// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ПослеВыполненияКоманды"
//
```
### Класс ПараметрКоманды:
> Основной класс для реализации параметров команды опции или аргумента
#### Публичные свойства
##### Имя
```bsl
// Имя параметра команды
// первая строка из массива строк, переданных при создании
```
##### Описание
```bsl
// Описание параметра команды
// Используется при выводе справки
```
##### ПодробноеОписание
```bsl
// Подробное описание параметра команды
// Используется при выводе справки (запланировано)
```
##### ПеременнаяОкружения
```bsl
// Содержит имя переменной окружения, откуда получать значение
// допустимо использование нескольких переменных окружения через пробел
// Используется при выводе справки
```
##### Синонимы
```bsl
// Содержит синонимов параметра команды
```
##### НаименованияПараметров
```bsl
// Содержит нормализованные наименования параметров
// для опций ("f force"):
// "-f", "--force"
// для аргументов ("ARG"):
// "ARG"
```
##### СкрытьЗначение
```bsl
// Определяет необходимость показа значения по умолчанию параметра в справке.
// Значение "Истина" скрывает в справке, по умолчанию "Ложь"
```
##### УстановленаИзПеременнойОкружения
```bsl
// Содержит признак истина, если значение получено из переменной окружения
```
##### УстановленаПользователем
```bsl
// Содержит признак истина, если значение установлено пользователем в строке использования
```
##### ТребоватьУстановкиПользователем
```bsl
// Признак обязательности установки значения пользователем в строке использования
// при "истина", если значение не передано явно, будет вызывать исключение
```
##### Значение
```bsl
// Содержит значение параметра
// В том числе установленное значение по умолчанию
```
##### ТипОпции
```bsl
// Содержит тип параметра
```
#### ЭтоМассив
```bsl
// Возвращает истина, если тип параметра Массив
//
// Возвращаемое значение:
// булево
```
#### Очистить
```bsl
// Процедура очищает, Значение параметра, для типа Массив
//
```
#### ЗначениеВСтроку
```bsl
// Возвращает строковое представление значения параметра
//
// Возвращаемое значение:
// строка
```
#### ПолучитьОбязательностьВвода
```bsl
// Возвращает истина, если данный параметр обязателен для указания
//
// Возвращаемое значение:
// булево
```
#### УстановитьЗначение
```bsl
// Процедура устанавливает значение параметра из входящего значения
// приводить к необходимому типу
//
// Параметры:
// ВходящееЗначение - строка - полученная строка при парсинге строки использования
```
#### ИзПеременнойОкружения
```bsl
// Процедура устанавливает значение параметра из переменной окружения
//
```
#### Текучие функции
##### ВОкружении
```bsl
// Функция устанавливает переменную окружения для параметра команды
// возвращает текущий параметр команды
//
// Параметры:
// СтрокаПеременнаяОкружения - строка - имя переменной окружения, откуда получать значение
// допустимо использование нескольких переменных окружения через пробел
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```
##### СкрытьВСправке
```bsl
// Функция устанавливает признак скрытости значения по умолчанию в справке
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```
##### ПоУмолчанию
```bsl
// Функция устанавливает значение по умолчанию
// возвращает текущий параметр команды
//
// Параметры:
// ВходящееЗначение - произвольный - значение параметра по умолчанию
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```
##### Флаговый
```bsl
// Функция устанавливает тип параметра "Булево"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
```
##### Флаг
```bsl
// Функция устанавливает тип параметра "Булево"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
```
##### ТБулево
```bsl
// Функция устанавливает тип параметра "Булево"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
```
##### ТДата
```bsl
// Функция устанавливает тип параметра "Дата"
// возвращает текущий параметр команды
//
// Параметры:
// ФорматДаты - Строка - формат даты, при приведении к дате из строки параметра по умолчанию (yyyy-MM-dd_HH:mm:ss)
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
```
##### ТЧисло
```bsl
// Функция устанавливает тип параметра "Число"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
```
##### ТСтрока
```bsl
// Функция устанавливает тип параметра "Строка"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
```
##### ТМассивДат
```bsl
// Функция устанавливает тип параметра "Массив" элементы "Дата"
// возвращает текущий параметр команды
//
// Параметры:
// ФорматДаты - Строка - формат даты, при приведении к дате из строки параметра по умолчанию (yyyy-MM-dd_HH:mm:ss)
// ВходящийРазделительМассива - символ - используется для разделения параметров при парсинге строки
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```
##### ТМассивЧисел
```bsl
// Функция устанавливает тип параметра "Массив" элементы "Число"
// возвращает текущий параметр команды
//
// Параметры:
// ВходящийРазделительМассива - символ - используется для разделения параметров при парсинге строки
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```
##### ТМассивСтрок
```bsl
// Функция устанавливает тип параметра "Массив" элементы "Строки"
// возвращает текущий параметр команды
//
// Параметры:
// ВходящийРазделительМассива - символ - используется для разделения параметров при парсинге строки
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```
##### ТМассивБулево
```bsl
// Функция устанавливает тип параметра "Массив" элементы "Булево"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```
##### ТПеречисление
```bsl
// Функция устанавливает тип параметра "Перечисление"
// возвращает текущий параметр команды
//
// Параметры:
// ДоступныеПеречисления - Соответсвие
// Ключ - Строка
// Значение - Структура ("Наименование, Значение, ДополнительнаяСправка")
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
```
##### Перечисление
```bsl
// Функция устанавливает произвольный тип параметра
// возвращает текущий параметр команды
//
// Параметры:
// НаименованиеПеречисления - строка - пользовательное значение перечисления
// ЗначениеПеречисления - произвольный - системное значение перечисления
// ДополнительнаяСправкаПеречисления - строка - дополнительная строка для справки
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
//
```
##### Описание
```bsl
// Функция устанавливает описание параметра для справки
// возвращает текущий параметр команды
//
// Параметры:
// НовыеОписание - строка - строка с новым описанием, отличным от переданного в момент создания
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```
##### ПодробноеОписание
```bsl
// Функция устанавливает подробное описание параметра для справки
// возвращает текущий параметр команды
//
// Параметры:
// ВходящееПодробноеОписание - строка - строка с новым описанием, отличным от переданного в момент создания
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
//
```
##### Псевдоним
```bsl
// Функция устанавливает дополнительный синоним/псевдоним параметра для справки
// возвращает текущий параметр команды
//
// Параметры:
// СтрокаПсевдонима - строка - строка с новым псевдонимом, отличным от переданного в момент создания
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```
##### Обязательный
```bsl
// Функция устанавливает признак обязательности указания данного параметра
// возвращает текущий параметр команды
//
// Параметры:
// Признак - булево - признак обязательности указания данного параметра (по умолчанию Истина)
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```
##### ВФайле
```bsl
// (ЗАГОТОВКА) Функция устанавливает путь и место в файле при получении настроек
// возвращает текущий параметр команды
//
// Параметры:
// ПутьКФайлу - строка - путь к файлу для чтения
// МестоВФайле - строка - путь в файле, в формате "general.force"
//
// Возвращаемое значение:
// ЭтотОбъект - класс ПараметрКоманд
```
##### ПроизвольныйТип
```bsl
// Функция устанавливает произвольный тип параметра
// возвращает текущий параметр команды
//
// Параметры:
// ВходящийКлассЗначенияПараметра - класс - Произвольный класс, реализующий ряд обязательных функций
// ВходящийТипПараметра - тип - тип значения параметра
// ВходящийТипЭлементаПараметра - Тип - тип элементов значения параметра, если тип Массив
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
```

View File

View File

@@ -0,0 +1,25 @@
# language: ru
Функционал: Создание проекта
Как разработчик
Я хочу запускать приложение
Контекст:
Дано Я очищаю параметры команды "oscript" в контексте
Сценарий: Запуск приложения без параметров
Когда Я выполняю команду "oscript" с параметрами "<КаталогПроекта>/tests/fixtures/ТестовоеПриложение.os"
И я вижу в консоли вывод
"""
Приложение: my-tests
"""
И Код возврата команды "oscript" равен 1
Сценарий: Получение версии приложения
Когда Я выполняю команду "oscript" с параметрами "<КаталогПроекта>/tests/fixtures/ТестовоеПриложение.os -v"
И я вижу в консоли вывод
"""
0.1.0
"""
И Код возврата команды "oscript" равен 0

28
lib/cli/packagedef Normal file
View File

@@ -0,0 +1,28 @@
////////////////////////////////////////////////////////////
// Описание пакета для сборки и установки
// Полную документацию см. на hub.oscript.io/packaging
//
Описание.Имя("cli")
.Версия("0.11.0")
.Автор("Khorev Aleksey")
.АдресАвтора("khorevaa@gmail.com")
.Описание("Данный пакет облегчает создание консольных приложений на Oscript")
.ВерсияСреды("1.8.3")
.ВключитьФайл("src")
.ВключитьФайл("docs")
//.ВключитьФайл("tests")
//.ВключитьФайл("package-loader.os")
//.ВключитьФайл("packagedef")
.ЗависитОт("logos", "1.1.1")
.ЗависитОт("delegate", "0.2.0")
.ЗависитОт("reflector", "0.5.1")
.ЗависитОт("fluent", "0.6.0")
.ЗависитОт("datetime", "0.1.0")
//.ЗависитОт("asserts")
//.ЗависитОт("1bdd") // Необходимо установил для тестирования
//.ЗависитОт("1testrunner") // Необходимо установил для тестирования
.ОпределяетКласс("КонсольноеПриложение", "src/core/Классы/КонсольноеПриложение.os")
.ОпределяетКласс("КомандаПриложения", "src/core/Классы/КомандаПриложения.os")
.ОпределяетКласс("ПараметрКоманды", "src/core/Классы/ПараметрКоманды.os")
;

View File

@@ -0,0 +1,18 @@
# must be unique in a given SonarQube instance
sonar.projectKey=cli
# sonar.organization=sonar-opensource-add
# this is the name displayed in the SonarQube UI
sonar.projectName=Command Line Interface for OScript
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# Since SonarQube 4.2, this property is optional if sonar.modules is set.
# If not set, SonarQube starts looking for source code from the directory containing
# the sonar-project.properties file.
sonar.sources=./src
# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
sonar.coverageReportPaths=coverage/genericCoverage.xml

22
lib/cli/sonar-qube.sh Normal file
View File

@@ -0,0 +1,22 @@
temp=`cat packagedef | grep ".Версия(" | sed 's|[^"]*"||' | sed -r 's/".+//'`
version=${temp##*|}
if [ "$TRAVIS_SECURE_ENV_VARS" == "true" ]; then
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
sonar-scanner \
-Dsonar.host.url=https://sonar.silverbulleters.org \
-Dsonar.analysis.mode=issues \
-Dsonar.github.pullRequest=$TRAVIS_PULL_REQUEST \
-Dsonar.github.repository=$TRAVIS_REPO_SLUG \
-Dsonar.github.oauth=$GITHUB_OAUTH_TOKEN \
-Dsonar.login=$SONAR_TOKEN \
-Dsonar.scanner.skip=false
elif [ "$TRAVIS_BRANCH" == "develop" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
sonar-scanner \
-Dsonar.host.url=https://sonar.oscript.ru \
-Dsonar.login=$SONAR_TOKEN \
-Dsonar.projectVersion=$version\
-Dsonar.scanner.skip=false
fi
fi

View File

@@ -0,0 +1,243 @@
#Использовать logos
Перем СтрокаАнализа;
Перем МассивТокенов;
Перем ОшибкаЧтения;
Перем ПодробноеОписаниеОшибки;
Перем Лог;
Процедура ПриСозданииОбъекта(Знач ВходящаяСтрока)
СтрокаАнализа = ВходящаяСтрока;
МассивТокенов = Новый Массив;
ОшибкаЧтения = "";
ПодробноеОписаниеОшибки = Новый Структура;
КонецПроцедуры
// Выполняет чтение строки по токенам и возвращает текущий класс
//
// Возвращаемое значение:
// Лексер - ссылка на текущий класс <Лексер>
//
Функция Прочитать() Экспорт
МассивТокенов.Очистить();
ПрочитатьТокены();
Возврат ЭтотОБъект;
КонецФункции
// Возвращает массив токенов
//
// Возвращаемое значение:
// массив - массив токенов после чтения строки
//
Функция ПолучитьТокены() Экспорт
Если ЕстьОшибка() Тогда
Возврат Новый Массив;
КонецЕсли;
Возврат МассивТокенов;
КонецФункции
// Выводит ошибку чтения строки
//
Процедура ВывестиИнформациюОбОшибке() Экспорт
Сообщить("Ошибка разбора строки: " + ОшибкаЧтения);
КонецПроцедуры
// Возвращает описание ошибки чтения строки
//
// Возвращаемое значение:
// строка - подробное описание ошибки чтения строки
//
Функция ПолучитьИнформациюОбОшибке() Экспорт
Возврат ОшибкаЧтения;
КонецФункции
// Проверяет наличие ошибки чтения строки
//
// Возвращаемое значение:
// булево - Истина, если есть ошибка чтения
//
Функция ЕстьОшибка() Экспорт
Возврат Не ПустаяСтрока(ОшибкаЧтения);
КонецФункции
Процедура ПрочитатьТокены()
МассивТокенов.Очистить();
Чтение = Новый ЧтениеСтроки(СтрокаАнализа);
Пока Чтение.Читать() Цикл
ТекущийСимвол = Чтение.ТекущийСимвол();
ТекущийИндекс = Чтение.ТекущийИндекс();
Лог.Отладка("Текущий символ: %1", ТекущийСимвол);
Лог.Отладка("Текущий индекс: %1", ТекущийИндекс);
Если Чтение.ЭтоСимвол(" ")
ИЛИ Чтение.ЭтоСимвол(Символы.ПС) Тогда
Продолжить;
ИначеЕсли Чтение.ЭтоСимвол("[") Тогда
МассивТокенов.Добавить(НовыйТокен(ТипыТокенов().TTOpenSq, ТекущийСимвол, ТекущийИндекс));
ИначеЕсли Чтение.ЭтоСимвол("]") Тогда
МассивТокенов.Добавить(НовыйТокен(ТипыТокенов().TTCloseSq, ТекущийСимвол, ТекущийИндекс));
ИначеЕсли Чтение.ЭтоСимвол("(") Тогда
МассивТокенов.Добавить(НовыйТокен(ТипыТокенов().TTOpenPar, ТекущийСимвол, ТекущийИндекс));
ИначеЕсли Чтение.ЭтоСимвол(")") Тогда
МассивТокенов.Добавить(НовыйТокен(ТипыТокенов().TTClosePar, ТекущийСимвол, ТекущийИндекс));
ИначеЕсли Чтение.ЭтоСимвол("|") Тогда
МассивТокенов.Добавить(НовыйТокен(ТипыТокенов().TTChoice, ТекущийСимвол, ТекущийИндекс));
ИначеЕсли Чтение.ЭтоСимвол(".") Тогда
ДополнительнаяДлинаТроеточия = 2;
Троеточие = Чтение.ВСтроку(ТекущийИндекс, ТекущийИндекс + ДополнительнаяДлинаТроеточия);
Если Не Троеточие = "..." Тогда
ОшибкаЧтения = "Ошибка в строке Спек, неправильно использованы символы <...>, должно быть 3";
Прервать;
КонецЕсли;
МассивТокенов.Добавить(НовыйТокен(ТипыТокенов().TTRep, Троеточие, ТекущийИндекс));
Чтение.ЧитатьНа(ДополнительнаяДлинаТроеточия);
ИначеЕсли Чтение.ЭтоСимвол("-") Тогда
СтартоваяПозиция = ТекущийИндекс;
Если Не Чтение.Читать() Тогда
ОшибкаЧтения = "Ошибка в строке Спек, не указано имя опции";
Прервать;
КонецЕсли;
Если Чтение.ЭтоБуква() Тогда
Чтение.ЧитатьДо("ПродолжитьЧтение = ЭтоБуква();");
ТипТокена = ТипыТокенов().TTShortOpt;
НазваниеТокена = Чтение.ВСтроку(СтартоваяПозиция, Чтение.ТекущийИндекс());
ДлинаИмениТокена = 2;
Если СтрДлина(НазваниеТокена) > ДлинаИмениТокена Тогда
ТипТокена = ТипыТокенов().TTOptSeq;
НазваниеТокена = Сред(НазваниеТокена, 1);
КонецЕсли;
МассивТокенов.Добавить(НовыйТокен(ТипТокена, НазваниеТокена, СтартоваяПозиция));
Если НЕ Чтение.КонецСтроки()
И Чтение.ВЧтениеСтрокиС(Чтение.ТекущийИндекс() + 1).ЭтоСимвол("-") Тогда
ОшибкаЧтения = "Не правильный синтаксис. Короткой опции";
Прервать;
КонецЕсли;
ИначеЕсли Чтение.ЭтоСимвол("-") Тогда
Если Чтение.КонецСтроки()
ИЛИ Чтение.СледующийСимволЭто(" ") Тогда
МассивТокенов.Добавить(НовыйТокен(ТипыТокенов().TTDoubleDash, "--", СтартоваяПозиция));
Продолжить;
КонецЕсли;
Чтение.ЧитатьДо("ПродолжитьЧтение = ЭтоБуква() ИЛИ ЭтоЧисло() ИЛИ ЭтоСимвол(""_"") ИЛИ ЭтоСимвол(""-"");");
НазваниеТокена = Чтение.ВСтроку(СтартоваяПозиция, Чтение.ТекущийИндекс());
ДлинаКороткойОпции = 2;
Если СтрДлина(НазваниеТокена) = ДлинаКороткойОпции Тогда
ОшибкаЧтения = "Не правильный синтаксис. Короткой опции";
Прервать;
КонецЕсли;
МассивТокенов.Добавить(НовыйТокен(ТипыТокенов().TTLongOpt, НазваниеТокена, СтартоваяПозиция));
КонецЕсли;
ИначеЕсли Чтение.ЭтоСимвол("=") Тогда
СтартоваяПозиция = ТекущийИндекс;
Если Не Чтение.СледующийСимволЭто("<") Тогда
ОшибкаЧтения = "Отсутствует начало описания опции '=<'";
Прервать;
КонецЕсли;
Закрыто = Чтение.ЧитатьДоСимвола(">");
Если Не Закрыто Тогда
ОшибкаЧтения = "Не закрытое описание опции";
Прервать;
КонецЕсли;
МинимальнаяДлинаОписанияОпции = 2;
Если Чтение.ТекущийИндекс() - СтартоваяПозиция = МинимальнаяДлинаОписанияОпции Тогда
ОшибкаЧтения = "Отсутствует описание опции";
Прервать;
КонецЕсли;
Чтение.Читать();
НазваниеТокена = Чтение.ВСтроку(СтартоваяПозиция, Чтение.ТекущийИндекс());
МассивТокенов.Добавить(НовыйТокен(ТипыТокенов().TTOptValue, НазваниеТокена, СтартоваяПозиция));
Иначе
Лог.Отладка("Это аргумент: %1", Чтение.ЭтоБольшаяБуква());
Если Чтение.ЭтоБольшаяБуква() Тогда
СтартоваяПозиция = ТекущийИндекс;
Чтение.ЧитатьДо("ПродолжитьЧтение = ЭтоБольшаяБуква() ИЛИ ЭтоЧисло() ИЛИ ЭтоСимвол(""_"");");
НазваниеТокена = Чтение.ВСтроку(СтартоваяПозиция, Чтение.ТекущийИндекс());
ТипТокена = ТипыТокенов().TTArg;
Если НазваниеТокена = "OPTIONS"
ИЛИ НазваниеТокена = "ОПЦИИ" Тогда
ТипТокена = ТипыТокенов().TTOptions;
КонецЕсли;
МассивТокенов.Добавить(НовыйТокен(ТипТокена, НазваниеТокена, СтартоваяПозиция));
Иначе
ОшибкаЧтения = СтрШаблон("Неизвестная ошибка! Индекс в строке: %1, символ: %2 ",
Чтение.ТекущийИндекс(),
Чтение.ТекущийСимвол());
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Возвращает возможные типы токенов
//
// Возвращаемое значение:
// Структура - структура данных вида:
// * Ключ - Имя токена
// * Значение - представление токена
//
Функция ТипыТокенов()
Возврат Токены.ТипыТокенов();
КонецФункции
Функция НовыйТокен(ТипТокена, Значение, Позиция)
Возврат Токены.НовыйТокен(ТипТокена, Значение, Позиция);
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_lexer");

View File

@@ -0,0 +1,60 @@
// Возвращает возможные типы токенов
//
// Возвращаемое значение:
// Структура - структура данных вида:
// * Ключ - Имя токена
// * Значение - представление токена
//
Функция ТипыТокенов() Экспорт
Типы = Новый Структура;
Типы.Вставить("TTArg", "Arg");
Типы.Вставить("TTOpenPar", "OpenPar");
Типы.Вставить("TTClosePar", "ClosePar");
Типы.Вставить("TTOpenSq", "TTOpenSq");
Типы.Вставить("TTCloseSq", "CloseSq");
Типы.Вставить("TTChoice", "Choice");
Типы.Вставить("TTOptions", "Options");
Типы.Вставить("TTRep", "Rep");
Типы.Вставить("TTShortOpt", "ShortOpt");
Типы.Вставить("TTLongOpt", "LongOpt");
Типы.Вставить("TTOptSeq", "OptSeq");
Типы.Вставить("TTOptValue", "OptValue");
Типы.Вставить("TTDoubleDash", "DblDash");
Возврат Типы;
КонецФункции
// Создает структура описания токена
//
// Параметры:
// ТипТокена - Строка - тип токена
// Значение - Строка - значение токена
// Позиция - Число - текущая позиция в строке
//
// Возвращаемое значение:
// Структура - структура описания токена
// * ТипТокена - Строка - тип токена
// * Значение - Строка - значение токена
// * Позиция - Число - текущая позиция в строке
//
Функция НовыйТокен(ТипТокена, Значение, Позиция) Экспорт
Возврат Новый Структура("Тип, Значение, Позиция", ТипТокена, Значение, Позиция);
КонецФункции
// Выводит данные по структуре описанию токена
//
// Параметры:
// Токен - Структура - структура описания токена
// * ТипТокена - Строка - тип токена
// * Значение - Строка - значение токена
// * Позиция - Число - текущая позиция в строке
//
Процедура СообщитьТокен(Токен) Экспорт
Сообщить(СтрШаблон("Тип: %1
|Значение: %2
|Пизиция: %3", Токен.Тип, Токен.Значение, Токен.Позиция));
КонецПроцедуры

View File

@@ -0,0 +1,92 @@
#Использовать logos
// Ссылка на класс аргумента
Перем Аргумент Экспорт;
Перем Лог;
Процедура ПриСозданииОбъекта(КлассОпции)
Аргумент = КлассОпции;
КонецПроцедуры
// Выполняет поиск аргумента в массиве входящих аргументов
//
// Параметры:
// ВходящиеАргументы - массив - входящие аргументы приложения
// КонтекстПоиска - Объект - класс "КонтекстПарсера"
//
// Возвращаемое значение:
// Структура - структура описания токена
// * РезультатПоиска - булево - признак успешного поиска
// * Аргументы - Массив - массив оставшихся аргументов после поиска
//
Функция Поиск(Знач ВходящиеАргументы, КонтекстПоиска) Экспорт
Аргументы = Новый Массив;
Для каждого Арг Из ВходящиеАргументы Цикл
Аргументы.Добавить(Арг);
КонецЦикла;
Результат = Новый Структура("РезультатПоиска, Аргументы", Аргумент.УстановленаИзПеременнойОкружения, Аргументы);
Лог.Отладка(" АргументыПарсера:
|УстановленаИзПеременнойОкружения <%1>
|УстановленаПользователем <%2>", Аргумент.УстановленаИзПеременнойОкружения, Аргумент.УстановленаПользователем);
Если Аргументы.Количество() = 0 Тогда
Если Аргумент.УстановленаИзПеременнойОкружения
И КонтекстПоиска.НеВключенныеАргументы[Аргумент] = Истина Тогда
Результат.РезультатПоиска = Ложь;
Иначе
КонтекстПоиска.НеВключенныеАргументы.Вставить(Аргумент, Истина);
КонецЕсли;
Возврат Результат;
КонецЕсли;
Если (НЕ КонтекстПоиска.СбросОпций И
СтрНачинаетсяС(Аргументы[0], "-")
И НЕ Аргументы[0] = "-")
ИЛИ ПустаяСтрока(Аргументы[0])
Тогда
Возврат Результат;
КонецЕсли;
АргументКонтекст = КонтекстПоиска.Аргументы[Аргумент];
Если АргументКонтекст = Неопределено Тогда
АргументКонтекст = Новый Массив;
КонецЕсли;
АргументКонтекст.Добавить(Аргументы[0]);
КонтекстПоиска.Аргументы.Вставить(Аргумент, АргументКонтекст);
Результат.РезультатПоиска = Истина;
Аргументы.Удалить(0);
Результат.Аргументы = Аргументы;
Возврат Результат;
КонецФункции
// Возвращает приоритет текущего парсера
//
// Возвращаемое значение:
// число - приоритет текущего парсера
//
Функция Приоритет() Экспорт
Возврат 8;
КонецФункции
// Возвращает имя текущего парсера
//
// Возвращаемое значение:
// строка - имя текущего парсера, на основании имени аргумента
//
Функция ВСтроку() Экспорт
Возврат Аргумент.Имя;
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_class_arg");

View File

@@ -0,0 +1,139 @@
#Использовать logos
Перем Опции Экспорт; // Массив - элементы ПараметрКоманды - Ссылка на класс опции
Перем ОпцииИндекс Экспорт; // Соответствие - Ссылка на текущий индекс опций
Перем Лог;
Процедура ПриСозданииОбъекта(ВходящиеОпции, Индекс)
Опции = ВходящиеОпции;
Лог.Отладка("Тип входящей опции: %1", ТипЗнч(ВходящиеОпции));
ОпцииИндекс = Индекс;
КонецПроцедуры
// Выполняет поиск опций в массиве входящих аргументов
//
// Параметры:
// ВходящиеАргументы - массив - входящие аргументы приложения
// КонтекстПоиска - Объект - класс "КонтекстПарсера"
//
// Возвращаемое значение:
// Структура - структура описания токена
// * РезультатПоиска - булево - признак успешного поиска
// * Аргументы - Массив - массив оставшихся аргументов после поиска
//
Функция Поиск(Знач ВходящиеАргументы, КонтекстПоиска) Экспорт
Аргументы = Новый Массив;
Для каждого Арг Из ВходящиеАргументы Цикл
Аргументы.Добавить(Арг);
КонецЦикла;
Результат = Новый Структура("РезультатПоиска, Аргументы", Ложь, Аргументы);
РезультатПопыткиПоиска = ПопыткаПоиска(Аргументы, КонтекстПоиска);
Если НЕ РезультатПопыткиПоиска.РезультатПоиска Тогда
Возврат Результат;
КонецЕсли;
АргументыДляЦикла = РезультатПопыткиПоиска.Аргументы;
Пока Истина Цикл
РезультатПопыткиПоискаВЦикле = ПопыткаПоиска(АргументыДляЦикла, КонтекстПоиска);
Если НЕ РезультатПопыткиПоискаВЦикле.РезультатПоиска Тогда
Результат.РезультатПоиска = Истина;
Результат.Аргументы = РезультатПопыткиПоискаВЦикле.Аргументы;
Возврат Результат;
КонецЕсли;
АргументыДляЦикла = РезультатПопыткиПоискаВЦикле.Аргументы;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПопыткаПоиска(Знач Аргументы, КонтекстПоиска)
Результат = Новый Структура("РезультатПоиска, Аргументы", Ложь, Аргументы);
Если Аргументы.Количество() = 0
ИЛИ КонтекстПоиска.СбросОпций Тогда
Возврат Результат;
КонецЕсли;
Для каждого ОпцияПоиска Из Опции Цикл
Если Не КонтекстПоиска.НеВключенныеОпции[ОпцияПоиска.Значение] = Неопределено Тогда
Лог.Отладка("Исключен поиск опцию %1", ОпцияПоиска.Ключ.Имя);
Продолжить;
КонецЕсли;
Лог.Отладка("Ищу опцию %1", ОпцияПоиска.Ключ.Имя);
Лог.Отладка("Ищу опцию тип %1", ОпцияПоиска.Значение);
КлассПоиска = Новый ОпцияПарсера(ОпцияПоиска.Значение, ОпцииИндекс);
РезультатПоиска = КлассПоиска.Поиск(Аргументы, КонтекстПоиска);
Лог.Отладка("Длина аргументов <%1> ", Аргументы.Количество());
Лог.Отладка("Результат поиска опции %1 = <%2>", ОпцияПоиска.Ключ.Имя, РезультатПоиска.РезультатПоиска);
Лог.Отладка("Длина аргументов после поиска <%1> ", РезультатПоиска.Аргументы.Количество());
Если РезультатПоиска.РезультатПоиска Тогда
Если ОпцияПоиска.Значение.УстановленаИзПеременнойОкружения Тогда
КонтекстПоиска.НеВключенныеОпции.Вставить(ОпцияПоиска.Значение, Истина);
КонецЕсли;
Возврат Новый Структура("РезультатПоиска, Аргументы", Истина, РезультатПоиска.Аргументы);
КонецЕсли;
КонецЦикла;
Возврат Новый Структура("РезультатПоиска, Аргументы", Ложь, Аргументы);
КонецФункции
// Возвращает приоритет текущего парсера
//
// Возвращаемое значение:
// число - приоритет текущего парсера
//
Функция Приоритет() Экспорт
Возврат 2;
КонецФункции
// Возвращает имя текущего парсера
//
// Возвращаемое значение:
// строка - имя текущего парсера, на основании имени опции
//
Функция ВСтроку() Экспорт
Представление = "-";
ДлинаОпции = 2;
Для каждого Опция Из Опции Цикл
ИмяОпции = Опция.Ключ.Синонимы[0];
Если СтрНачинаетсяС(ИмяОпции, "-") Тогда
ИмяОпции = Сред(ИмяОпции, ДлинаОпции);
КонецЕсли;
Представление = Представление + ИмяОпции;
КонецЦикла;
Возврат Представление;
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_class_options");

View File

@@ -0,0 +1,72 @@
Перем Опции Экспорт; // Структура Ключ - Значение (Структура описание опции)
Перем Аргументы Экспорт; // Структура
Перем НеВключенныеОпции Экспорт; // Структура Ключ - Значение (Структура описание опции)
Перем НеВключенныеАргументы Экспорт; // Структура Ключ - Значение (Структура описание опции)
Перем СбросОпций Экспорт;
// Соединяет текущий контекст с входящим контекстом
//
// Параметры:
// ВходящийКонтекст - Объект - присоединяемый класс "КонтекстПарсеров"
//
Процедура ПрисоединитьКонтекст(Знач ВходящийКонтекст) Экспорт
ОбработатьОпции(ВходящийКонтекст.Опции);
ОбработатьАргументы(ВходящийКонтекст.Аргументы);
КонецПроцедуры
Процедура ОбработатьАргументы(Знач ВходящиеАргументы)
Для каждого ВходящийАргументы Из ВходящиеАргументы Цикл
Если ВходящийАргументы.Значение = Неопределено Тогда
Продолжить;
КонецЕсли;
АргументыКонтекст = Аргументы[ВходящийАргументы.Ключ];
Если АргументыКонтекст = Неопределено Тогда
АргументыКонтекст = Новый Массив;
КонецЕсли;
Для каждого ЭлементМассива Из ВходящийАргументы.Значение Цикл
АргументыКонтекст.Добавить(ЭлементМассива);
КонецЦикла;
Аргументы.Вставить(ВходящийАргументы.Ключ, АргументыКонтекст);
КонецЦикла;
КонецПроцедуры
Процедура ОбработатьОпции(Знач ВходящиеОпции)
Для каждого ВходящаяОпции Из ВходящиеОпции Цикл
Если ВходящаяОпции.Значение = Неопределено Тогда
Продолжить;
КонецЕсли;
ОпцииКонтекст = Опции[ВходящаяОпции.Ключ];
Если ОпцииКонтекст = Неопределено Тогда
ОпцииКонтекст = Новый Массив;
КонецЕсли;
Для каждого ЭлементМассива Из ВходящаяОпции.Значение Цикл
ОпцииКонтекст.Добавить(ЭлементМассива);
КонецЦикла;
Опции.Вставить(ВходящаяОпции.Ключ, ОпцииКонтекст);
КонецЦикла;
КонецПроцедуры
Опции = Новый Соответствие;
Аргументы = Новый Соответствие;
НеВключенныеОпции = Новый Соответствие;
НеВключенныеАргументы = Новый Соответствие;
СбросОпций = Ложь;

View File

@@ -0,0 +1,36 @@
// Выполняет поиск любого парсера в массиве входящих аргументов
//
// Параметры:
// Аргументы - массив - входящие аргументы приложения
// КонтекстПоиска - Объект - класс "КонтекстПарсера"
//
// Возвращаемое значение:
// Структура - структура описания токена
// * РезультатПоиска - булево - признак успешного поиска
// * Аргументы - Массив - массив оставшихся аргументов после поиска
//
Функция Поиск(Аргументы, КонтекстПоиска) Экспорт
Результат = Новый Структура("РезультатПоиска, Аргументы", Истина, Аргументы);
Возврат Результат;
КонецФункции
// Возвращает приоритет текущего парсера
//
// Возвращаемое значение:
// число - приоритет текущего парсера
//
Функция Приоритет() Экспорт
Возврат 10;
КонецФункции
// Возвращает имя текущего парсера
//
// Возвращаемое значение:
// строка - имя текущего парсера всегда "*"
//
Функция ВСтроку() Экспорт
Возврат "*";
КонецФункции

View File

@@ -0,0 +1,36 @@
// Выполняет поиск парсера в массиве входящих аргументов
//
// Параметры:
// Аргументы - массив - входящие аргументы приложения
// КонтекстПоиска - Объект - класс "КонтекстПарсера"
//
// Возвращаемое значение:
// Структура - структура описания токена
// * РезультатПоиска - булево - признак успешного поиска
// * Аргументы - Массив - массив оставшихся аргументов после поиска
//
Функция Поиск(Аргументы, КонтекстПоиска) Экспорт
Результат = Новый Структура("РезультатПоиска, Аргументы", Истина, Аргументы);
Возврат Результат;
КонецФункции
// Возвращает приоритет текущего парсера
//
// Возвращаемое значение:
// число - приоритет текущего парсера
//
Функция Приоритет() Экспорт
Возврат 9;
КонецФункции
// Возвращает имя текущего парсера
//
// Возвращаемое значение:
// строка - имя текущего парсера всегда "--"
//
Функция ВСтроку() Экспорт
Возврат "--";
КонецФункции

View File

@@ -0,0 +1,408 @@
#Использовать logos
Перем Опция Экспорт; // ПараметрКоманды - Ссылка на класс опции
Перем ОпцииИндекс Экспорт; // Соответствие - Ссылка на текущий индекс опций
Перем Лог;
Процедура ПриСозданииОбъекта(КлассОпции, Индекс)
Лог.Отладка("Создан парсер для опции %1", КлассОпции.Имя);
Опция = КлассОпции;
ОпцииИндекс = Индекс;
КонецПроцедуры
// Выполняет поиск парсера в массиве входящих аргументов
//
// Параметры:
// ВходящиеАргументы - массив - входящие аргументы приложения
// КонтекстПоиска - Объект - класс "КонтекстПарсера"
//
// Возвращаемое значение:
// Структура - структура описания токена
// * РезультатПоиска - булево - признак успешного поиска
// * Аргументы - Массив - массив оставшихся аргументов после поиска
//
Функция Поиск(Знач ВходящиеАргументы, КонтекстПоиска) Экспорт
Аргументы = Новый Массив;
Для каждого Арг Из ВходящиеАргументы Цикл
Аргументы.Добавить(Арг);
КонецЦикла;
Результат = Новый Структура("РезультатПоиска, Аргументы", Ложь, Аргументы);
Лог.Отладка("Начало поиска опции");
Лог.Отладка("Количество входящих аргументов %1", Аргументы.Количество());
Если Аргументы.Количество() = 0
ИЛИ КонтекстПоиска.СбросОпций Тогда
Лог.Отладка("Не найдено аргументов <%1> или СбросОпций <%2>", Аргументы.Количество(), КонтекстПоиска.СбросОпций );
Результат.РезультатПоиска = Опция.УстановленаИзПеременнойОкружения;
Возврат Результат;
КонецЕсли;
Индекс = 0;
Пока Индекс <= Аргументы.Вграница() Цикл
ТекущийАргумент = Аргументы[Индекс];
Если ТекущийАргумент = "-" Тогда
Индекс = Индекс + 1;
Продолжить;
ИначеЕсли ТекущийАргумент = "--" Тогда
Результат.РезультатПоиска = Опция.УстановленаИзПеременнойОкружения;
Возврат Результат;
ИначеЕсли СтрНачинаетсяС(ТекущийАргумент, "--") Тогда
РезультатПоискаДлиннойОпции = НайтиДлиннуюОпцию(Аргументы, Индекс, КонтекстПоиска);
Лог.Отладка("Длинная опция найдена: %1", РезультатПоискаДлиннойОпции.Найден);
Если РезультатПоискаДлиннойОпции.Найден Тогда
Результат.РезультатПоиска = Истина;
Результат.Аргументы = РезультатПоискаДлиннойОпции.Аргументы;
Возврат Результат;
КонецЕсли;
Если РезультатПоискаДлиннойОпции.ПрибавочныйИндекс = 0 Тогда
Возврат Новый Структура("РезультатПоиска, Аргументы", Опция.УстановленаИзПеременнойОкружения, Аргументы);
КонецЕсли;
Индекс = Индекс + РезультатПоискаДлиннойОпции.ПрибавочныйИндекс;
ИначеЕсли СтрНачинаетсяС(ТекущийАргумент, "-") Тогда
РезультатПоискаКороткойОпции = НайтиКороткуюОпцию(Аргументы, Индекс, КонтекстПоиска);
Лог.Отладка("Короткая опция найдена: %1", РезультатПоискаКороткойОпции.Найден);
Если РезультатПоискаКороткойОпции.Найден Тогда
Результат.РезультатПоиска = Истина;
Результат.Аргументы = РезультатПоискаКороткойОпции.Аргументы;
Возврат Результат;
КонецЕсли;
Если РезультатПоискаКороткойОпции.ПрибавочныйИндекс = 0 Тогда
Возврат Новый Структура("РезультатПоиска, Аргументы", Опция.УстановленаИзПеременнойОкружения, Аргументы);
КонецЕсли;
Индекс = Индекс + РезультатПоискаКороткойОпции.ПрибавочныйИндекс;
Иначе
Результат.РезультатПоиска = Опция.УстановленаИзПеременнойОкружения;
Возврат Результат;
КонецЕсли;
КонецЦикла;
Результат.РезультатПоиска = Опция.УстановленаИзПеременнойОкружения;
Возврат Результат;
КонецФункции
Функция НайтиКороткуюОпцию(Знач Аргументы, Индекс, КонтекстПоиска)
Лог.Отладка("Класс опции %1", ТипЗнч(Опция));
Лог.Отладка("Ищу короткую опцию %1", Опция.Имя);
ТекущийАргумент = Аргументы[Индекс];
Результат = Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 0, Аргументы);
Если СтрДлина(ТекущийАргумент) < 2 Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 0, Аргументы);
КонецЕсли;
Если Сред(ТекущийАргумент, 3, 1) = "=" Тогда
Имя = Лев(ТекущийАргумент, 2);
КлассОпции = ОпцииИндекс[Имя];
Если Не КлассОпции.имя = Опция.Имя Тогда
Результат.ПрибавочныйИндекс = 1;
Возврат Результат;
КонецЕсли;
Значение = Сред(ТекущийАргумент, 4);
Если ПустаяСтрока(СокрЛП(Значение)) Тогда
Возврат Результат;
КонецЕсли;
ОпцииКонтекст = КонтекстПоиска.Опции[Опция];
Если ОпцииКонтекст = Неопределено Тогда
ОпцииКонтекст = Новый Массив;
КонецЕсли;
ОпцииКонтекст.Добавить(Значение);
КонтекстПоиска.Опции.Вставить(Опция, ОпцииКонтекст);
Аргументы.Удалить(Индекс);
Результат.ПрибавочныйИндекс = 1;
Результат.Аргументы = Аргументы;
Результат.Найден = Истина;
Возврат Результат;
КонецЕсли;
ЧтениеСтроки = Новый ЧтениеСтроки(ТекущийАргумент);
ИщемОпцию = ЧтениеСтроки.ВЧтениеСтрокиС(1);
ИИ = 0;
Лог.Отладка("Строка опции: %1", ИщемОпцию.ВСтроку(ИИ));
Пока Не ПустаяСтрока(ИщемОпцию.ВСтрокуС(ИИ)) Цикл
ИмяОпции = ИщемОпцию.ВСтроку(ИИ, ИИ);
Лог.Отладка("ИмяОпции: %1", ИмяОпции);
КлассОпции = ОпцииИндекс["-" + ИмяОпции];
Лог.Отладка("КлассОпции: %1", Строка(КлассОпции));
Если КлассОпции = Неопределено Тогда
Лог.Отладка("Неопределенная опция: %1", Строка(ИмяОпции));
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 0, Аргументы);
КонецЕсли;
Лог.Отладка("КлассОпции.ТипОпции: %1 ", КлассОпции.ТипОпции);
Если КлассОпции.ТипОпции = Тип("Булево")
Или КлассОпции.ТипОпции = Тип("Массив") И КлассОпции.ТипЭлементаОпции = Тип("Булево") Тогда
Если Не КлассОпции.Имя = Опция.Имя Тогда
ИИ = ИИ + 1;
Лог.Отладка("Не нашли опцию %1, %2 <> %3", ИмяОпции, КлассОпции.Имя, Опция.Имя);
Продолжить;
КонецЕсли;
ОпцииКонтекст = КонтекстПоиска.Опции[Опция];
Если ОпцииКонтекст = Неопределено Тогда
ОпцииКонтекст = Новый Массив;
КонецЕсли;
ОпцииКонтекст.Добавить(Истина);
Лог.Отладка("Добавили.значение <%2> опции <%1> в контекст", Опция.Имя , Истина);
КонтекстПоиска.Опции.Вставить(Опция, ОпцииКонтекст);
Результат.Найден = Истина;
Лог.Отладка("Вычисление остаточного ими от <%1> до индекса <%2> после индекса <%3> ",
ИщемОпцию.ВСтроку(),
ИщемОпцию.ВСтрокуПо(ИИ - 1),
ИщемОпцию.ВСтрокуС(ИИ + 1));
ОстаточноеИмя = ИщемОпцию.ВСтрокуПо(ИИ - 1) + ИщемОпцию.ВСтрокуС(ИИ + 1);
Лог.Отладка("Остаточное имя <%1> опции ", ОстаточноеИмя );
Если ПустаяСтрока(ОстаточноеИмя) Тогда
Аргументы.Удалить(Индекс);
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Истина, 1, Аргументы);
КонецЕсли;
Аргументы[Индекс] = "-" + ОстаточноеИмя;
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Истина, 0, Аргументы);
КонецЕсли;
Значение = ИщемОпцию.ВСтрокуС(ИИ + 1);
Если ПустаяСтрока(Значение) Тогда
Если Аргументы.Вграница() - Индекс = 0 Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 0, Аргументы);
КонецЕсли;
Если Не КлассОпции.имя = Опция.Имя Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 2, Аргументы);
КонецЕсли;
Значение = Аргументы[Индекс + 1];
Лог.Отладка("Значение найденной опции равно <%1>", Значение );
Если СтрНачинаетсяС(Значение, "-") Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 0, Аргументы);
КонецЕсли;
ОпцииКонтекст = КонтекстПоиска.Опции[Опция];
Если ОпцииКонтекст = Неопределено Тогда
ОпцииКонтекст = Новый Массив;
КонецЕсли;
ОпцииКонтекст.Добавить(Значение);
КонтекстПоиска.Опции.Вставить(Опция, ОпцииКонтекст);
Лог.Отладка("Имя опции <%1> равно <%2> ", ИмяОпции, ИщемОпцию.ВСтроку());
Если СтрДлина(ИмяОпции) = СтрДлина(ИщемОпцию.ВСтроку()) Тогда
Аргументы.Удалить(Индекс);
Аргументы.Удалить(Индекс);
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Истина, 2, Аргументы);
КонецЕсли;
НовыйАргумент = СтрЗаменить(ИщемОпцию.ВСтроку(), ИмяОпции, "");
Аргументы[Индекс] = "-" + НовыйАргумент;
Аргументы.Удалить(Индекс + 1); // удаление значения,
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Истина, 1, Аргументы);
КонецЕсли;
Если Не КлассОпции.имя = Опция.Имя Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 1, Аргументы);
КонецЕсли;
ОпцииКонтекст = КонтекстПоиска.Опции[Опция];
Если ОпцииКонтекст = Неопределено Тогда
ОпцииКонтекст = Новый Массив;
КонецЕсли;
Лог.Отладка("Значение найденной опции равно <%1>", Значение);
ОпцииКонтекст.Добавить(Значение);
КонтекстПоиска.Опции.Вставить(Опция, ОпцииКонтекст);
ОстатокИмени = ИщемОпцию.ВСтрокуПо(ИИ - 1);
Лог.Отладка("Остаток имени <%1>", ОстатокИмени);
Если ПустаяСтрока(ОстатокИмени) Тогда
Аргументы.Удалить(Индекс); // удаление значения, т.к. индекс уже сдвинулся.
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Истина, 1, Аргументы);
КонецЕсли;
Аргументы[Индекс] = "-" + ОстатокИмени;
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Истина, 0, Аргументы);
КонецЦикла;
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 1, Аргументы);
КонецФункции
Функция НайтиДлиннуюОпцию(Знач Аргументы, Индекс, КонтекстПоиска)
Лог.Отладка("Класс опции %1", ТипЗнч(Опция));
Лог.Отладка("Ищу длинную опцию %1", Опция.Имя);
ТекущийАргумент = Аргументы[Индекс];
МассивСтрокаАргумента = СтрРазделить(ТекущийАргумент, "=");
ИмяОпции = МассивСтрокаАргумента[0];
Лог.Отладка("Определели имя длинной опции %1", ИмяОпции);
КлассОпции = ОпцииИндекс[ИмяОпции];
Лог.Отладка("Класс опции по имени %1", КлассОпции);
Если КлассОпции = Неопределено Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 0, Аргументы);
КонецЕсли;
Если МассивСтрокаАргумента.Количество() = 2 Тогда
Лог.Отладка("Строка содержит <=> второй элемент массива %1", МассивСтрокаАргумента[1]);
Если Не КлассОпции.имя = Опция.Имя Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 1, Аргументы);
КонецЕсли;
Значение = МассивСтрокаАргумента[1];
Если ПустаяСтрока(Значение) Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 0, Аргументы);
КонецЕсли;
ОпцииКонтекст = КонтекстПоиска.Опции[Опция];
Если ОпцииКонтекст = Неопределено Тогда
ОпцииКонтекст = Новый Массив;
КонецЕсли;
ОпцииКонтекст.Добавить(Значение);
Лог.Отладка("Значение длинной опции <%1>", Значение);
КонтекстПоиска.Опции.Вставить(Опция, ОпцииКонтекст);
Аргументы.Удалить(Индекс);
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Истина, 1, Аргументы);
ИначеЕсли КлассОпции.ТипОпции = Тип("Булево")
Или КлассОпции.ТипОпции = Тип("Массив") И КлассОпции.ТипЭлементаОпции = Тип("Булево") Тогда
Если Не КлассОпции.имя = Опция.Имя Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 1, Аргументы);
КонецЕсли;
ОпцииКонтекст = КонтекстПоиска.Опции[Опция];
Если ОпцииКонтекст = Неопределено Тогда
ОпцииКонтекст = Новый Массив;
КонецЕсли;
ОпцииКонтекст.Добавить(Истина);
КонтекстПоиска.Опции.Вставить(Опция, ОпцииКонтекст);
Аргументы.Удалить(Индекс);
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Истина, 1, Аргументы);
Иначе
Лог.Отладка("Разница между <%1> и %2 меньше 2", Аргументы.Вграница(), Индекс);
Если Аргументы.Количество() - Индекс < 2 Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 0, Аргументы);
КонецЕсли;
Если Не КлассОпции.имя = Опция.Имя Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 2, Аргументы);
КонецЕсли;
Значение = Аргументы[Индекс + 1];
Если СтрНачинаетсяС(Значение, "-") Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 0, Аргументы);
КонецЕсли;
Лог.Отладка("Значение длинной опции <%1>", Значение);
Если ПустаяСтрока(Значение) Тогда
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Ложь, 0, Аргументы);
КонецЕсли;
ОпцииКонтекст = КонтекстПоиска.Опции[Опция];
Если ОпцииКонтекст = Неопределено Тогда
ОпцииКонтекст = Новый Массив;
КонецЕсли;
ОпцииКонтекст.Добавить(Значение);
КонтекстПоиска.Опции.Вставить(Опция, ОпцииКонтекст);
Аргументы.Удалить(Индекс);
Аргументы.Удалить(Индекс); // удаление значения, т.к. индекс уже сдвинулся.
Возврат Новый Структура("Найден, ПрибавочныйИндекс, Аргументы", Истина, 1, Аргументы);
КонецЕсли;
КонецФункции
// Возвращает приоритет текущего парсера
//
// Возвращаемое значение:
// число - приоритет текущего парсера
//
Функция Приоритет() Экспорт
Возврат 1;
КонецФункции
// Возвращает имя текущего парсера
//
// Возвращаемое значение:
// строка - имя текущего парсера всегда начинается с "-" и добавляется имя опции
//
Функция ВСтроку() Экспорт
Возврат "-" + Опция.Имя;
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_class_opt");

View File

@@ -0,0 +1,345 @@
#Использовать "../../lexer"
Перем Спек;
Перем Опции; // Структура Ключ - Значение (Структура описание опции)
Перем Аргументы; // Структура
Перем ОпцииИндекс; // Соответствие
Перем АргументыИндекс; // Соответствие
Перем ТокеныПарсера;
Перем ТекущаяПозиция;
Перем НайденныйТокен;
Перем СкинутьОпции;
Перем ТипыТокенов;
Перем ОбработчикВыборкиПути;
Перем Лог;
Процедура ПриСозданииОбъекта(Знач ТокеныСпек, Знач ПараметрыПарсера)
ТокеныПарсера = ТокеныСпек;
Опции = ПараметрыПарсера.Опции;
Аргументы = ПараметрыПарсера.Аргументы;
ОпцииИндекс = ПараметрыПарсера.ОпцииИндекс;
АргументыИндекс = ПараметрыПарсера.АргументыИндекс;
Спек = ПараметрыПарсера.Спек;
Лог.Отладка("Спек %1", Спек);
Лог.Отладка("Количество опций: %1", Опции.Количество());
ТекущаяПозиция = 0;
СкинутьОпции = Ложь;
ТипыТокенов = Токены.ТипыТокенов();
ОбработчикВыборкиПути = Новый ВыборСовпадений();
КонецПроцедуры
// Выполняет чтение аргументов строки
//
// Возвращаемое значение:
// Объект - ссылка на класс "Совпадение"
//
Функция Прочитать() Экспорт
Лог.Отладка("Начинаю чтение спека %1", Спек);
Лог.Отладка("Количество токенов %1", ТокеныПарсера.Количество());
Результат = ПрочитатьРекурсивно(Ложь);
Если Не КонецТокенов() Тогда
ВызватьИсключение "Косяк ппц что делать";
КонецЕсли;
НачальноеСостояние = Результат.НачальноеСостояние;
КонечноеСостояние = Результат.КонечноеСостояние;
КонечноеСостояние.Завершено = Истина;
НачальноеСостояние.Подготовить();
Возврат НачальноеСостояние;
КонецФункции
Функция ПрочитатьРекурсивно(Требуется)
Лог.Отладка("Рекурсивное чтение %1", Требуется);
НачальноеСостояние = ОбработчикВыборкиПути.НовоеСостояние();
КонечноеСостояние = НачальноеСостояние;
Если Требуется Тогда
Результат = ТокенВыбора();
Для каждого Соединение Из Результат.НачальноеСостояние.МассивСоединений Цикл
КонечноеСостояние.Т(Соединение.Парсер, Соединение.СледующееСостояние);
КонецЦикла;
КонечноеСостояние = Результат.КонечноеСостояние;
КонецЕсли;
Пока МогуПрочитать() Цикл
РезультатВЦикле = ТокенВыбора();
Для каждого Соединение Из РезультатВЦикле.НачальноеСостояние.МассивСоединений Цикл
КонечноеСостояние.Т(Соединение.Парсер, Соединение.СледующееСостояние);
КонецЦикла;
КонечноеСостояние = РезультатВЦикле.КонечноеСостояние;
КонецЦикла;
Возврат Новый Структура("НачальноеСостояние, КонечноеСостояние", НачальноеСостояние, КонечноеСостояние);
КонецФункции
Функция ЧтениеДалее()
Лог.Отладка("Вызов <ЧтениеДалее>");
НачальноеСостояние = ОбработчикВыборкиПути.НовоеСостояние();
КонечноеСостояние = Неопределено;
Если КонецТокенов() Тогда
ВызватьИсключение "Не правильная строка использования";
ИначеЕсли НашлиТокен(ТипыТокенов.TTArg) Тогда
Имя = НайденныйТокен.Значение;
КлассОпции = АргументыИндекс[Имя];
Если КлассОпции = Неопределено Тогда
Назад();
ВызватьИсключение "Нашли не объявленный аргумент";
КонецЕсли;
КонечноеСостояние = НачальноеСостояние.Т(Новый АргументыПарсера(КлассОпции), ОбработчикВыборкиПути.НовоеСостояние());
ИначеЕсли НашлиТокен(ТипыТокенов.TTOptions) Тогда
Если СкинутьОпции Тогда
Назад();
Сообщить("нет опций после --");
ВызватьИсключение "нет опций после --";
КонецЕсли;
КонечноеСостояние = ОбработчикВыборкиПути.НовоеСостояние();
НачальноеСостояние.Т(Новый ВсеОпцииПарсера(Опции, ОпцииИндекс), КонечноеСостояние);
ИначеЕсли НашлиТокен(ТипыТокенов.TTShortOpt)
ИЛИ НашлиТокен(ТипыТокенов.TTLongOpt) Тогда
Лог.Отладка("Обрабатываю токен: %1", НайденныйТокен.Тип);
Если СкинутьОпции Тогда
Назад();
Сообщить("нет опций после --");
ВызватьИсключение "нет опций после --";
КонецЕсли;
Имя = НайденныйТокен.Значение;
КлассОпции = ОпцииИндекс[Имя];
Лог.Отладка(" >> Имя токен: %1", НайденныйТокен.Значение);
Лог.Отладка(" >> класс опции: %1", КлассОпции.Имя);
Если КлассОпции = Неопределено Тогда
Назад();
Сообщить("Нашли не объявленную опцию");
ВызватьИсключение "Ошибка";
КонецЕсли;
КонечноеСостояние = НачальноеСостояние.Т(Новый ОпцияПарсера(КлассОпции, ОпцииИндекс),
ОбработчикВыборкиПути.НовоеСостояние());
Лог.Отладка(" >> НачальноеСостояние.МассивСоединений: %1", НачальноеСостояние.МассивСоединений.Количество());
НашлиТокен(ТипыТокенов.TTOptValue); // Пропуск значение после "="
ИначеЕсли НашлиТокен(ТипыТокенов.TTOptSeq) Тогда
Если СкинутьОпции Тогда
Назад();
Сообщить("нет опций после --");
ВызватьИсключение "нет опций после --";
КонецЕсли;
КонечноеСостояние = ОбработчикВыборкиПути.НовоеСостояние();
ДоступныеОпции = НайденныйТокен.Значение;
Если СтрНачинаетсяС(ДоступныеОпции, "-") Тогда
ДоступныеОпции = Прав(ДоступныеОпции, СтрДлина(ДоступныеОпции) - 1);
КонецЕсли;
МассивДоступныхОпций = Новый Соответствие;
ДлинаОпций = СтрДлина(ДоступныеОпции);
Для ИИ = 1 По ДлинаОпций Цикл
ИмяОпции = Сред(ДоступныеОпции, ИИ, 1);
КлассОпции = ОпцииИндекс["-" + ИмяОпции];
Если КлассОпции = Неопределено Тогда
Назад();
Сообщить("Нашли не объявленную опцию");
ВызватьИсключение "Ошибка Нашли не объявленную опцию";
КонецЕсли;
МассивДоступныхОпций.Вставить(КлассОпции, КлассОпции);
КонецЦикла;
НачальноеСостояние.Т(Новый ВсеОпцииПарсера(МассивДоступныхОпций, ОпцииИндекс), КонечноеСостояние);
ИначеЕсли НашлиТокен(ТипыТокенов.TTOpenPar) Тогда
РезультатЧтения = ПрочитатьРекурсивно(Истина);
НачальноеСостояние = РезультатЧтения.НачальноеСостояние;
КонечноеСостояние = РезультатЧтения.КонечноеСостояние;
ОжидаюТокен(ТипыТокенов.TTClosePar);
ИначеЕсли НашлиТокен(ТипыТокенов.TTOpenSq) Тогда
РезультатЧтения = ПрочитатьРекурсивно(Истина);
НачальноеСостояние = РезультатЧтения.НачальноеСостояние;
КонечноеСостояние = РезультатЧтения.КонечноеСостояние;
НачальноеСостояние.Т(Новый ЛюбойСимвол(), КонечноеСостояние);
ОжидаюТокен(ТипыТокенов.TTCloseSq);
ИначеЕсли НашлиТокен(ТипыТокенов.TTDoubleDash) Тогда
СкинутьОпции = Истина;
КонечноеСостояние = НачальноеСостояние.Т(Новый ОпцииЗавершениеПарсера(), ОбработчикВыборкиПути.НовоеСостояние());
Возврат Новый Структура("НачальноеСостояние, КонечноеСостояние", НачальноеСостояние, КонечноеСостояние);
Иначе
ВызватьИсключение "Все плохо сэр. Паника";
КонецЕсли;
Если НашлиТокен(ТипыТокенов.TTRep) Тогда
КонечноеСостояние.Т(Новый ЛюбойСимвол(), НачальноеСостояние);
КонецЕсли;
Если КонечноеСостояние = Неопределено Тогда
ВызватьИсключение "Не могу правильно построить маршрут";
КонецЕсли;
Возврат Новый Структура("НачальноеСостояние, КонечноеСостояние", НачальноеСостояние, КонечноеСостояние);
КонецФункции
Функция ТокенВыбора()
Лог.Отладка("Вызов <ТокенВыбора>");
НачальноеСостояние = ОбработчикВыборкиПути.НовоеСостояние();
КонечноеСостояние = ОбработчикВыборкиПути.НовоеСостояние();
Результат = ЧтениеДалее();
НачальноеСостояние.Т(Новый ЛюбойСимвол(), Результат.НачальноеСостояние);
Результат.КонечноеСостояние.Т(Новый ЛюбойСимвол(), КонечноеСостояние);
Пока НашлиТокен(ТипыТокенов.TTChoice) Цикл
Лог.Отладка("Нашли токен %1", ТипыТокенов.TTChoice);
РезультатВЦикле = ЧтениеДалее();
НачальноеСостояние.Т(Новый ЛюбойСимвол(), РезультатВЦикле.НачальноеСостояние);
РезультатВЦикле.КонечноеСостояние.Т(Новый ЛюбойСимвол(), КонечноеСостояние);
КонецЦикла;
Возврат Новый Структура("НачальноеСостояние, КонечноеСостояние", НачальноеСостояние, КонечноеСостояние);
КонецФункции
Процедура ОжидаюТокен(ТипТокена)
Если НЕ НашлиТокен(ТипТокена) Тогда
ВызватьИсключение "Не найден ожидаемый токен " + ТипТокена;
КонецЕсли;
КонецПроцедуры
Функция КонецТокенов()
Возврат ТекущаяПозиция >= ТокеныПарсера.Количество();
КонецФункции
Процедура Назад()
ТекущаяПозиция = ТекущаяПозиция - 1;
КонецПроцедуры
Функция Токен()
Если КонецТокенов() Тогда
Возврат Неопределено;
КонецЕсли;
Возврат ТокеныПарсера[ТекущаяПозиция];
КонецФункции
Функция ЭтоТокен(Знач ТипТокена)
Если КонецТокенов() Тогда
Возврат Ложь;
КонецЕсли;
Возврат Токен().Тип = ТипТокена;
КонецФункции
Функция МогуПрочитать()
Если ЭтоТокен(ТипыТокенов.TTArg)
ИЛИ ЭтоТокен(ТипыТокенов.TTOptions)
ИЛИ ЭтоТокен(ТипыТокенов.TTShortOpt)
ИЛИ ЭтоТокен(ТипыТокенов.TTLongOpt)
ИЛИ ЭтоТокен(ТипыТокенов.TTOptSeq)
ИЛИ ЭтоТокен(ТипыТокенов.TTOpenPar)
ИЛИ ЭтоТокен(ТипыТокенов.TTOpenSq)
ИЛИ ЭтоТокен(ТипыТокенов.TTDoubleDash)
Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
Функция НашлиТокен(Знач ТипТокена)
Если ЭтоТокен(ТипТокена) Тогда
Лог.Отладка("Нашли токен: %1", ТипТокена);
НайденныйТокен = Токен();
ТекущаяПозиция = ТекущаяПозиция + 1;
ЛОг.Отладка("Текущая позиция: %1", ТекущаяПозиция);
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.spec_parse");

View File

@@ -0,0 +1,226 @@
#Использовать logos
Перем Лог;
Перем НомераСостояний;
Перем ПоследнийНомар;
// Выполняет заполнение значений параметров команды
//
// Параметры:
// КонтейнерыЗначений - Объект - ссылка на Класс ПараметрКоманды
//
Процедура ЗаполнитьЗначения(КонтейнерыЗначений) Экспорт
Для каждого Контейнер Из КонтейнерыЗначений Цикл
Лог.Отладка("Заполняю значения %1", Контейнер.Ключ);
Если Контейнер.Ключ.ЭтоМассив() Тогда
Контейнер.Ключ.Очистить();
КонецЕсли;
Лог.Отладка("Контейнер <%1> массив %2", Контейнер.Ключ, Контейнер.Ключ.ЭтоМассив());
Для каждого значениеКонтейнера Из Контейнер.Значение Цикл
Лог.Отладка("Установил значения %1 в контейнер %2", значениеКонтейнера, Контейнер.Ключ);
Контейнер.Ключ.УстановитьЗначение(значениеКонтейнера);
КонецЦикла;
Контейнер.Ключ.УстановленаИзПеременнойОкружения = Ложь;
Если Не Контейнер.Ключ.УстановленаПользователем Тогда
Контейнер.Ключ.УстановленаПользователем = Истина;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// <Описание процедуры>
//
// Параметры:
// НачальноеСостояние - <Тип.Вид> - <описание параметра>
// Состояние - <Тип.Вид> - <описание параметра>
// ПосетилиСостояние - <Тип.Вид> - <описание параметра>
//
Процедура УпроститьСоединения(НачальноеСостояние, Состояние, ПосетилиСостояние) Экспорт
Лог.Отладка("Я УпроститьСоединения");
Если ПосетилиСостояние[Состояние] = Истина Тогда
Лог.Отладка("Я уже тут был");
Возврат;
КонецЕсли;
ПосетилиСостояние.Вставить(Состояние, Истина);
Для каждого Соединение Из Состояние.МассивСоединений Цикл
УпроститьСоединения(НачальноеСостояние, Соединение.СледующееСостояние, ПосетилиСостояние);
КонецЦикла;
Пока Истина Цикл
Если Не Состояние.УпроститьСвоиСоединения() Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// <Описание функции>
//
// Параметры:
// Состояние - <Тип.Вид> - <описание параметра>
//
// Возвращаемое значение:
// <Тип.Вид> - <описание возвращаемого значения>
//
Функция НомерСостояния(Состояние) Экспорт
Номер = НомераСостояний[Состояние];
Если Номер = Неопределено Тогда
ПоследнийНомар = ПоследнийНомар + 1;
Номер = ПоследнийНомар;
НомераСостояний.Вставить(Состояние, Номер);
КонецЕсли;
Возврат Номер;
КонецФункции
// <Описание функции>
//
// Параметры:
// Состояние - <Тип.Вид> - <описание параметра>
//
// Возвращаемое значение:
// <Тип.Вид> - <описание возвращаемого значения>
//
Функция ИмяСостояния(Состояние) Экспорт
Номер = НомерСостояния(Состояние);
Если Состояние.Завершено Тогда
Возврат СтрШаблон("(S%1)", Номер);
КонецЕсли;
Возврат СтрШаблон("S%1", Номер);
КонецФункции
// <Описание функции>
//
// Параметры:
// НачальноеСостояние - <Тип.Вид> - <описание параметра>
//
// Возвращаемое значение:
// <Тип.Вид> - <описание возвращаемого значения>
//
Функция СгенеритьСтрокуПути(НачальноеСостояние) Экспорт
ПосетилиСостояние = Новый Соответствие;
МассивСтрок = СостояниеВСтрокуПути(НачальноеСостояние, НомераСостояний, ПосетилиСостояние);
Возврат СтрСоединить(МассивСтрок, Символы.ПС);
КонецФункции
Функция СостояниеВСтрокуПути(Состояние, НомераСостояний, ПосетилиСостояние)
МассивСтрок = Новый Массив;
Если ПосетилиСостояние[Состояние] = Истина Тогда
Возврат МассивСтрок;
КонецЕсли;
ПосетилиСостояние.Вставить(Состояние, Истина);
Для каждого Соединение Из Состояние.МассивСоединений Цикл
МассивСтрок.Добавить(СтрШаблон("%1 %2 %3",
ИмяСостояния(Состояние),
Соединение.Парсер.ВСтроку(),
ИмяСостояния(Соединение.СледующееСостояние)));
СоединитьМассивы(МассивСтрок, СостояниеВСтрокуПути(Соединение.СледующееСостояние, НомераСостояний, ПосетилиСостояние));
КонецЦикла;
Возврат МассивСтрок;
КонецФункции
Процедура СоединитьМассивы(ИсходныйМассив, ПрисоединяемыйМассив)
Для каждого Переменная Из ПрисоединяемыйМассив Цикл
ИсходныйМассив.Добавить(Переменная);
КонецЦикла;
КонецПроцедуры
// <Описание процедуры>
//
// Параметры:
// Состояние - <Тип.Вид> - <описание параметра>
// ПосетилиСостояние - <Тип.Вид> - <описание параметра>
//
Процедура СортировкаСоединений(Состояние, ПосетилиСостояние) Экспорт
Если ПосетилиСостояние[Состояние] = Истина Тогда
Возврат;
КонецЕсли;
ПосетилиСостояние.Вставить(Состояние, Истина);
СортироватьМассив(Состояние.МассивСоединений);
Для каждого Соединение Из Состояние.МассивСоединений Цикл
СортировкаСоединений(Соединение.СледующееСостояние, ПосетилиСостояние);
КонецЦикла;
КонецПроцедуры
Процедура СортироватьМассив(МассивСоединений)
Для ТекущийИндекс = 0 По МассивСоединений.Количество() - 1 Цикл
Флаг = Ложь;
КоличествоСоединений = МассивСоединений.Количество() - 1;
Пока КоличествоСоединений > ТекущийИндекс Цикл
Элемент = МассивСоединений[КоличествоСоединений - 1];
СледующийЭлемент = МассивСоединений[КоличествоСоединений];
РезультатСортировки = Элемент.Парсер.Приоритет() > СледующийЭлемент.Парсер.Приоритет();
Если РезультатСортировки > 0 Тогда
МассивСоединений[КоличествоСоединений - 1] = СледующийЭлемент;
МассивСоединений[КоличествоСоединений] = Элемент;
Флаг = Истина;
КонецЕсли;
КоличествоСоединений = КоличествоСоединений - 1;
КонецЦикла;
Если НЕ Флаг Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// <Описание функции>
//
// Возвращаемое значение:
// <Тип.Вид> - <описание возвращаемого значения>
//
Функция НовоеСостояние() Экспорт
Возврат Новый Совпадение();
КонецФункции
НомераСостояний = Новый Соответствие;
ПоследнийНомар = 0;
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_path");

View File

@@ -0,0 +1,265 @@
#Использовать logos
Перем Лог;
Перем Завершено Экспорт; // Булево, признак завершения
// Массив, элементов соединений типа Структура
// * Парсер - объект - ссылка на класс парсера
// * СледующееСостояние - элемент типа Структура
Перем МассивСоединений Экспорт;
Процедура ПриСозданииОбъекта()
МассивСоединений = Новый Массив;
Завершено = Ложь;
КонецПроцедуры
// Процедура добавляет соединению к текущему состоянию
//
// Параметры:
// Парсер - Объект - ссылка на произвольный класс парсера
// СледующееСостояние - Объект.Совпадение - ссылка на класс Совпадение, следующего состояния
//
// Возвращаемое значение:
// Объект.Совпадение - ссылка на класс Совпадение, следующего состояния
//
Функция Т(Парсер, СледующееСостояние) Экспорт
МассивСоединений.Добавить(НовоеСоединениеСовпадений(Парсер, СледующееСостояние));
Возврат СледующееСостояние;
КонецФункции
Функция НовоеСоединениеСовпадений(Парсер, СледующееСостояние)
Возврат Новый Структура("Парсер, СледующееСостояние", Парсер, СледующееСостояние);
КонецФункции
// Выполняет подготовку соединений
//
Процедура Подготовить() Экспорт
ПосетилиСостояниеСортировки = Новый Соответствие;
ПосетилиСостояниеУпрощения = Новый Соответствие;
ОбработчикВыборкиПути = Новый ВыборСовпадений();
ОбработчикВыборкиПути.УпроститьСоединения(ЭтотОбъект, ЭтотОбъект, ПосетилиСостояниеУпрощения);
ОбработчикВыборкиПути.СортировкаСоединений(ЭтотОбъект, ПосетилиСостояниеСортировки);
КонецПроцедуры
// Выполняет чтения параметров команды
//
// Параметры:
// ВходящиеАргументы - Массив - массив входящих аргументов, типа строка
//
// Возвращаемое значение:
// булево - результат чтения параметров,
// * истина - все найдено
// * ложь - завершено с ошибками
//
Функция Прочитать(ВходящиеАргументы) Экспорт
Контекст = Новый КонтекстПарсеров;
Успех = ПрименитьКонтекст(ВходящиеАргументы, Контекст);
Если Не Успех Тогда
Возврат Ложь;
КонецЕсли;
ОбработчикВыборкиПути = Новый ВыборСовпадений();
ОбработчикВыборкиПути.ЗаполнитьЗначения(Контекст.Опции);
ОбработчикВыборкиПути.ЗаполнитьЗначения(Контекст.Аргументы);
Лог.Отладка("Проверка контекста:
| количество опций: %1
| количество аргументов %2", Контекст.Опции.Количество(), Контекст.Аргументы.Количество());
Возврат истина;
КонецФункции
// Выполняет поиск параметров команды в рамках контекста
//
// Параметры:
// ВходящиеАргументы - Массив - массив входящих аргументов, типа строка
// Контекст - Объект - ссылка на класс "КонтекстПарсеров"
//
// Возвращаемое значение:
// булево - результат поиска параметров,
// * истина - все найдено
// * ложь - завершено с ошибками
//
Функция ПрименитьКонтекст(Знач ВходящиеАргументы, Контекст) Экспорт
Лог.Отладка("Применяю контекст:
| количество соединений %1
| количество входящих аргументов %2
| Завершено: %3", МассивСоединений.Количество(), ВходящиеАргументы.Количество(), Завершено);
Если Завершено
И ВходящиеАргументы.Количество() = 0 Тогда
Возврат Истина;
КонецЕсли;
Если ВходящиеАргументы.Количество() > 0 Тогда
ПервыйАргумент = ВходящиеАргументы[0];
Если Не Контекст.СбросОпций
И СокрЛП(ПервыйАргумент) = "--" Тогда
Контекст.СбросОпций = Истина;
ВходящиеАргументы.Удалить(0);
КонецЕсли;
КонецЕсли;
МассивСовпадений = Новый Массив;
Лог.Отладка("Перебираю возможные пути: %1", МассивСоединений.Количество() );
Номер = 1;
Для каждого Соединение Из МассивСоединений Цикл
Лог.Отладка("Перебираю путь номер: %1", Номер);
ЧистыйКонтекст = Новый КонтекстПарсеров;
ЧистыйКонтекст.СбросОпций = Контекст.СбросОпций;
ЧистыйКонтекст.НеВключенныеАргументы = Контекст.НеВключенныеАргументы;
РезультатПоиска = Соединение.Парсер.Поиск(ВходящиеАргументы, ЧистыйКонтекст);
Лог.Отладка("Нашли опцию или аргумент: %2 %1", РезультатПоиска.РезультатПоиска, Соединение.Парсер.ВСтроку() );
лог.Отладка("Количество опций в контексте: %1", ЧистыйКонтекст.Опции.Количество());
лог.Отладка("Количество аргументов после поиска: %1", РезультатПоиска.Аргументы.Количество());
Если РезультатПоиска.РезультатПоиска Тогда
Лог.Отладка("Добавляю в массив найденное значение");
МассивСовпадений.Добавить(НовоеСовпадение(Соединение, РезультатПоиска.Аргументы, ЧистыйКонтекст));
КонецЕсли;
Номер = Номер + 1;
КонецЦикла;
Для каждого ЭлементСовпадения Из МассивСовпадений Цикл
СледующееСостояние = ЭлементСовпадения.Соединение.СледующееСостояние;
Если СледующееСостояние.ПрименитьКонтекст(ЭлементСовпадения.Результат, ЭлементСовпадения.Контекст) Тогда
Контекст.ПрисоединитьКонтекст(ЭлементСовпадения.Контекст);
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
// Выводит соединения текущего состояния
//
Процедура СообщитьСоединения() Экспорт
Лог.Отладка("Завершено: %1", Завершено);
Лог.Отладка("КоличествоСоединений: %1", МассивСоединений.Количество());
Для каждого Переменная Из МассивСоединений Цикл
СледующееСостояние = Переменная.СледующееСостояние;
Лог.Отладка("Класс текущего соединения: %1", Переменная.Парсер);
Лог.Отладка("Следующее состояние завершено: %1", СледующееСостояние.Завершено);
Лог.Отладка("Следующее состояние КоличествоСоединений: %1", СледующееСостояние.МассивСоединений.Количество());
Лог.Отладка("Вывожу сообщения для следующего состояния");
СледующееСостояние.СообщитьСоединения();
КонецЦикла;
КонецПроцедуры
// Проверяет наличие соединения в текущем состоянии
//
// Параметры:
// СоединениеПроверки - структура - Структура вида,
// * Парсер - объект - ссылка на класс парсера
// * СледующееСостояние - элемент типа Структура
// Возвращаемое значение:
// Булево - Истина, если массив соединений, содержит переданное соединения
//
Функция СодержитСоединения(Знач СоединениеПроверки) Экспорт
Для каждого Соединение Из МассивСоединений Цикл
Если Соединение.СледующееСостояние = СоединениеПроверки.СледующееСостояние
И Соединение.Парсер = СоединениеПроверки.Парсер Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
// Выполняет упрощение своих соединений
//
// Возвращаемое значение:
// Булево - результат упрощения соединения
//
Функция УпроститьСвоиСоединения() Экспорт
Индекс = 0;
Лог.Отладка("Я всего соединений: %1", МассивСоединений.Количество());
Пока Индекс <= МассивСоединений.ВГраница() Цикл
Лог.Отладка("Я всего соединений внутри: %1", МассивСоединений.Количество());
Соединение = МассивСоединений[Индекс];
Если ТипЗнч(Соединение.Парсер) = Тип("ЛюбойСимвол") Тогда
Лог.Отладка("Я Нашел ЛюбойСимвол");
СледующееСостояние = Соединение.СледующееСостояние;
Для каждого СоединениеСледующего Из СледующееСостояние.МассивСоединений Цикл
Если НЕ СодержитСоединения(СоединениеСледующего) Тогда
Лог.Отладка("Я добавил сюда подчиненные соединения");
МассивСоединений.Добавить(СоединениеСледующего);
Лог.Отладка("Добавляю соединение с парсером %1", СоединениеСледующего.Парсер);
КонецЕсли;
КонецЦикла;
Лог.Отладка("Упростить завершено %1", Завершено);
Лог.Отладка("Упростить следующие состояние завершено %1", СледующееСостояние.Завершено);
Если СледующееСостояние.Завершено Тогда
Завершено = Истина;
Лог.Отладка("Упростить установлено завершено %1", Завершено);
КонецЕсли;
Лог.Отладка("Удалил соединение с индексом %1", Индекс);
МассивСоединений.Удалить(Индекс);
Возврат Истина;
Иначе
Индекс = Индекс + 1;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
Функция НовоеСовпадение(Соединение, Результат, Контекст)
Возврат Новый Структура("Соединение, Результат, Контекст", Соединение, Результат, Контекст);
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_state");

View File

@@ -0,0 +1,570 @@
#Использовать logos
Перем ТекущийИндекс;
Перем Длина;
Перем ДлинаМассива;
Перем СтрокаЧтения;
Перем МассивСимволов;
Перем Лог;
Перем ПервоеЧтение;
Процедура ПриСозданииОбъекта(Знач ВходящаяСтрокаЧтения)
СтрокаЧтения = ВходящаяСтрокаЧтения;
Длина = СтрДлина(СтрокаЧтения);
МассивСимволов = Новый Массив;
Прочитать();
ПервоеЧтение = Истина;
ТекущийИндекс = ?(МассивСимволов.Количество() > 0, 0 , -1);
Если ТекущийИндекс = -1 Тогда
ПервоеЧтение = Ложь;
КонецЕсли;
КонецПроцедуры
// Функция выполняет чтение/разделение строки на символы строки
//
// Возвращаемое значение:
// Объект.ЧтениеСтроки - ссылка на текущий класс ЧтениеСтроки
//
Функция Прочитать() Экспорт
МассивСимволов.Очистить();
Для ИИ = 1 По Длина Цикл
МассивСимволов.Добавить(Сред(СтрокаЧтения, ИИ, 1));
КонецЦикла;
ДлинаМассива = МассивСимволов.ВГраница();
Лог.Отладка("Количество символов в строке %1", ДлинаМассива);
Возврат ЭтотОБъект;
КонецФункции
// Преобразовывает строку в массив символов между индексами
//
// Параметры:
// НачальныйИндекс - Число - начальный индекс символа строки
// КонечныйИндекс - Число - конечный индекс символа строки
//
// Возвращаемое значение:
// Массив - массив символов строки
//
Функция ВМассив(Знач НачальныйИндекс = Неопределено, Знач КонечныйИндекс = Неопределено) Экспорт
МассивВозврата = Новый Массив;
Если НачальныйИндекс = Неопределено
И КонечныйИндекс = Неопределено Тогда
Возврат МассивВозврата.Добавить(СтрокаЧтения);
КонецЕсли;
Если (ТипЗнч(КонечныйИндекс) = Тип("Число")
И КонечныйИндекс > ДлинаМассива)
Или КонечныйИндекс = Неопределено Тогда
КонечныйИндекс = ДлинаМассива;
КонецЕсли;
Если НачальныйИндекс = Неопределено Тогда
НачальныйИндекс = 0;
КонецЕсли;
Для ИндексСимвола = НачальныйИндекс По КонечныйИндекс Цикл
МассивВозврата.Добавить(МассивСимволов[ИндексСимвола]);
КонецЦикла;
Возврат МассивВозврата;
КонецФункции
// Преобразовывает строку в массив символов с начального индекса
//
// Параметры:
// НачальныйИндекс - Число - начальный индекс символа строки
//
// Возвращаемое значение:
// Массив - массив символов строки
//
Функция ВМассивС(Знач НачальныйИндекс) Экспорт
Возврат ВМассив(НачальныйИндекс);
КонецФункции
// Преобразовывает строку в массив символов до конечного индекса
//
// Параметры:
// КонечныйИндекс - Число - конечный индекс символа строки
//
// Возвращаемое значение:
// Массив - массив символов строки
//
Функция ВМассивПо(Знач КонечныйИндекс) Экспорт
Возврат ВМассив(, КонечныйИндекс);
КонецФункции
// Преобразовывает строку в класс "ЧтениеСтроки" символов между индексами
//
// Параметры:
// НачальныйИндекс - Число - начальный индекс символа строки
// КонечныйИндекс - Число - конечный индекс символа строки
//
// Возвращаемое значение:
// ЧтениеСтроки - класс ЧтениеСтроки
//
Функция ВЧтениеСтроки(НачальныйИндекс = Неопределено, КонечныйИндекс = Неопределено) Экспорт
Возврат Новый ЧтениеСтроки(ВСтроку(НачальныйИндекс, КонечныйИндекс));
КонецФункции
// Преобразовывает строку в класс "ЧтениеСтроки" символов с начального индекса
//
// Параметры:
// НачальныйИндекс - Число - начальный индекс символа строки
//
// Возвращаемое значение:
// ЧтениеСтроки - класс ЧтениеСтроки
//
Функция ВЧтениеСтрокиС(НачальныйИндекс) Экспорт
Возврат Новый ЧтениеСтроки(ВСтрокуС(НачальныйИндекс));
КонецФункции
// Преобразовывает строку в класс "ЧтениеСтроки" символов до конечного индекса
//
// Параметры:
// КонечныйИндекс - Число - конечный индекс символа строки
//
// Возвращаемое значение:
// ЧтениеСтроки - класс ЧтениеСтроки
//
Функция ВЧтениеСтрокиПо(КонечныйИндекс) Экспорт
Возврат Новый ЧтениеСтроки(ВСтрокуПо(КонечныйИндекс));
КонецФункции
// Преобразовывает строку массив символов между индексами
//
// Параметры:
// НачальныйИндекс - Число - начальный индекс символа строки
// КонечныйИндекс - Число - конечный индекс символа строки
//
// Возвращаемое значение:
// строка - строка между индексами
//
Функция ВСтроку(Знач НачальныйИндекс = Неопределено, Знач КонечныйИндекс = Неопределено) Экспорт
Если НачальныйИндекс = Неопределено
И КонечныйИндекс = Неопределено Тогда
Возврат СтрокаЧтения;
КонецЕсли;
Если (ТипЗнч(КонечныйИндекс) = Тип("Число")
И КонечныйИндекс > ДлинаМассива)
Или КонечныйИндекс = Неопределено Тогда
КонечныйИндекс = ДлинаМассива;
КонецЕсли;
Возврат СтрСоединить(ВМассив(НачальныйИндекс, КонечныйИндекс));
КонецФункции
// Преобразовывает строку массив символов с начального индекса
//
// Параметры:
// НачальныйИндекс - Число - начальный индекс символа строки
//
// Возвращаемое значение:
// строка - строка с начального индекса
//
Функция ВСтрокуС(НачальныйИндекс) Экспорт
Возврат ВСтроку(НачальныйИндекс);
КонецФункции
// Преобразовывает строку массив символов до конечного индекса
//
// Параметры:
// КонечныйИндекс - Число - конечный индекс символа строки
//
// Возвращаемое значение:
// строка - строка до конечного индекса
//
Функция ВСтрокуПо(КонечныйИндекс) Экспорт
Возврат ВСтроку(, КонечныйИндекс);
КонецФункции
// Последовательное чтение строки по индексам
//
// Параметры:
// Прибавка - Число - прибавка к индексу для чтения (по умолчанию 1)
//
// Возвращаемое значение:
// булево - результат чтения
// * Истина - при успешном чтении
//
Функция Читать(Знач Прибавка = 1) Экспорт
Если ПервоеЧтение Тогда
ПервоеЧтение = Ложь;
Возврат Истина;
КонецЕсли;
Если КонецСтроки() Тогда
Возврат Ложь;
КонецЕсли;
Лог.Отладка("Выполняю чтение");
ТекущийИндекс = ТекущийИндекс + Прибавка;
Возврат Истина;
КонецФункции
// Последовательное чтение строки по индексам с условием
//
// Параметры:
// ПроверкаПродолженияЧтения - булево - признак приостановки чтения строки
//
// Возвращаемое значение:
// булево - результат чтения
// * Истина - при успешном чтении
//
Функция ЧитатьПока(Знач ПроверкаПродолженияЧтения) Экспорт
Если НЕ ПроверкаПродолженияЧтения Тогда
Назад();
Возврат Ложь;
КонецЕсли;
Возврат Читать();
КонецФункции
// Последовательное чтение строки по индексам с ограничением
//
// Параметры:
// ОграничениеЧтения - строка - ограничение чтения строки по условию
//
// Возвращаемое значение:
// булево - результат чтения
// * Истина - при успешном чтении
//
Функция ЧитатьДо(Знач ОграничениеЧтения = Неопределено) Экспорт
НачальныйИндекс = ТекущийИндекс;
УспешноПрочитали = Ложь;
Лог.Отладка("ЧитатьДо: ОграничениеЧтения: %1", ОграничениеЧтения);
Если ТипЗнч(ОграничениеЧтения) = Тип("Строка") Тогда
ПродолжитьЧтение = Ложь;
Пока Читать() Цикл
ПродолжитьЧтение = Истина;
Выполнить(ОграничениеЧтения);
Если Не ПродолжитьЧтение Тогда
УспешноПрочитали = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если УспешноПрочитали Тогда
Назад();
КонецЕсли;
Если ПродолжитьЧтение
И КонецСтроки() Тогда
УспешноПрочитали = Истина;
КонецЕсли;
ИначеЕсли ТипЗнч(ОграничениеЧтения) = Тип("Число") Тогда
УспешноПрочитали = ЧитатьДоИндекса(ОграничениеЧтения);
КонецЕсли;
Если НЕ УспешноПрочитали Тогда
ТекущийИндекс = НачальныйИндекс;
КонецЕсли;
Возврат УспешноПрочитали;
КонецФункции
// Последовательное чтение строки по индексам с ограничением по индексу
//
// Параметры:
// ТребуемыйИндекс - Число - нужный индекс чтения
//
// Возвращаемое значение:
// булево - результат чтения
// * Истина - при успешном чтении
//
Функция ЧитатьДоИндекса(Знач ТребуемыйИндекс) Экспорт
Если МассивСимволов.ВГраница() < ТребуемыйИндекс Тогда
Возврат Ложь;
КонецЕсли;
ТекущийИндекс = ТребуемыйИндекс - 1;
Возврат Истина;
КонецФункции
// Последовательное чтение строки по индексам с условию по символу
//
// Параметры:
// ВходящийСимвол - Символ - нужный символ строки
//
// Возвращаемое значение:
// булево - результат чтения
// * Истина - при успешном чтении
//
Функция ЧитатьДоСимвола(Знач ВходящийСимвол) Экспорт
Возврат ЧитатьДо(СтрШаблон("ПродолжитьЧтение = НЕ ЭтоСимвол(""%1"")", ВходящийСимвол));
КонецФункции
// Функция перемещает индекс чтения строки назад на 1 символ
//
// Возвращаемое значение:
// Объект.ЧтениеСтроки - ссылка на текущий класс ЧтениеСтроки
//
Функция Назад() Экспорт
ТекущийИндекс = ТекущийИндекс - 1;
Возврат ЭтотОБъект;
КонецФункции
// Функция сбрасывает индекс чтения строки на 0
//
// Возвращаемое значение:
// Объект.ЧтениеСтроки - ссылка на текущий класс ЧтениеСтроки
//
Функция СброситьЧтение() Экспорт
ТекущийИндекс = 0;
Возврат ЭтотОБъект;
КонецФункции
// Последовательное чтение строки по индексам на Н символов
//
// Параметры:
// Прибавка - Число - прибавка к индексу для чтения (по умолчанию 1)
//
// Возвращаемое значение:
// булево - результат чтения
// * Истина - при успешном чтении
//
Функция ЧитатьНа(Знач Прибавка = 1) Экспорт
Возврат Читать(Прибавка);
КонецФункции
// Получает и возвращает символ по текущему индексу
//
// Возвращаемое значение:
// строка - текущий символ по индексу
//
Функция ПолучитьСимвол() Экспорт
Возврат МассивСимволов[ТекущийИндекс];
КонецФункции
// Выполняем проверку текущего символа на "[a-zA-Zа-яА-Я]"
//
// Возвращаемое значение:
// булево - результат проверки
// * Истина - при успешном проверке по регулярному выражению
//
Функция ЭтоБуква() Экспорт
Значение = ПолучитьСимвол();
РегуляркаДляПочты = Новый РегулярноеВыражение("[a-zA-Zа-яА-Я]");
КоллекцияСовпадений = РегуляркаДляПочты.НайтиСовпадения(Значение);
Возврат КоллекцияСовпадений.Количество() = 1;
КонецФункции
// Выполняем проверку текущего символа на "[A-ZА-Я]"
//
// Возвращаемое значение:
// булево - результат проверки
// * Истина - при успешном проверке по регулярному выражению
//
Функция ЭтоБольшаяБуква() Экспорт
Значение = ПолучитьСимвол();
РегуляркаДляПочты = Новый РегулярноеВыражение ("[A-ZА-Я]");
КоллекцияСовпадений = РегуляркаДляПочты.НайтиСовпадения(Значение);
Возврат КоллекцияСовпадений.Количество() = 1;
КонецФункции
// Выполняем проверку текущего символа на "[a-zа-я]"
//
// Возвращаемое значение:
// булево - результат проверки
// * Истина - при успешном проверке по регулярному выражению
//
Функция ЭтоМаленькаяБуква() Экспорт
Значение = ПолучитьСимвол();
РегуляркаДляПочты = Новый РегулярноеВыражение ("[a-zа-я]");
КоллекцияСовпадений = РегуляркаДляПочты.НайтиСовпадения(Значение);
Возврат КоллекцияСовпадений.Количество() = 1;
КонецФункции
// Выполняем проверку текущего символа на "\d"
//
// Возвращаемое значение:
// булево - результат проверки
// * Истина - при успешном проверке по регулярному выражению
//
Функция ЭтоЧисло() Экспорт
Значение = ПолучитьСимвол();
РегуляркаДляПочты = Новый РегулярноеВыражение ("\d");
КоллекцияСовпадений = РегуляркаДляПочты.НайтиСовпадения(Значение);
Возврат КоллекцияСовпадений.Количество() = 1;
КонецФункции
// Выполняем проверку текущего символа на переданный символ
//
// Параметры:
// СимволПроверки - Строка, Символ - символ проверки
//
// Возвращаемое значение:
// булево - результат проверки
// * Истина - при успешном проверке на равенство символу
//
Функция ЭтоСимвол(Знач СимволПроверки) Экспорт
Возврат ПолучитьСимвол() = СимволПроверки;
КонецФункции
// Получает и возвращает символ по текущему индексу
//
// Возвращаемое значение:
// строка - текущий символ по индексу
//
Функция ТекущийСимвол() Экспорт
Возврат ПолучитьСимвол();
КонецФункции
// Получает и возвращает символ по следующему индексу без чтения
//
// Возвращаемое значение:
// строка - текущий символ по индексу
//
Функция СледующийСимвол() Экспорт
ЗапределамиМассива = ТекущийИндекс + 1 > МассивСимволов.ВГраница();
Если ЗапределамиМассива Тогда
Возврат "";
КонецЕсли;
Возврат МассивСимволов[ТекущийИндекс + 1];
КонецФункции
// Выполняем проверку следующего символа на переданный символ без чтения строки
//
// Параметры:
// СимволПроверки - Строка, Символ - символ проверки
//
// Возвращаемое значение:
// булево - результат проверки
// * Истина - при успешном проверке на равенство символу
//
Функция СледующийСимволЭто(Знач СимволПроверки) Экспорт
Значение = СледующийСимвол();
Возврат Значение = СимволПроверки;
КонецФункции
// Получает и возвращает текущий индекс
//
// Возвращаемое значение:
// число - текущий индекс
//
Функция ТекущийИндекс() Экспорт
Возврат ТекущийИндекс;
КонецФункции
// Выполняет проверку на конец строки при чтении
//
// Возвращаемое значение:
// булево - результат проверки
// * Истина - если чтение строки закончилось
//
Функция КонецСтроки() Экспорт
Если ДлинаМассива = -1 Тогда
Возврат Истина;
КонецЕсли;
Возврат ТекущийИндекс = МассивСимволов.ВГраница();
КонецФункции
// Выполняет проверку на текущий индекс строки при чтении находится за пределами массива
//
// Возвращаемое значение:
// булево - результат проверки
// * Истина - если текущий индекс за пределами массива чтения
//
Функция ИндексЗаПределомМассива() Экспорт
Возврат ТекущийИндекс > МассивСимволов.ВГраница();
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.string_read");

View File

@@ -0,0 +1,60 @@
Перем ОписаниеОшибкиКласса;
// Возвращает строковое представление значения типа
//
// Параметры:
// Значение - Булево - значение типа
//
// Возвращаемое значение:
// строка - значение в строковом представлении
//
Функция ВСтроку(Значение) Экспорт
Возврат Строка(Значение);
КонецФункции
// Преобразует и устанавливает входящее значение к значению типа
//
// Параметры:
// ВходящееЗначение - строка - строковое представление значения
// Значение - булево - переменная для установки значения
//
// Возвращаемое значение:
// булево - конвертированные значение
//
Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт
Если ТипЗнч(ВходящееЗначение) = Тип("Булево") Тогда
Возврат ВходящееЗначение;
КонецЕсли;
Попытка
Значение = Булево(ВходящееЗначение);
Исключение
ОписаниеОшибкиКласса = ОписаниеОшибки();
КонецПопытки;
Возврат Значение;
КонецФункции
// Возвращает описание ошибки и устанавливает признак ошибки
//
// Параметры:
// ЕстьОшибка - булево - произвольная переменная
//
// Возвращаемое значение:
// Строка - описание текущей ошибки преобразования типов
//
Функция Ошибка(ЕстьОшибка = Ложь) Экспорт
Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда
ЕстьОшибка = Истина;
КонецЕсли;
Возврат ОписаниеОшибкиКласса;
КонецФункции
ОписаниеОшибкиКласса = "";

View File

@@ -0,0 +1,68 @@
#Использовать datetime
Перем ОписаниеОшибкиКласса;
Перем ФорматДаты;
Процедура ПриСозданииОбъекта(Знач ВходящийФормат = "yyyy-MM-dd HH:mm:ss")
ФорматДаты = ВходящийФормат;
КонецПроцедуры
// Возвращает строковое представление значения типа
//
// Параметры:
// Значение - Дата - значение типа
//
// Возвращаемое значение:
// строка - значение в строковом представлении
//
Функция ВСтроку(Значение) Экспорт
Возврат Формат(Значение, ФорматДаты);
КонецФункции
// Преобразует и устанавливает входящее значение к значению типа
//
// Параметры:
// ВходящаяСтрока - строка - строковое представление значения
// Значение - Дата - переменная для установки значения
//
// Возвращаемое значение:
// дата - конвертированные значение
//
Функция УстановитьЗначение(Знач ВходящаяСтрока, Значение) Экспорт
Попытка
ПроцессорДаты = Новый ДатаВремя();
Значение = ПроцессорДаты.СтрокаВДату(ВходящаяСтрока, ФорматДаты);
Исключение
Значение = Дата("20010101");
ОписаниеОшибкиКласса = ОписаниеОшибки();
КонецПопытки;
Возврат Значение;
КонецФункции
// Возвращает описание ошибки и устанавливает признак ошибки
//
// Параметры:
// ЕстьОшибка - булево - произвольная переменная
//
// Возвращаемое значение:
// Строка - описание текущей ошибки преобразования типов
//
Функция Ошибка(ЕстьОшибка = Ложь) Экспорт
Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда
ЕстьОшибка = Истина;
КонецЕсли;
Возврат ОписаниеОшибкиКласса;
КонецФункции
ОписаниеОшибкиКласса = "";

View File

@@ -0,0 +1,76 @@
Перем ОписаниеОшибкиКласса;
// Возвращает строковое представление значения типа
//
// Параметры:
// Значение - массив - значение типа
//
// Возвращаемое значение:
// строка - значение в строковом представлении
//
Функция ВСтроку(Значение) Экспорт
Возврат ПреобразоватьМассивВСтроку(Значение);
КонецФункции
// Преобразует и устанавливает входящее значение к значению типа
//
// Параметры:
// ВходящееЗначение - Булево - Значение флага
// Значение - массив - переменная для установки значения
//
// Возвращаемое значение:
// массив - конвертированные значение
//
Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт
Если ТипЗнч(ВходящееЗначение) = Тип("Булево") Тогда
Значение.Добавить(ВходящееЗначение);
Иначе
Попытка
Значение.Добавить(Булево(ВходящееЗначение));
Исключение
ОписаниеОшибкиКласса = ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
Возврат Значение;
КонецФункции
// Возвращает описание ошибки и устанавливает признак ошибки
//
// Параметры:
// ЕстьОшибка - булево - произвольная переменная
//
// Возвращаемое значение:
// Строка - описание текущей ошибки преобразования типов
//
Функция Ошибка(ЕстьОшибка = Ложь) Экспорт
Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда
ЕстьОшибка = Истина;
КонецЕсли;
Возврат ОписаниеОшибкиКласса;
КонецФункции
Функция ПреобразоватьМассивВСтроку(МассивЗначений)
Если НЕ ТипЗнч(МассивЗначений) = Тип("Массив") Тогда
Возврат "";
КонецЕсли;
МассивСтрок = Новый Массив;
Для Каждого Значение Из МассивЗначений Цикл
МассивСтрок.Добавить(Формат(Значение, "БЛ=Ложь; БИ=Истина"));
КонецЦикла;
Возврат СтрСоединить(МассивСтрок, ", ");
КонецФункции
ОписаниеОшибкиКласса = "";

View File

@@ -0,0 +1,85 @@
#Использовать datetime
Перем ОписаниеОшибкиКласса;
Перем ФорматДаты;
Процедура ПриСозданииОбъекта(Знач ВходящийФорматДаты = "yyyy-MM-dd HH:mm:ss")
ФорматДаты = ВходящийФорматДаты;
КонецПроцедуры
// Возвращает строковое представление значения типа
//
// Параметры:
// Значение - Массив - значение типа
//
// Возвращаемое значение:
// строка - значение в строковом представлении
//
Функция ВСтроку(Знач Значение) Экспорт
Возврат ПреобразоватьМассивВСтроку(Значение);
КонецФункции
// Преобразует и устанавливает входящее значение к значению типа
//
// Параметры:
// ВходящееЗначение - строка - строковое представление значения
// Значение - массив - переменная для установки значения
//
// Возвращаемое значение:
// массив - конвертированные значение
//
Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт
Попытка
ПроцессорДаты = Новый ДатаВремя();
ВходящееЗначение = ПроцессорДаты.СтрокаВДату(ВходящееЗначение, ФорматДаты);
Значение.Добавить(ВходящееЗначение);
Исключение
Значение = Дата("20010101");
ОписаниеОшибкиКласса = ОписаниеОшибки();
КонецПопытки;
Возврат Значение;
КонецФункции
// Возвращает описание ошибки и устанавливает признак ошибки
//
// Параметры:
// ЕстьОшибка - булево - произвольная переменная
//
// Возвращаемое значение:
// Строка - описание текущей ошибки преобразования типов
//
Функция Ошибка(ЕстьОшибка = Ложь) Экспорт
Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда
ЕстьОшибка = Истина;
КонецЕсли;
Возврат ОписаниеОшибкиКласса;
КонецФункции
Функция ПреобразоватьМассивВСтроку(Знач Значение)
Если НЕ ТипЗнч(Значение) = Тип("Массив") Тогда
Возврат "";
КонецЕсли;
Для каждого ЭлементМассива Из Значение Цикл
ЭлементМассива = Формат(ЭлементМассива, ФорматДаты);
КонецЦикла;
Возврат СтрСоединить(Значение, ", ");
КонецФункции
ОписаниеОшибкиКласса = "";

View File

@@ -0,0 +1,67 @@
Перем ОписаниеОшибкиКласса;
// Возвращает строковое представление значения типа
//
// Параметры:
// Значение - массив - значение типа
//
// Возвращаемое значение:
// строка - значение в строковом представлении
//
Функция ВСтроку(Значение) Экспорт
Возврат ПреобразоватьМассивВСтроку(Значение);
КонецФункции
// Преобразует и устанавливает входящее значение к значению типа
//
// Параметры:
// ВходящееЗначение - строка - строковое представление значения
// Значение - массив - переменная для установки значения
//
// Возвращаемое значение:
// массив - конвертированные значение
//
Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт
Попытка
Значение.Добавить(ВходящееЗначение);
Исключение
ОписаниеОшибкиКласса = ОписаниеОшибки();
КонецПопытки;
Возврат Значение;
КонецФункции
// Возвращает описание ошибки и устанавливает признак ошибки
//
// Параметры:
// ЕстьОшибка - булево - произвольная переменная
//
// Возвращаемое значение:
// Строка - описание текущей ошибки преобразования типов
//
Функция Ошибка(ЕстьОшибка = Ложь) Экспорт
Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда
ЕстьОшибка = Истина;
КонецЕсли;
Возврат ОписаниеОшибкиКласса;
КонецФункции
Функция ПреобразоватьМассивВСтроку(Значение)
Если НЕ ТипЗнч(Значение) = Тип("Массив") Тогда
Возврат "";
КонецЕсли;
Возврат СтрСоединить(Значение, ", ");
КонецФункции
ОписаниеОшибкиКласса = "";

View File

@@ -0,0 +1,68 @@
Перем ОписаниеОшибкиКласса;
// Возвращает строковое представление значения типа
//
// Параметры:
// Значение - Массив - значение типа
//
// Возвращаемое значение:
// строка - значение в строковом представлении
//
Функция ВСтроку(Значение) Экспорт
Возврат ПреобразоватьМассивВСтроку(Значение);
КонецФункции
// Преобразует и устанавливает входящее значение к значению типа
//
// Параметры:
// ВходящееЗначение - строка - строковое представление значения
// Значение - массив - переменная для установки значения
//
// Возвращаемое значение:
// массив - конвертированные значение
//
Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт
Попытка
ВходящееЗначение = Число(ВходящееЗначение);
Значение.Добавить(ВходящееЗначение);
Исключение
ОписаниеОшибкиКласса = ОписаниеОшибки();
КонецПопытки;
Возврат Значение;
КонецФункции
// Возвращает описание ошибки и устанавливает признак ошибки
//
// Параметры:
// ЕстьОшибка - булево - произвольная переменная
//
// Возвращаемое значение:
// Строка - описание текущей ошибки преобразования типов
//
Функция Ошибка(ЕстьОшибка = Ложь) Экспорт
Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда
ЕстьОшибка = Истина;
КонецЕсли;
Возврат ОписаниеОшибкиКласса;
КонецФункции
Функция ПреобразоватьМассивВСтроку(Значение)
Если НЕ ТипЗнч(Значение) = Тип("Массив") Тогда
Возврат "";
КонецЕсли;
Возврат СтрСоединить(Значение, ", ");
КонецФункции
ОписаниеОшибкиКласса = "";

View File

@@ -0,0 +1,123 @@
Перем ПеречисленияКласса Экспорт; // Соответствие
Перем ОписаниеОшибкиКласса;
// Возвращает строковое представление значения типа
//
// Параметры:
// Значение - Строка - значение типа
//
// Возвращаемое значение:
// строка - значение в строковом представлении
//
Функция ВСтроку(Значение) Экспорт
Если ТипЗнч(Значение) = Тип("Сценарий") Тогда
Возврат Значение.ВСтроку();
КонецЕсли;
Возврат Строка(Значение);
КонецФункции
// Возвращает подробное описание перечислений значения типа
//
// Возвращаемое значение:
// строка - значение в строковом представлении
//
Функция ПодробноеОписание() Экспорт
СтрокаОписания = "";
Для каждого КлючЗначение Из ПеречисленияКласса Цикл
СтрокаОписания = СтрокаОписания + СтрШаблон("%1: %2",
КлючЗначение.Значение.Наименование,
КлючЗначение.Значение.ДополнительнаяСправка) + Символы.ПС;
КонецЦикла;
Возврат СтрокаОписания;
КонецФункции
// Преобразует и устанавливает входящее значение к значению типа
//
// Параметры:
// ВходящееЗначение - строка - строковое представление значения
// Значение - произвольный - переменная для установки значения
//
// Возвращаемое значение:
// Произвольный - конвертированные значение
//
Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт
ЗначениеПеречисления = ПеречисленияКласса[ВходящееЗначение];
Если НЕ ЗначениеПеречисления = Неопределено Тогда
Значение = ЗначениеПеречисления.Значение;
Иначе
ОписаниеОшибкиКласса = "Выбранное значение перечисления не соответствует доступным";
КонецЕсли;
Возврат Значение;
КонецФункции
// Возвращает описание ошибки и устанавливает признак ошибки
//
// Параметры:
// ЕстьОшибка - булево - произвольная переменная
//
// Возвращаемое значение:
// Строка - описание текущей ошибки преобразования типов
//
Функция Ошибка(ЕстьОшибка = Ложь) Экспорт
Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда
ЕстьОшибка = Истина;
КонецЕсли;
Возврат ОписаниеОшибкиКласса;
КонецФункции
// Устанавливает доступные перечисления из соответствия
//
// Параметры:
// СоответствиеПеречислений - Соответствие - Доступные перечисления
// * Ключ - Строка - доступные ключи ("Наименование, Значение, ДополнительнаяСправка")
// * Значение - произвольный
//
Процедура УстановитьПеречисления(Знач СоответствиеПеречислений) Экспорт
Если Тип("Соответствие") = ТипЗнч(СоответствиеПеречислений) Тогда
ПеречисленияКласса = СоответствиеПеречислений;
КонецЕсли;
КонецПроцедуры
// Добавляет перечисление в коллекцию
//
// Параметры:
// ПользовательскоеЗначение - Строка - пользовательское представление значения
// Значение - произвольный - системное значение перечисления
// ДополнительнаяСправка - строка - дополнительное описание для справки
//
Процедура ДобавитьПеречисление(Знач ПользовательскоеЗначение, Знач Значение, Знач ДополнительнаяСправка = "") Экспорт
ПеречисленияКласса.Вставить(ПользовательскоеЗначение,
НовоеПеречисление(ПользовательскоеЗначение, Значение, ДополнительнаяСправка));
КонецПроцедуры
Функция НовоеПеречисление(Знач Наименование, Знач Значение, Знач ДополнительнаяСправка = "")
Возврат Новый Структура("Наименование, Значение, ДополнительнаяСправка", Наименование, Значение, ДополнительнаяСправка);
КонецФункции
ПеречисленияКласса = Новый Соответствие;
ОписаниеОшибкиКласса = "";

View File

@@ -0,0 +1,53 @@
Перем ОписаниеОшибкиКласса;
// Возвращает строковое представление значения типа
//
// Параметры:
// Значение - Строка - значение типа
//
// Возвращаемое значение:
// строка - значение в строковом представлении
//
Функция ВСтроку(Значение) Экспорт
Возврат Значение;
КонецФункции
// Преобразует и устанавливает входящее значение к значению типа
//
// Параметры:
// ВходящееЗначение - строка - строковое представление значения
// Значение - строка - переменная для установки значения
//
// Возвращаемое значение:
// строка - конвертированные значение
//
Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт
Значение = Строка(ВходящееЗначение);
Возврат Значение;
КонецФункции
// Возвращает описание ошибки и устанавливает признак ошибки
//
// Параметры:
// ЕстьОшибка - булево - произвольная переменная
//
// Возвращаемое значение:
// Строка - описание текущей ошибки преобразования типов
//
Функция Ошибка(ЕстьОшибка = Ложь) Экспорт
Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда
ЕстьОшибка = Истина;
КонецЕсли;
Возврат ОписаниеОшибкиКласса;
КонецФункции
ОписаниеОшибкиКласса = "";

View File

@@ -0,0 +1,57 @@
Перем ОписаниеОшибкиКласса;
// Возвращает строковое представление значения типа
//
// Параметры:
// Значение - число - значение типа
//
// Возвращаемое значение:
// строка - значение в строковом представлении
//
Функция ВСтроку(Значение) Экспорт
Возврат Строка(Значение);
КонецФункции
// Преобразует и устанавливает входящее значение к значению типа
//
// Параметры:
// ВходящееЗначение - строка - строковое представление значения
// Значение - число - переменная для установки значения
//
// Возвращаемое значение:
// число - конвертированные значение
//
Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт
Попытка
Значение = Число(ВходящееЗначение);
Исключение
ОписаниеОшибкиКласса = ОписаниеОшибки();
КонецПопытки;
Возврат Значение;
КонецФункции
// Возвращает описание ошибки и устанавливает признак ошибки
//
// Параметры:
// ЕстьОшибка - булево - произвольная переменная
//
// Возвращаемое значение:
// Строка - описание текущей ошибки преобразования типов
//
Функция Ошибка(ЕстьОшибка = Ложь) Экспорт
Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда
ЕстьОшибка = Истина;
КонецЕсли;
Возврат ОписаниеОшибкиКласса;
КонецФункции
ОписаниеОшибкиКласса = "";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,211 @@
// Класс ПараметрКоманды, для доступа к установленному значению из вне
Перем ФлагВерсия Экспорт;
// Строковое представление версии приложения
Перем ВерсияПриложения Экспорт;
Перем Команда;
Перем НаименованиеПриложения;
Перем ОписаниеПриложения;
// Процедура добавляет версию приложения,
// при вызове данной опции, показывается установленная версия и
// завершается выполнение с кодом (0)
//
// Параметры:
// Наименование - строка - имя опции, в строке допустимо задавать синоним через пробел, например "v version"
// СтрокаВерсии - строка - версия, приложения
Процедура Версия(Наименование, СтрокаВерсии) Экспорт
ВерсияПриложения = СтрокаВерсии;
ФлагВерсия = Команда.Опция(Наименование, Ложь, "показать версию и выйти");
КонецПроцедуры
// Процедура позволяет переопределить стандартную строку использования приложения
//
// Параметры:
// СтрокаСпек - строка - переопределенная строка использования приложения
Процедура УстановитьСпек(Знач СтрокаСпек) Экспорт
Команда.Спек = СтрокаСпек;
КонецПроцедуры
// Возвращает основную команду приложения
//
// Возвращаемое значение:
// Команда - класс КомандаПриложения
Функция ПолучитьКоманду() Экспорт
Возврат Команда;
КонецФункции
// Основная процедура запуска приложения
//
// Параметры:
// АргументыКоманднойСтрокиВходящие - Массив - Элементы <Строка>, необзательный,
// Если, не передано считывает из АргументыКоманднойСтроки
Процедура Запустить(АргументыКоманднойСтрокиВходящие = Неопределено) Экспорт
Аргументы = АргументыКоманднойСтроки;
Если Не АргументыКоманднойСтрокиВходящие = Неопределено Тогда
Аргументы = АргументыКоманднойСтрокиВходящие;
КонецЕсли;
Если Тип("ПараметрКоманды") = ТипЗнч(ФлагВерсия)
И ЗначениеЗаполнено(ВерсияПриложения)
И ФлагУстановлен(Аргументы, ФлагВерсия) Тогда
ВывестиВерсию();
ЗавершитьРаботу(0);
КонецЕсли;
Команда.НачалоЗапуска();
Команда.Запуск(Аргументы);
КонецПроцедуры
// Функция добавляет команду приложение и возвращает экземпляр данной команды
//
// Параметры:
// ИмяКоманды - строка - в строке допустимо задавать синоним через пробел, например "exec e"
// ОписаниеКоманды - строка - описание команды для справки
// КлассРеализацииКоманды - объект - класс, объект реализующий функции выполнения команды.
// Так же используется, для автоматической настройки опций и параметров команды
//
// Возвращаемое значение:
// Команда - класс КомандаПриложения
Функция ДобавитьКоманду(ИмяКоманды, ОписаниеКоманды, КлассРеализацииКоманды) Экспорт
Возврат Команда.ДобавитьПодкоманду(ИмяКоманды, ОписаниеКоманды, КлассРеализацииКоманды);
КонецФункции
// Процедура устанавливает процедуру "ВыполнитьКоманду" выполнения для приложения
//
// Параметры:
// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды.
// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ВыполнитьКоманду"
//
Процедура УстановитьОсновноеДействие(КлассРеализации, ИмяПроцедуры = "ВыполнитьКоманду") Экспорт
Команда.УстановитьДействиеВыполнения(КлассРеализации, ИмяПроцедуры);
КонецПроцедуры
// Процедура устанавливает процедуру "ПередВыполнениемКоманды" выполнения для приложения
// запускаемую перед выполнением "ВыполнитьКоманду"
//
// Параметры:
// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды.
// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ПередВыполнениемКоманды"
//
Процедура УстановитьДействиеПередВыполнением(КлассРеализации, ИмяПроцедуры = "ПередВыполнениемКоманды") Экспорт
Команда.УстановитьДействиеПередВыполнением(КлассРеализации, ИмяПроцедуры);
КонецПроцедуры
// Процедура устанавливает процедуру "ПослеВыполненияКоманды" выполнения для приложения
// запускаемую после выполнением "ВыполнитьКоманду"
//
// Параметры:
// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды.
// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ПослеВыполненияКоманды"
//
Процедура УстановитьДействиеПослеВыполнения(КлассРеализации, ИмяПроцедуры = "ПослеВыполненияКоманды") Экспорт
Команда.УстановитьДействиеПослеВыполнения(КлассРеализации, ИмяПроцедуры);
КонецПроцедуры
// Функция добавляет опцию приложения и возвращает экземпляр данной опции
//
// Параметры:
// Имя - строка - имя опции, в строке допустимо задавать синоним через пробел, например "s some-opt"
// Значение - строка - значение опции по умолчанию
// Описание - объект - описание опции для справки.
//
// Возвращаемое значение:
// Команда - класс ПараметрКоманды
//
// Дополнительно смотри справку по классу ПараметрКоманды
Функция Опция(Имя, Значение = "", Описание = "") Экспорт
Возврат Команда.Опция(Имя, Значение, Описание);
КонецФункции
// Функция добавляет аргумент приложения и возвращает экземпляр данной аргумента
//
// Параметры:
// Имя - строка - имя аргумента, в строке допустимо использование только из БОЛЬШИХ латинских букв, например "ARG"
// Значение - строка - значение аргумента по умолчанию
// Описание - объект - описание аргумента для справки.
//
// Возвращаемое значение:
// Команда - класс ПараметрКоманды
//
// Дополнительно смотри справку по классу ПараметрКоманды
Функция Аргумент(Имя, Значение = "", Описание = "") Экспорт
Возврат Команда.Аргумент(Имя, Значение, Описание);
КонецФункции
// Предопределенная процедура выполнения приложения, если не задана процедура в классе.
// Выводит справку, по работе с приложением и завершает работу с кодом "1"
// Переопределяется, процедурой "УстановитьОсновноеДействие"
//
// Параметры:
// Команда - класс КомандаПриложения - инстанс класс, для доступа к опция и аргументам выполняемой команды
//
Процедура ВыполнитьКоманду(Знач Команда) Экспорт
Сообщить("Не корректное использование"+ Символы.ПС);
Команда.ВывестиСправку();
ЗавершитьРаботу(1);
КонецПроцедуры
Процедура ВывестиВерсию()
Сообщить(ВерсияПриложения);
КонецПроцедуры
Функция ФлагУстановлен(Знач АргументыCLI, Знач ОпцияФлаг)
Если АргументыCLI.Количество() = 0 Тогда
Возврат Ложь;
КонецЕсли;
МассивИменОпции = ОпцияФлаг.НаименованияПараметров;
Для каждого ИмяФлага Из МассивИменОпции Цикл
Если АргументыCLI[0] = ИмяФлага Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
Процедура ПриСозданииОбъекта(Знач Наименование, Знач Описание, Знач КлассРеализацииОсновныйКоманды = Неопределено)
НаименованиеПриложения = Наименование;
ОписаниеПриложения = Описание;
Если КлассРеализацииОсновныйКоманды = Неопределено Тогда
КлассРеализацииОсновныйКоманды = ЭтотОбъект;
КонецЕсли;
Команда = Новый КомандаПриложения(Наименование, Описание, КлассРеализацииОсновныйКоманды, ЭтотОбъект);
КонецПроцедуры

View File

@@ -0,0 +1,643 @@
#Использовать logos
// Имя параметра команды
// первая строка из массива строк, переданных при создании
Перем Имя Экспорт; // Строка
// Описание параметра команды
// Используется при выводе справки
Перем Описание Экспорт; // Строка
// Подробное описание параметра команды
// Используется при выводе справки (запланировано)
Перем ПодробноеОписаниеПараметра Экспорт; // Строка
// Содержит имя переменной окружения, откуда получать значение
// допустимо использование нескольких переменных окружения через пробел
// Используется при выводе справки
Перем ПеременнаяОкружения Экспорт; // Строка
// Содержит синонимов параметра команды
Перем Синонимы Экспорт; // Массив
// Содержит нормализованные наименования параметров
// для опций ("f force"):
// "-f", "--force"
// для аргументов ("ARG"):
// "ARG"
Перем НаименованияПараметров Экспорт; // Массив
// Определяет необходимость показа значения по умолчанию параметра в справке.
// Значение "Истина" скрывает в справке, по умолчанию "Ложь"
Перем СкрытьЗначение Экспорт; // булево
// Содержит признак истина, если значение получено из переменной окружения
Перем УстановленаИзПеременнойОкружения Экспорт; // булево
// Содержит признак истина, если значение установлено пользователем в строке использования
Перем УстановленаПользователем Экспорт; // булево
// Признак обязательности установки значения пользователем в строке использования
// при "истина", если значение не передано явно, будет вызывать исключение
Перем ТребоватьУстановкиПользователем Экспорт;
// Содержит значение параметра
// В том числе установленное значение по умолчанию
Перем Значение Экспорт; // Произвольный
// Содержит тип параметра
Перем ТипОпции Экспорт; // Тип
// Содержит тип элементов значения параметра, если ТипОпции = Тип("Массив")
Перем ТипЭлементаОпции Экспорт; // Тип
Перем НеОбязательныйПараметр; // Булево
Перем ТипПараметра; // Опция и аргумент
Перем ТипЗначенияПараметра; // Произвольный класс реализуемые несколько обязательных методов
Перем РазделительМассива; // Строка
Перем Лог;
Процедура ПриСозданииОбъекта(ВходящийТипПараметра,
ПолноеИмя,
ЗначениеПоУмолчанию = "",
ОписаниеПараметра = "",
ПеременнаяОкруженияПараметра = "")
Синонимы = СтрРазделить(ПолноеИмя, " ", Ложь);
Имя = Синонимы[0];
Значение = ЗначениеПоУмолчанию;
Описание = ОписаниеПараметра;
ПеременнаяОкружения = ПеременнаяОкруженияПараметра;
СкрытьЗначение = Ложь;
ТипОпции = ТипЗнч(ЗначениеПоУмолчанию);
ТипЭлементаОпции = ТипОпции;
Если ТипОпции = Тип("Булево")
ИЛИ НЕ ВходящийТипПараметра = "опция"Тогда
СкрытьЗначение = Истина;
КонецЕсли;
ТипЗначенияПоУмолчанию = ТипЗнч(ЗначениеПоУмолчанию);
ВстроенныеТипы = ВстроенныеТипЗначенийПараметров();
ОпределенныйТип = ВстроенныеТипы[Строка(ТипЗначенияПоУмолчанию)];
ТипЗначенияПараметра = ?(ОпределенныйТип = Неопределено, Новый ТипСтрока, Новый (ОпределенныйТип));
УстановленаПользователем = Ложь;
УстановленаИзПеременнойОкружения = Ложь;
НеОбязательныйПараметр = Истина;
Если ВходящийТипПараметра = "аргумент" Тогда
НеОбязательныйПараметр = Ложь;
КонецЕсли;
ТипПараметра = ВходящийТипПараметра;
РазделительМассива = Неопределено;
ПодробноеОписаниеПараметра = "";
ПодготовитьНаименованияПараметров();
КонецПроцедуры
// Возвращает истина, если тип параметра Массив
//
// Возвращаемое значение:
// булево - выполняется проверка на тип "Массив",
// * Истина - если типы совпадают
// * Ложь - во всех остальных случаях
Функция ЭтоМассив() Экспорт
Возврат ТипОпции = Тип("Массив");
КонецФункции
// Процедура очищает, Значение параметра, для типа Массив
//
Процедура Очистить() Экспорт
Если Не ЭтоМассив() Тогда
Возврат;
КонецЕсли;
Значение.Очистить();
КонецПроцедуры
// Возвращает строковое представление значения параметра
//
// Возвращаемое значение:
// Строковое представление - строка - вызывает у класса значения параметра функцию "ВСтроку"
Функция ЗначениеВСтроку() Экспорт
Возврат ТипЗначенияПараметра.ВСтроку(Значение);
КонецФункции
// Возвращает подробное описание для справки
//
// Возвращаемое значение:
// Подробное описание - строка - вызывает у класса значения параметра функцию "ПодробноеОписание"
Функция ПолучитьПодробноеОписание() Экспорт
ВстроенныеТипы = ВстроенныеТипЗначенийПараметров();
ОпределенныйТип = ВстроенныеТипы[Строка(ТипЗнч(ТипЗначенияПараметра))];
Если ОпределенныйТип = Неопределено
Или Тип("ТипПеречисление") = ОпределенныйТип Тогда
ПодробноеОписаниеПараметра = ТипЗначенияПараметра.ПодробноеОписание();
КонецЕсли;
Возврат ПодробноеОписаниеПараметра;
КонецФункции
// Возвращает истина, если данный параметр обязателен для указания
//
// Возвращаемое значение:
// Обязательный параметр - булево - получает обязательность параметра
Функция ПолучитьОбязательностьВвода() Экспорт
Возврат НЕ НеОбязательныйПараметр;
КонецФункции
// Процедура устанавливает значение параметра из входящего значения
// приводить к необходимому типу
//
// Параметры:
// ВходящееЗначение - строка - полученная строка при парсинге строки использования
Процедура УстановитьЗначение(ВходящееЗначение) Экспорт
Если ЭтоМассив()
И Не РазделительМассива = Неопределено Тогда
МассивСтрок = СтрРазделить(ВходящееЗначение, РазделительМассива);
Для каждого ЭлементМассива Из МассивСтрок Цикл
Значение = ТипЗначенияПараметра.УстановитьЗначение(ЭлементМассива, Значение);
КонецЦикла;
Иначе
Значение = ТипЗначенияПараметра.УстановитьЗначение(ВходящееЗначение, Значение);
КонецЕсли;
УстановленаПользователем = Истина;
КонецПроцедуры
// Процедура устанавливает значение параметра из переменной окружения
//
Процедура ИзПеременнойОкружения() Экспорт
Если ПустаяСтрока(ПеременнаяОкружения) Тогда
Возврат;
КонецЕсли;
МассивПеременныхОК = СтрРазделить(ПеременнаяОкружения, " ");
Для каждого ПеременнаяО Из МассивПеременныхОК Цикл
ЗначениеИзПеременнойОкружения = ПолучитьПеременнуюСреды(ПеременнаяО);
Если ЗначениеЗаполнено(ЗначениеИзПеременнойОкружения) Тогда
УстановленаИзПеременнойОкружения = Истина;
УстановитьЗначение(ЗначениеИзПеременнойОкружения);
КонецЕсли;
КонецЦикла;
УстановленаПользователем = Ложь;
КонецПроцедуры
#Область Текучих_функций
// Функция устанавливает переменную окружения для параметра команды
// возвращает текущий параметр команды
//
// Параметры:
// СтрокаПеременнаяОкружения - строка - имя переменной окружения, откуда получать значение
// допустимо использование нескольких переменных окружения через пробел
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
Функция ВОкружении(Знач СтрокаПеременнаяОкружения) Экспорт
ПеременнаяОкружения = СтрокаПеременнаяОкружения;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает признак скрытости значения по умолчанию в справке
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
Функция СкрытьВСправке() Экспорт
СкрытьЗначение = Истина;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает значение по умолчанию
// возвращает текущий параметр команды
//
// Параметры:
// ВходящееЗначение - произвольный - значение параметра по умолчанию
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
Функция ПоУмолчанию(ВходящееЗначение) Экспорт
Значение = ВходящееЗначение;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает тип параметра "Булево"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
Функция Флаговый() Экспорт
Возврат ТБулево();
КонецФункции
// Функция устанавливает тип параметра "Булево"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
Функция Флаг() Экспорт
Возврат ТБулево();
КонецФункции
// Функция устанавливает тип параметра "Булево"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
Функция ТБулево() Экспорт
ТипОпции = Тип("Булево");
ТипЭлементаОпции = Тип("Булево");
СкрытьЗначение = Истина;
ТипЗначенияПараметра = Новый ТипБулево();
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает тип параметра "Дата"
// возвращает текущий параметр команды
//
// Параметры:
// ФорматДаты - Строка - формат даты, при приведении к дате из строки параметра по умолчанию (yyyy-MM-dd_HH:mm:ss)
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
Функция ТДата(Знач ФорматДаты = "yyyy-MM-dd_HH:mm:ss" ) Экспорт
ТипОпции = Тип("Дата");
ТипЭлементаОпции = Тип("Дата");
ТипЗначенияПараметра = Новый ТипДатаВремя(ФорматДаты);
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает тип параметра "Число"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
Функция ТЧисло() Экспорт
ТипОпции = Тип("Число");
ТипЭлементаОпции = ТипОпции;
ТипЗначенияПараметра = Новый ТипЧисло();
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает тип параметра "Строка"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
Функция ТСтрока() Экспорт
ТипОпции = Тип("Строка");
ТипЭлементаОпции = ТипОпции;
ТипЗначенияПараметра = Новый ТипСтрока();
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает тип параметра "Массив" элементы "Дата"
// возвращает текущий параметр команды
//
// Параметры:
// ФорматДаты - Строка - формат даты, при приведении к дате из строки параметра по умолчанию (yyyy-MM-dd_HH:mm:ss)
// ВходящийРазделительМассива - символ - используется для разделения параметров при парсинге строки
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
Функция ТМассивДат(Знач ФорматДаты = "yyyy-MM-dd_HH:mm:ss", Знач ВходящийРазделительМассива = Неопределено) Экспорт
ТипОпции = Тип("Массив");
ТипЭлементаОпции = Тип("Дата");
ТипЗначенияПараметра = Новый ТипМассивДат(ФорматДаты);
Значение = Новый Массив;
Если Не ВходящийРазделительМассива = Неопределено Тогда
РазделительМассива = ВходящийРазделительМассива;
КонецЕсли;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает тип параметра "Массив" элементы "Число"
// возвращает текущий параметр команды
//
// Параметры:
// ВходящийРазделительМассива - символ - используется для разделения параметров при парсинге строки
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
Функция ТМассивЧисел(Знач ВходящийРазделительМассива = Неопределено) Экспорт
ТипОпции = Тип("Массив");
ТипЭлементаОпции = Тип("Число");
ТипЗначенияПараметра = Новый ТипМассивЧисел();
Значение = Новый Массив;
Если Не ВходящийРазделительМассива = Неопределено Тогда
РазделительМассива = ВходящийРазделительМассива;
КонецЕсли;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает тип параметра "Массив" элементы "Строки"
// возвращает текущий параметр команды
//
// Параметры:
// ВходящийРазделительМассива - символ - используется для разделения параметров при парсинге строки
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
Функция ТМассивСтрок(Знач ВходящийРазделительМассива = Неопределено) Экспорт
ТипОпции = Тип("Массив");
ТипЭлементаОпции = Тип("Строка");
ТипЗначенияПараметра = Новый ТипМассивСтрок();
Значение = Новый Массив;
Если Не ВходящийРазделительМассива = Неопределено Тогда
РазделительМассива = ВходящийРазделительМассива;
КонецЕсли;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает тип параметра "Массив" элементы "Булево"
// возвращает текущий параметр команды
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
Функция ТМассивБулево() Экспорт
ТипОпции = Тип("Массив");
ТипЭлементаОпции = Тип("Булево");
ТипЗначенияПараметра = Новый ТипМассивБулево();
Значение = Новый Массив;
СкрытьЗначение = Истина;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает описание параметра для справки
// возвращает текущий параметр команды
//
// Параметры:
// НовыеОписание - строка - строка с новым описанием, отличным от переданного в момент создания
//
// Возвращаемое значение:
// ПараметрКоманды - Объект - ссылка текущий класс "ПараметрКоманды" значение из переменной ЭтотОбъект
Функция Описание(Знач НовыеОписание) Экспорт
Описание = НовыеОписание;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает дополнительный синоним/псевдоним параметра для справки
// возвращает текущий параметр команды
//
// Параметры:
// СтрокаПсевдонима - строка - строка с новым псевдонимом, отличным от переданного в момент создания
//
// Возвращаемое значение:
// ПараметрКоманды - Объект - ссылка текущий класс "ПараметрКоманды" значение из переменной ЭтотОбъект
Функция Псевдоним(СтрокаПсевдонима) Экспорт
Если Синонимы.Найти(СтрокаПсевдонима) = Неопределено Тогда
Синонимы.Добавить(СтрокаПсевдонима);
ПодготовитьНаименованияПараметров();
КонецЕсли;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает признак обязательности указания данного параметра
// возвращает текущий параметр команды
//
// Параметры:
// Признак - булево - признак обязательности указания данного параметра (по умолчанию Истина)
//
// Возвращаемое значение:
// ПараметрКоманды - Объект - ссылка текущий класс "ПараметрКоманды" значение из переменной ЭтотОбъект
Функция Обязательный(Знач Признак = Истина) Экспорт
ТребоватьУстановкиПользователем = Признак;
НеОбязательныйПараметр = Не Признак;
Возврат ЭтотОбъект;
КонецФункции
// (ЗАГОТОВКА) Функция устанавливает путь и место в файле при получении настроек
// возвращает текущий параметр команды
//
// Параметры:
// ПутьКФайлу - строка - путь к файлу для чтения
// МестоВФайле - строка - путь в файле, в формате "general.force"
//
// Возвращаемое значение:
// ПараметрКоманды - Объект - ссылка текущий класс "ПараметрКоманды" значение из переменной ЭтотОбъект
Функция ВФайле(Знач ПутьКФайлу, Знач МестоВФайле) Экспорт
Лог.Отладка("Данная функция не реализована!!
|ПутьКФайлу: <%1>
|МестоВФайле: <%2>
|", ПутьКФайлу, МестоВФайле);
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает произвольный тип параметра
// возвращает текущий параметр команды
//
// Параметры:
// ВходящийКлассЗначенияПараметра - класс - Произвольный класс, реализующий ряд обязательных функций
// ВходящийТипПараметра - тип - тип значения параметра
// ВходящийТипЭлементаПараметра - Тип - тип элементов значения параметра, если тип Массив
//
// Возвращаемое значение:
// ПараметрКоманды - Объект - ссылка текущий класс "ПараметрКоманды" значение из переменной ЭтотОбъект
Функция ПроизвольныйТип(Знач ВходящийКлассЗначенияПараметра,
Знач ВходящийТипПараметра,
ВходящийТипЭлементаПараметра = Неопределено) Экспорт
ТипОпции = ВходящийТипПараметра;
ТипЭлементаОпции = ВходящийТипЭлементаПараметра;
ТипЗначенияПараметра = ВходящийКлассЗначенияПараметра;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает тип параметра "Перечисление"
// возвращает текущий параметр команды
//
// Параметры:
// ДоступныеПеречисления - Соответствие - Доступные перечисления
// * Ключ - Строка
// * Значение - Структура ("Наименование, Значение, ДополнительнаяСправка")
// Возвращаемое значение:
// ПараметрКоманды - Объект - ссылка текущий класс "ПараметрКоманды" значение из переменной ЭтотОбъект
// Вызов необязателен, автоматически определяется при создании параметра,
// если передано значение по умолчанию
Функция ТПеречисление(Знач ДоступныеПеречисления = Неопределено) Экспорт
ТипОпции = ТипЗнч(Неопределено);
ТипЭлементаОпции = ТипОпции;
ТипЗначенияПараметра = Новый ТипПеречисление();
Если Не ДоступныеПеречисления = Неопределено Тогда
ТипЗначенияПараметра.УстановитьПеречисления(ДоступныеПеречисления);
КонецЕсли;
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает произвольный тип параметра
// возвращает текущий параметр команды
//
// Параметры:
// НаименованиеПеречисления - строка - пользовательное значение перечисления
// ЗначениеПеречисления - произвольный - системное значение перечисления
// ДополнительнаяСправкаПеречисления - строка - дополнительная строка для справки
//
// Возвращаемое значение:
// ПараметрКоманды - Объект - ссылка текущий класс "ПараметрКоманды" значение из переменной ЭтотОбъект
Функция Перечисление(Знач НаименованиеПеречисления,
Знач ЗначениеПеречисления = Неопределено,
Знач ДополнительнаяСправкаПеречисления = "") Экспорт
Если Не ТипЗнч(ТипЗначенияПараметра) = Тип("ТипПеречисление") Тогда
ВызватьИсключение "Указание перечисления допустимо только для типа параметра перечисление";
КонецЕсли;
Если ЗначениеПеречисления = Неопределено Тогда
ЗначениеПеречисления = НаименованиеПеречисления;
КонецЕсли;
ТипЗначенияПараметра.ДобавитьПеречисление(НаименованиеПеречисления,
ЗначениеПеречисления,
ДополнительнаяСправкаПеречисления);
Возврат ЭтотОбъект;
КонецФункции
// Функция устанавливает подробное описание параметра для справки
// возвращает текущий параметр команды
//
// Параметры:
// ВходящееПодробноеОписание - строка - строка с новым описанием, отличным от переданного в момент создания
//
// Возвращаемое значение:
// ПараметрКоманды - значение из переменной ЭтотОбъект
//
Функция ПодробноеОписание(Знач ВходящееПодробноеОписание) Экспорт
ПодробноеОписаниеПараметра = ВходящееПодробноеОписание;
Возврат ЭтотОбъект;
КонецФункции
#КонецОбласти
Функция ВстроенныеТипЗначенийПараметров()
ВстроенныеТипы = Новый Соответствие;
ВстроенныеТипы.Вставить("Булево", Тип("ТипБулево"));
ВстроенныеТипы.Вставить("Число", Тип("ТипЧисло"));
ВстроенныеТипы.Вставить("Строка", Тип("ТипСтрока"));
ВстроенныеТипы.Вставить("ТипБулево", Тип("ТипБулево"));
ВстроенныеТипы.Вставить("ТипЧисло", Тип("ТипЧисло"));
ВстроенныеТипы.Вставить("ТипДатаВремя", Тип("ТипДатаВремя"));
ВстроенныеТипы.Вставить("ТипСтрока", Тип("ТипСтрока"));
ВстроенныеТипы.Вставить("ТипМассивЧисел", Тип("ТипМассивЧисел"));
ВстроенныеТипы.Вставить("ТипМассивСтрок", Тип("ТипМассивСтрок"));
ВстроенныеТипы.Вставить("ТипМассивДат", Тип("ТипМассивДат"));
ВстроенныеТипы.Вставить("ТипМассивБулево", Тип("ТипМассивБулево"));
ВстроенныеТипы.Вставить("ТипПеречисление", Тип("ТипПеречисление"));
Возврат ВстроенныеТипы;
КонецФункции
Процедура ПодготовитьНаименованияПараметров()
НаименованияПараметров = Новый Массив;
Для каждого ИмяСинонима Из Синонимы Цикл
Префикс = "";
Если ТипПараметра = "опция" Тогда
Префикс = "-";
Если СтрДлина(ИмяСинонима) > 1 Тогда
Префикс = "--";
КонецЕсли;
КонецЕсли;
НаименованияПараметров.Добавить(Префикс + ИмяСинонима);
КонецЦикла;
КонецПроцедуры
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_params");

30
lib/cli/tasks/coverage.os Normal file
View File

@@ -0,0 +1,30 @@
#Использовать coverage
#Использовать 1commands
#Использовать fs
ФС.ОбеспечитьПустойКаталог("coverage");
ПутьКСтат = "coverage/stat.json";
Команда = Новый Команда;
Команда.УстановитьКоманду("oscript");
Команда.ДобавитьПараметр("-encoding=utf-8");
Команда.ДобавитьПараметр(СтрШаблон("-codestat=%1", ПутьКСтат));
Команда.ДобавитьПараметр("tasks/test.os");
Команда.ПоказыватьВыводНемедленно(Истина);
КодВозврата = Команда.Исполнить();
Файл_Стат = Новый Файл(ПутьКСтат);
ИмяПакета = "cli";
ПроцессорГенерации = Новый ГенераторОтчетаПокрытия();
ПроцессорГенерации.ОтносительныеПути()
.ФайлСтатистики(Файл_Стат.ПолноеИмя)
.GenericCoverage()
.Cobertura()
.Clover(ИмяПакета)
.Сформировать();
ЗавершитьРаботу(КодВозврата);

87
lib/cli/tasks/test.os Normal file
View File

@@ -0,0 +1,87 @@
#Использовать "../src/core"
#Использовать 1bdd
#Использовать 1testrunner
#Использовать fs
Функция ПрогнатьТесты()
Тестер = Новый Тестер;
ПутьКТестам = ОбъединитьПути(ТекущийСценарий().Каталог, "..", "tests");
ПутьКОтчетуJUnit = ОбъединитьПути(ТекущийСценарий().Каталог, "..", "tests-reports");
ФС.ОбеспечитьПустойКаталог(ПутьКОтчетуJUnit);
КаталогТестов = Новый Файл(ПутьКТестам);
Если Не КаталогТестов.Существует() Тогда
Сообщить(СтрШаблон("Не найден каталог тестов %1", ПутьКТестам));
Возврат Истина;
КонецЕсли;
РезультатТестирования = Тестер.ТестироватьКаталог(
КаталогТестов,
Новый Файл(ПутьКОтчетуJUnit)
);
Успешно = РезультатТестирования = 0;
Возврат Успешно;
КонецФункции // ПрогнатьТесты()
Функция ПрогнатьФичи()
ПутьОтчетаJUnit = "./bdd-log.xml";
КаталогФич = ОбъединитьПути(".", "features");
Файл_КаталогФич = Новый Файл(КаталогФич);
Если Не Файл_КаталогФич.Существует() Тогда
Сообщить(СтрШаблон("Не найден каталог фич %1", КаталогФич));
Возврат Истина;
КонецЕсли;
ИсполнительБДД = Новый ИсполнительБДД;
РезультатыВыполнения = ИсполнительБДД.ВыполнитьФичу(Файл_КаталогФич, Файл_КаталогФич);
ИтоговыйРезультатВыполнения = ИсполнительБДД.ПолучитьИтоговыйСтатусВыполнения(РезультатыВыполнения);
СтатусВыполнения = ИсполнительБДД.ВозможныеСтатусыВыполнения().НеВыполнялся;
Если РезультатыВыполнения.Строки.Количество() > 0 Тогда
СтатусВыполнения = ИсполнительБДД.ПолучитьИтоговыйСтатусВыполнения(РезультатыВыполнения);
КонецЕсли;
ГенераторОтчетаJUnit = Новый ГенераторОтчетаJUnit;
ГенераторОтчетаJUnit.Сформировать(РезультатыВыполнения, СтатусВыполнения, ПутьОтчетаJUnit);
Сообщить(СтрШаблон("Результат прогона фич <%1>
|", ИтоговыйРезультатВыполнения));
Возврат ИтоговыйРезультатВыполнения <> ИсполнительБДД.ВозможныеСтатусыВыполнения().Сломался;
КонецФункции // ПрогнатьФичи()
Попытка
ТестыПрошли = ПрогнатьТесты();
Исключение
ТестыПрошли = Ложь;
Сообщить(СтрШаблон("Тесты через 1testrunner выполнены неудачно
|%1", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
КонецПопытки;
ФичиПрошли = Истина;
Попытка
ФичиПрошли = ПрогнатьФичи();
Исключение
ФичиПрошли = Ложь;
Сообщить(СтрШаблон("Тесты поведения через 1bdd выполнены неудачно
|%1", ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
КонецПопытки;
Если Не ТестыПрошли Или Не ФичиПрошли Тогда
ВызватьИсключение "Тестирование завершилось неудачно!";
Иначе
Сообщить(СтрШаблон("Результат прогона тестов <%1>
|", ТестыПрошли));
КонецЕсли;

View File

@@ -0,0 +1,16 @@
Перем МассивДат Экспорт;
Процедура ПриСозданииОбъекта()
КонецПроцедуры
Процедура ОписаниеКоманды(КомандаПриложения) Экспорт
ТекКоманда = КомандаПриложения.Опция("a datearray",,"Массив дат");
ТекКоманда.ТМассивДат("yyyy-MM-dd", ";");
КонецПроцедуры
Процедура ВыполнитьКоманду(КомандаПриложения) Экспорт
МассивДат = КомандаПриложения.ЗначениеОпции("a")
КонецПроцедуры

View File

@@ -0,0 +1,32 @@
#Использовать "../../src/core"
Процедура ВыполнитьПриложение()
Приложение = Новый КонсольноеПриложение( "my-tests",
"Мое описание");
Приложение.Версия("v version", "0.1.0");
// Приложение.ДобавитьКоманду(
// "m make", "",
// Новый );
// Приложение.УстановитьОсновноеДействие(ЭтотОбъект);
Приложение.Запустить(АргументыКоманднойСтроки);
КонецПроцедуры // ВыполнениеКоманды()
// Процедура ВыполнитьКоманду(Знач КомандаПриложения) Экспорт
// КомандаПриложения.ВывестиСправку();
// КонецПроцедуры
Попытка
ВыполнитьПриложение();
ЗавершитьРаботу(0);
Исключение
Сообщить(ОписаниеОшибки());
ЗавершитьРаботу(1);
КонецПопытки;

View File

@@ -0,0 +1,133 @@
#использовать "../src/core"
#Использовать asserts
#Использовать logos
Перем юТест;
Перем Лог;
Функция ПолучитьСписокТестов(Знач Тестирование) Экспорт
юТест = Тестирование;
ИменаТестов = Новый Массив;
ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсингАргументов");
ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсингАргументовПослеСбросаОпций");
Возврат ИменаТестов;
КонецФункции
Процедура ТестДолжен_ПроверитьПарсингАргументов() Экспорт
ARG = Аргумент("ARG", Ложь).Флаг();
SRC = Аргумент("SRC", "").ТСтрока();
INT = Аргумент("INT", "").ТЧисло();
DATE = Аргумент("DATE", "").ТДата();
ИндексАргументов = Новый Соответствие;
ИндексАргументов.Вставить("ARG", ARG);
ИндексАргументов.Вставить("SRC", SRC);
ИндексАргументов.Вставить("INT", INT);
ИндексАргументов.Вставить("DATE", DATE);
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f x", "-f", Неопределено));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("a", "", "a"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("", "", Неопределено));
Для каждого Тест Из ТестовыеСлучаи Цикл
НачальноеКоличество = Тест.Аргументы.Количество();
Лог.Отладка("Проверяю тестовый случай: %1", СтрСоединить(Тест.Аргументы, " "));
Для каждого КлючЗначение Из ИндексАргументов Цикл
Парсер_Аргумента = Новый АргументыПарсера(КлючЗначение.Значение);
Утверждения.ПроверитьРавенство(КлючЗначение.Ключ, Парсер_Аргумента.ВСтроку(), "Парсер аргументов должен быть равен "+ КлючЗначение.Ключ);
Контекст = Новый КонтекстПарсеров();
Результат = Парсер_Аргумента.Поиск(Тест.Аргументы, Контекст);
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
Если Тест.ЗначениеОпции = Неопределено Тогда
Утверждения.ПроверитьЛожь(Результат.РезультатПоиска, "Аргумент не должен быть найден");
Иначе
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Аргумент должен быть найден");
Утверждения.ПроверитьРавенство(1, Контекст.Аргументы[Парсер_Аргумента.Аргумент].Количество(), "Количество результатов должно быть 1");
Утверждения.ПроверитьРавенство(Контекст.Аргументы[Парсер_Аргумента.Аргумент][0], Тест.ЗначениеОпции, "Ожидаемые результаты должны быть равны");
Утверждения.ПроверитьРавенство(СтрСоединить(Результат.Аргументы, " "), СтрСоединить(Тест.АргументыВыхода, " "), "Аргументы выходные должны быть равны");
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функция ТестовыйСлучай(Знач Аргументы, Знач АргументыВыхода, Знач ЗначениеОпции)
Тест = Новый Структура;
Тест.Вставить("Аргументы", СтрРазделить(Аргументы," "));
Тест.Вставить("АргументыВыхода", СтрРазделить(АргументыВыхода," "));
Тест.Вставить("ЗначениеОпции", ЗначениеОпции);
Возврат Тест;
КонецФункции
Процедура ТестДолжен_ПроверитьПарсингАргументовПослеСбросаОпций() Экспорт
ARG = Аргумент("ARG", Ложь).Флаг();
SRC = Аргумент("SRC", "").ТСтрока();
INT = Аргумент("INT", "").ТЧисло();
DATE = Аргумент("DATE", "").ТДата();
ИндексАргументов = Новый Соответствие;
ИндексАргументов.Вставить("ARG", ARG);
ИндексАргументов.Вставить("SRC", SRC);
ИндексАргументов.Вставить("INT", INT);
ИндексАргументов.Вставить("DATE", DATE);
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f -x", "-x", "-f"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-a", "", "-a"));
Для каждого Тест Из ТестовыеСлучаи Цикл
НачальноеКоличество = Тест.Аргументы.Количество();
Лог.Отладка("Проверяю тестовый случай: %1", СтрСоединить(Тест.Аргументы, " "));
Для каждого КлючЗначение Из ИндексАргументов Цикл
Парсер_Аргумента = Новый АргументыПарсера(КлючЗначение.Значение);
Утверждения.ПроверитьРавенство(КлючЗначение.Ключ, Парсер_Аргумента.ВСтроку(), "Парсер аргументов должен быть равен "+ КлючЗначение.Ключ);
Контекст = Новый КонтекстПарсеров();
Контекст.СбросОпций = Истина;
Результат = Парсер_Аргумента.Поиск(Тест.Аргументы, Контекст);
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Аргумент должен быть найден");
Утверждения.ПроверитьРавенство(1, Контекст.Аргументы[Парсер_Аргумента.Аргумент].Количество(), "Количество результатов должно быть 1");
Утверждения.ПроверитьРавенство(Контекст.Аргументы[Парсер_Аргумента.Аргумент][0], Тест.ЗначениеОпции, "Ожидаемые результаты должны быть равны");
Утверждения.ПроверитьРавенство(СтрСоединить(Результат.Аргументы, " "), СтрСоединить(Тест.АргументыВыхода, " "), "Аргументы выходные должны быть равны");
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функция Аргумент(Наименование, ЗначениеПоУмолчанию)
Возврат Новый ПараметрКоманды("Аргумент", Наименование, ЗначениеПоУмолчанию, "Тестовый параметр f")
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_class_arg");
//Лог.УстановитьУровень(УровниЛога.Отладка);

View File

@@ -0,0 +1,212 @@
#использовать "../src/core"
#Использовать asserts
#Использовать logos
Перем юТест;
Перем Лог;
Функция ПолучитьСписокТестов(Знач Тестирование) Экспорт
юТест = Тестирование;
ИменаТестов = Новый Массив;
ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсингВсеОпции");
ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсингМассивовВсеОпции");
Возврат ИменаТестов;
КонецФункции
Функция ТестовыйСлучай(Знач Аргументы, Знач АргументыВыхода, Знач ЗначениеОпции)
Тест = Новый Структура;
Тест.Вставить("Аргументы", СтрРазделить(Аргументы," "));
Тест.Вставить("АргументыВыхода", СтрРазделить(АргументыВыхода," "));
Тест.Вставить("ЗначениеОпции", СтрРазделить(ЗначениеОпции," "));
Возврат Тест;
КонецФункции
Процедура ТестДолжен_ПроверитьПарсингВсеОпции() Экспорт
НаименованияОпции = Новый Массив;
НаименованияОпции.Добавить("-f");
НаименованияОпции.Добавить("-F");
НаименованияОпции.Добавить("--force");
НаименованияОпции.Добавить("-o");
НаименованияОпции.Добавить("--other");
МассивОпций = Новый Массив;
МассивОпций.Добавить(Опция("o other", "").ТСтрока());
МассивОпций.Добавить(Опция("o other", "").ТДата());
МассивОпций.Добавить(Опция("o other", "").ТЧисло());
ОпцияForce = Опция("f F force", Ложь).Флаг();
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f x", "x", "Истина null"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f=false y", "y", "Ложь null"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force x", "x", "Истина null"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force=true y", "y", "истина null"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-o x", "", "null x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-o=x y", "y", "null x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-ox y", "y", "null x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--other x", "", "null x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--other=x y", "y", "null x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f -o x y", "y", "истина x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-o x -f y", "y", "истина x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-fo x y", "y", "истина x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-foxxx y", "y", "истина xxx"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-Foxxx y", "y", "истина xxx"));
Для каждого Тест Из ТестовыеСлучаи Цикл
Для каждого ОпцияТеста Из МассивОпций Цикл
НачальноеКоличество = Тест.Аргументы.Количество();
Лог.Отладка("Проверяю тестовый случай: %1", СтрСоединить(Тест.Аргументы, " "));
Лог.Отладка("-> тип опции: %1", ОпцияForce.ТипОпции);
ИндексОпций = Новый Соответствие;
ИндексОпций.Вставить("-f", ОпцияForce);
ИндексОпций.Вставить("-F", ОпцияForce);
ИндексОпций.Вставить("--force", ОпцияForce);
ИндексОпций.Вставить("-o", ОпцияТеста);
ИндексОпций.Вставить("--other", ОпцияТеста);
Опции = Новый Соответствие;
Опции.Вставить(ОпцияТеста, ОпцияТеста);
Опции.Вставить(ОпцияForce, ОпцияForce);
АргументыТеста = Тест.Аргументы;
О_Парсера = Новый ВсеОпцииПарсера(Опции, ИндексОпций);
Утверждения.ПроверитьРавенство("-of", О_Парсера.ВСтроку(), "Парсер опции должен быть равен -of");
Контекст = Новый КонтекстПарсеров();
Результат = О_Парсера.Поиск(АргументыТеста, Контекст);
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Опции должны быть найдены");
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
Утверждения.ПроверитьРавенство(СтрСоединить(Результат.Аргументы, " "), СтрСоединить(Тест.АргументыВыхода, " "), "Аргументы выходные должны быть равны");
Если Не Контекст.Опции[ОпцияForce] = Неопределено Тогда
Утверждения.ПроверитьРавенство(Булево(Контекст.Опции[ОпцияForce][0]),Булево(Тест.ЗначениеОпции[0]), "Ожидаемые результаты опции --force должны быть равны");
КонецЕсли;
Если Не Контекст.Опции[ОпцияТеста] = Неопределено Тогда
Утверждения.ПроверитьРавенство(Контекст.Опции[ОпцияТеста][0], Тест.ЗначениеОпции[1], "Ожидаемые результаты опции теста должны быть равны");
КонецЕсли;
КонтекстСброса = Новый КонтекстПарсеров();
КонтекстСброса.СбросОпций = Истина;
Результат = О_Парсера.Поиск(АргументыТеста, КонтекстСброса);
Утверждения.ПроверитьЛожь(Результат.РезультатПоиска, "Любые опции не должны быть найдены");
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура ТестДолжен_ПроверитьПарсингМассивовВсеОпции() Экспорт
НаименованияОпции = Новый Массив;
НаименованияОпции.Добавить("-f");
НаименованияОпции.Добавить("--force");
НаименованияОпции.Добавить("-o");
НаименованияОпции.Добавить("--other");
МассивОпций = Новый Массив;
МассивОпций.Добавить(Опция("o other", "").ТМассивСтрок());
МассивОпций.Добавить(Опция("o other", "").ТМассивДат());
МассивОпций.Добавить(Опция("o other", "").ТМассивЧисел());
ОпцияForce = Опция("f force", Ложь).Флаг();
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f x", "x", "Истина null"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f=false y", "y", "Ложь null"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force x", "x", "Истина null"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force=true y", "y", "истина null"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-o x -o x2", "", "null x x2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-o=x -o=x2 y", "y", "null x x2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-o=x -o=x2 -y z", "-y z", "null x x2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-ox -ox2 y", "y", "null x x2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--other x --other x2", "", "null x x2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--other=x --other=x2 -y", "-y", "null x x2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f -o x -o x2 y", "y", "истина x x2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-o x -f -o x2 y", "y", "истина x x2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-o x -o x2 -f y", "y", "истина x x2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-fo x -o=x2 y", "y", "истина x x2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-foxxx -oxxx2 -y z", "-y z", "истина xxx xxx2"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-foxxx -oxxx2 z", "z", "истина xxx xxx2"));
Для каждого Тест Из ТестовыеСлучаи Цикл
Для каждого ОпцияТеста Из МассивОпций Цикл
НачальноеКоличество = Тест.Аргументы.Количество();
Лог.Отладка("Проверяю тестовый случай: %1", СтрСоединить(Тест.Аргументы, " "));
Лог.Отладка("-> тип опции: %1", ОпцияForce.ТипОпции);
ИндексОпций = Новый Соответствие;
ИндексОпций.Вставить("-f", ОпцияForce);
ИндексОпций.Вставить("--force", ОпцияForce);
ИндексОпций.Вставить("-o", ОпцияТеста);
ИндексОпций.Вставить("--other", ОпцияТеста);
Опции = Новый Соответствие;
Опции.Вставить(ОпцияТеста, ОпцияТеста);
Опции.Вставить(ОпцияForce, ОпцияForce);
АргументыТеста = Тест.Аргументы;
О_Парсера = Новый ВсеОпцииПарсера(Опции, ИндексОпций);
Утверждения.ПроверитьРавенство("-of", О_Парсера.ВСтроку(), "Парсер опции должен быть равен -of");
Контекст = Новый КонтекстПарсеров();
Результат = О_Парсера.Поиск(АргументыТеста, Контекст);
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Опции должны быть найдены");
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
Результат = О_Парсера.Поиск(АргументыТеста, Контекст);
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Опции должны быть найдены");
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
Утверждения.ПроверитьРавенство(СтрСоединить(Результат.Аргументы, " "), СтрСоединить(Тест.АргументыВыхода, " "), "Аргументы выходные должны быть равны");
Если Не Контекст.Опции[ОпцияForce] = Неопределено Тогда
Утверждения.ПроверитьРавенство(Булево(Контекст.Опции[ОпцияForce][0]),Булево(Тест.ЗначениеОпции[0]), "Ожидаемые результаты опции --force должны быть равны");
КонецЕсли;
Если Не Контекст.Опции[ОпцияТеста] = Неопределено Тогда
Утверждения.ПроверитьРавенство(Контекст.Опции[ОпцияТеста][0], Тест.ЗначениеОпции[1], "Ожидаемые результаты опции теста должны быть равны");
Утверждения.ПроверитьРавенство(Контекст.Опции[ОпцияТеста][1], Тест.ЗначениеОпции[2], "Ожидаемые результаты опции теста должны быть равны");
КонецЕсли;
КонтекстСброса = Новый КонтекстПарсеров();
КонтекстСброса.СбросОпций = Истина;
Результат = О_Парсера.Поиск(АргументыТеста, КонтекстСброса);
Утверждения.ПроверитьЛожь(Результат.РезультатПоиска, "Любые опции не должны быть найдены");
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функция Опция(Наименование, ЗначениеПоУмолчанию)
Возврат Новый ПараметрКоманды("опция", Наименование, ЗначениеПоУмолчанию, "Тестовый параметр f")
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_class_options");
//Лог.УстановитьУровень(УровниЛога.Отладка);

View File

@@ -0,0 +1,559 @@
#использовать "../src/core"
#Использовать asserts
#Использовать logos
#Использовать delegate
Перем юТест;
Перем Лог;
Функция ПолучитьСписокТестов(Знач Тестирование) Экспорт
юТест = Тестирование;
ИменаТестов = Новый Массив;
// Скорость выполнения команды
ИменаТестов.Добавить("ТестДолжен_ПроверитьСкоростьРаботуКомандыПриложения");
// Работа с опциями и аргументами
// ИменаТестов.Добавить("ТестДолжен_ПроверитьПолучениеЗначенияАргументаПоИмени");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьПолучениеЗначенияОпцииПоИмени");
ИменаТестов.Добавить("ТестДолжен_ПроверитьУстановкуЗначенийОпций");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьУстановкуМножественныхЗначенийОпций");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьУстановкуЗначенийАргументов");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьУстановкуМножественныхАргументовОпций");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьГруппировкуОпций");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьНеобязательностьОпций");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьНеобязательностьАргументов");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьВзаимоисключающиеОпции");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьПовторяемыеВзаимоисключающиеОпции");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьРаботуСОднимТиреВАргументах");
ИменаТестов.Добавить("ТестДолжен_ПроверитьСбросОпцийПередАргументами");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьСбросМножественныхОпций");
ИменаТестов.Добавить("ТестДолжен_СтандартнуюСтрокуИспользования");
ИменаТестов.Добавить("ТестДолжен_СтандартнуюСтрокуИспользования_МассивАргументов");
ИменаТестов.Добавить("ТестДолжен_СтандартнуюСтрокуИспользования_МассивАргументовНесколькоАргументов");
ИменаТестов.Добавить("ТестДолжен_СтандартнуюСтрокуИспользования_ОбязательнаяОпция");
// ИменаТестов.Добавить("ТестДолжен_СложныеСлучаиФормированияСтрокиИспользования");
ИменаТестов.Добавить("ТестДолжен_ПроверитьВыводСправки");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьВыводВерсии");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьВыполнениеОбработчикаПередВыполнениемКоманды");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьВыполнениеОбработчикаПослеВыполненияКоманды");
ИменаТестов.Добавить("ТестДолжен_ПроверитьЧтениеОпцийИАргументовРодителяКомандыБезВызоваПроцедуры");
ИменаТестов.Добавить("ТестДолжен_ПроверитьЧтениеОпцийИАргументовРодителяКоманды");
ИменаТестов.Добавить("ТестДолжен_ПроверитьЧтениеОпцийИАргументовРодителяКомандыПервогоУровня");
Возврат ИменаТестов;
КонецФункции
Процедура ВыполнитьКоманду(Знач ВыполняемаяКоманда) Экспорт
Лог.Отладка("Полезная работа команды: %1", ВыполняемаяКоманда.ПолучитьИмяКоманды());
КонецПроцедуры
Процедура ТестДолжен_ПроверитьСкоростьРаботуКомандыПриложения() Экспорт
Спек = "[--login] [--realm] [--note] [--no-copy] [--gen [--length] [--min-length] [--max-length] [--no-upper] [--no-lower] [--no-digit] [--no-symbol] [--no-similar] [--min-upper] [--max-upper] [--min-lower] [--max-lower] [--min-digit] [--max-digit] [--min-symbol] [--max-symbol] [--exclude]]";
ИмяПроцедурыОбъекта = "КомандаСкоростьРаботуКомандыПриложения";
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("", Спек, Истина));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--gen", Спек, Истина));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--gen --length 42", Спек, Истина));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--length 42 --gen", Спек, Истина));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--min-length 10 --length 42 --gen", Спек, Истина));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--min-length 10 --no-symbol --no-lower --length 42 --gen", Спек, Истина));
Для каждого Тест Из ТестовыеСлучаи Цикл
РезультатВыполнения = ВыполненаКомандаПриложения(Тест.Спек, ИмяПроцедурыОбъекта, Тест.Аргументы);
Утверждения.ПроверитьРавенство(РезультатВыполнения, Тест.Результат, "Команда должна выполниться успешно! Входящие аргументы" + СтрСоединить(Тест.Аргументы));
КонецЦикла;
КонецПроцедуры
Процедура ТестДолжен_ПроверитьЧтениеОпцийИАргументовРодителяКомандыБезВызоваПроцедуры () Экспорт
Команда = ПодготовитьТестовуюКоманду();
ОпцияМассив = Команда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
АргументСтрока = Команда.Аргумент("ARG", "", "Тестовый простой необязательный аргумент").Обязательный(Ложь);
ВложеннаяКоманда = Команда.ДобавитьПодкоманду("sub s", "", ЭтотОбъект);
ОпцияМассив = ВложеннаяКоманда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
Аргументы = Новый Массив;
Аргументы.Добавить("-e=Знач1");
Аргументы.Добавить("-e=Знач2");
Аргументы.Добавить("-e=Знач3");
Аргументы.Добавить("ЗначениеАргумента");
Аргументы.Добавить("sub");
РезультатВыполнения = ВыполнитьКомандуПриложения(Команда, Аргументы);
Утверждения.ПроверитьИстину(РезультатВыполнения, "Команда должна выполниться");
Утверждения.ПроверитьРавенство(ВложеннаяКоманда.ЗначениеОпцииКомандыРодителя("e").Количество(), 3 , "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(ВложеннаяКоманда.ЗначениеОпции("e").Количество(), 0 , "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(ВложеннаяКоманда.ЗначениеАргумента("ARG"), "ЗначениеАргумента" , "Результат <АргументСтрока> должны совпадать");
КонецПроцедуры
Процедура ТестДолжен_ПроверитьЧтениеОпцийИАргументовРодителяКоманды() Экспорт
Команда = ПодготовитьТестовуюКоманду();
ОпцияМассив =Команда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
АргументСтрока = Команда.Аргумент("ARG", "", "Тестовый простой необязательный аргумент").Обязательный(Ложь);
ВложеннаяКоманда = Команда.ДобавитьПодкоманду("sub s", "", ЭтотОбъект);
Аргументы = Новый Массив;
Аргументы.Добавить("-e=Знач1");
Аргументы.Добавить("-e=Знач2");
Аргументы.Добавить("-e=Знач3");
Аргументы.Добавить("ЗначениеАргумента");
Аргументы.Добавить("sub");
РезультатВыполнения = ВыполнитьКомандуПриложения(Команда, Аргументы);
Утверждения.ПроверитьИстину(РезультатВыполнения, "Команда должна выполниться");
Утверждения.ПроверитьРавенство(ВложеннаяКоманда.ЗначениеОпцииКомандыРодителя("e").Количество(), 3 , "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(ВложеннаяКоманда.ЗначениеАргументаКомандыРодителя("ARG"), "ЗначениеАргумента" , "Результат <АргументСтрока> должны совпадать");
КонецПроцедуры
Процедура ТестДолжен_ПроверитьЧтениеОпцийИАргументовРодителяКомандыПервогоУровня() Экспорт
Команда = ПодготовитьТестовуюКоманду();
ОпцияМассив =Команда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
АргументСтрока = Команда.Аргумент("ARG", "", "Тестовый простой необязательный аргумент").Обязательный(Ложь);
ВложеннаяКоманда = Команда.ДобавитьПодкоманду("sub s", "", ЭтотОбъект);
ВложеннаяКоманда2 = ВложеннаяКоманда.ДобавитьПодкоманду("subsub ss", "", ЭтотОбъект);
Аргументы = Новый Массив;
Аргументы.Добавить("-e=Знач1");
Аргументы.Добавить("-e=Знач2");
Аргументы.Добавить("-e=Знач3");
Аргументы.Добавить("ЗначениеАргумента");
Аргументы.Добавить("sub");
Аргументы.Добавить("subsub");
РезультатВыполнения = ВыполнитьКомандуПриложения(Команда, Аргументы);
Утверждения.ПроверитьИстину(РезультатВыполнения, "Команда должна выполниться");
Утверждения.ПроверитьРавенство(ВложеннаяКоманда2.ЗначениеОпцииКомандыРодителя("e").Количество(), 3 , "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(ВложеннаяКоманда2.ЗначениеАргументаКомандыРодителя("ARG"), "ЗначениеАргумента" , "Результат <АргументСтрока> должны совпадать");
КонецПроцедуры
Процедура ТестДолжен_ПроверитьУстановкуЗначенийОпций() Экспорт
Спек = "";
ИмяПроцедурыОбъекта = "КомандаПростыеОпции";
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--bool", Спек, "Истина;;0"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--string Строка", Спек, "Ложь;Строка;0"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--int 42", Спек, "Ложь;;42"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--string Строка --bool", Спек, "Истина;Строка;0"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--int 42 --bool", Спек, "Истина;;42"));
Для каждого Тест Из ТестовыеСлучаи Цикл
Команда = ВыполнитьКомандаПриложения(Тест.Спек, ИмяПроцедурыОбъекта, Тест.Аргументы);
ЗначениеБулева = Команда.ЗначениеОпции("bool");
ЗначениеСтрока = Команда.ЗначениеОпции("string");
ЗначениеЧисло = Команда.ЗначениеОпции("int");
МассивРезультата = СтрРазделить(Тест.Результат, ";", Истина);
Утверждения.ПроверитьРавенство(ЗначениеБулева, Булево(МассивРезультата[0]), "Результаты должны совпадать" + СтрСоединить(Тест.Аргументы));
Утверждения.ПроверитьРавенство(ЗначениеСтрока, Строка(МассивРезультата[1]), "Результаты должны совпадать" + СтрСоединить(Тест.Аргументы));
Утверждения.ПроверитьРавенство(ЗначениеЧисло, Число(МассивРезультата[2]), "Результаты должны совпадать" + СтрСоединить(Тест.Аргументы));
КонецЦикла;
КонецПроцедуры
Процедура ТестДолжен_СтандартнуюСтрокуИспользования() Экспорт
Спек = "";
ИмяПроцедурыОбъекта = "КомандаПростыеОпции";
Команда = ПодготовитьТестовуюКоманду(Спек);
ОпцияМассив =Команда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
АргументСтрока = Команда.Аргумент("ARG", "", "Тестовый простой необязательный аргумент").Обязательный(Ложь);
Аргументы = Новый Массив;
Аргументы.Добавить("-e=Знач1");
Аргументы.Добавить("-e=Знач2");
Аргументы.Добавить("-e=Знач3");
Аргументы.Добавить("ЗначениеАргумента");
РезультатВыполнения = ВыполнитьКомандуПриложения(Команда, Аргументы);
Утверждения.ПроверитьИстину(РезультатВыполнения, "Команда должна выполниться");
Утверждения.ПроверитьРавенство(ОпцияМассив.Значение.Количество(), 3 , "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(АргументСтрока.Значение, "ЗначениеАргумента" , "Результат <АргументСтрока> должны совпадать");
Команда = ПодготовитьТестовуюКоманду(Спек);
ОпцияМассив =Команда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
АргументСтрока = Команда.Аргумент("ARG", "", "Тестовый простой необязательный аргумент").Обязательный(Ложь);
Аргументы = Новый Массив;
Аргументы.Добавить("-e=Знач1");
Аргументы.Добавить("-e=Знач2");
Аргументы.Добавить("-e=Знач3");
//Аргументы.Добавить("ЗначениеАргумента");
РезультатВыполнения = ВыполнитьКомандуПриложения(Команда, Аргументы);
Утверждения.ПроверитьИстину(РезультатВыполнения, "Команда должна выполниться");
Утверждения.ПроверитьРавенство(ОпцияМассив.Значение.Количество(), 3 , "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(АргументСтрока.Значение, "" , "Результат <АргументСтрока> должны совпадать");
КонецПроцедуры
Процедура ТестДолжен_СтандартнуюСтрокуИспользования_МассивАргументов() Экспорт
Спек = "";
ИмяПроцедурыОбъекта = "КомандаПростыеОпции";
Команда = ПодготовитьТестовуюКоманду(Спек);
ОпцияМассив =Команда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
АргументСтрока = Команда.Аргумент("ARG", "", "Тестовый простой необязательный аргумент").ТМассивСтрок().Обязательный(Ложь);
Аргументы = Новый Массив;
Аргументы.Добавить("-e=Знач1");
Аргументы.Добавить("-e=Знач2");
Аргументы.Добавить("-e=Знач3");
Аргументы.Добавить("ЗначениеАргумента");
Аргументы.Добавить("ЗначениеАргумента");
РезультатВыполнения = ВыполнитьКомандуПриложения(Команда, Аргументы);
Утверждения.ПроверитьИстину(РезультатВыполнения, "Команда должна выполниться");
Утверждения.ПроверитьРавенство(ОпцияМассив.Значение.Количество(), 3, "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(АргументСтрока.Значение.Количество(), 2, "Результат <АргументСтрока> должны совпадать");
// Необязательный массив
// Аргументы не переданы
Команда = ПодготовитьТестовуюКоманду(Спек);
ОпцияМассив =Команда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
АргументСтрока = Команда.Аргумент("ARG", "", "Тестовый простой необязательный аргумент").ТМассивСтрок().Обязательный(Ложь);
Аргументы = Новый Массив;
Аргументы.Добавить("-e=Знач1");
Аргументы.Добавить("-e=Знач2");
Аргументы.Добавить("-e=Знач3");
РезультатВыполнения = ВыполнитьКомандуПриложения(Команда, Аргументы);
Утверждения.ПроверитьИстину(РезультатВыполнения, "Команда должна выполниться");
Утверждения.ПроверитьРавенство(ОпцияМассив.Значение.Количество(), 3, "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(АргументСтрока.Значение.Количество(), 0, "Результат <АргументСтрока> должны совпадать");
// Просто массив
Команда = ПодготовитьТестовуюКоманду(Спек);
ОпцияМассив =Команда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
АргументСтрока = Команда.Аргумент("ARG", "", "Тестовый простой необязательный аргумент").ТМассивСтрок();
Аргументы = Новый Массив;
Аргументы.Добавить("-e=Знач1");
Аргументы.Добавить("-e=Знач2");
Аргументы.Добавить("-e=Знач3");
Аргументы.Добавить("ЗначениеАргумента");
Аргументы.Добавить("ЗначениеАргумента");
РезультатВыполнения = ВыполнитьКомандуПриложения(Команда, Аргументы);
Утверждения.ПроверитьИстину(РезультатВыполнения, "Команда должна выполниться");
Утверждения.ПроверитьРавенство(ОпцияМассив.Значение.Количество(), 3, "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(АргументСтрока.Значение.Количество(), 2, "Результат <АргументСтрока> должны совпадать");
КонецПроцедуры
Процедура ТестДолжен_СтандартнуюСтрокуИспользования_МассивАргументовНесколькоАргументов() Экспорт
Спек = "";
ИмяПроцедурыОбъекта = "КомандаПростыеОпции";
Команда = ПодготовитьТестовуюКоманду(Спек);
ОпцияМассив =Команда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
АргументСтрока = Команда.Аргумент("ARG", "", "Тестовый простой необязательный аргумент").ТМассивСтрок().Обязательный(Ложь);
АргументСтрока2 = Команда.Аргумент("ARG2", "", "Тестовый простой необязательный аргумент").Обязательный();
Аргументы = Новый Массив;
Аргументы.Добавить("-e=Знач1");
Аргументы.Добавить("-e=Знач2");
Аргументы.Добавить("-e=Знач3");
Аргументы.Добавить("ЗначениеАргумента");
Аргументы.Добавить("ЗначениеАргумента2");
РезультатВыполнения = ВыполнитьКомандуПриложения(Команда, Аргументы);
Утверждения.ПроверитьИстину(РезультатВыполнения, "Команда должна выполниться");
Утверждения.ПроверитьРавенство(ОпцияМассив.Значение.Количество(), 3, "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(АргументСтрока.Значение.Количество(), 1, "Результат <АргументСтрока> должны совпадать");
Утверждения.ПроверитьРавенство(АргументСтрока2.Значение, "ЗначениеАргумента2", "Результат <АргументСтрока2> должны совпадать");
КонецПроцедуры
Процедура ТестДолжен_СтандартнуюСтрокуИспользования_ОбязательнаяОпция() Экспорт
Команда = ПодготовитьТестовуюКоманду();
ОбычныйОпция = Команда.Опция("z", , "Необязательная опция").ТСтрока();
ОпцияМассив = Команда.Опция("e env", Новый Массив, "Тестовый необязательный массив опций").ТМассивСтрок();
ARG2 = Команда.Аргумент("ARG2", "", "Тестовый простой необязательный аргумент").ТМассивСтрок();
СтрокаИспользования = СокрЛП(Команда.ПолучитьСтрокуИспользования());
Утверждения.ПроверитьРавенство(СтрокаИспользования, "[ОПЦИИ] -- ARG2...", "Результат <СтрокаИспользования> должны совпадать");
Команда = ПодготовитьТестовуюКоманду();
ОбычныйОпция = Команда.Опция("z", , "Необязательная опция").ТСтрока();
ОпцияМассив = Команда.Опция("e env", Новый Массив, "Тестовый обязательный массив опций").ТМассивСтрок().Обязательный(Истина);
ARG2 = Команда.Аргумент("ARG2", "", "Тестовый простой необязательный аргумент").ТМассивСтрок();
СтрокаИспользования = СокрЛП(Команда.ПолучитьСтрокуИспользования());
Утверждения.ПроверитьРавенство(СтрокаИспользования, "[-z] -e... -- ARG2...", "Результат <СтрокаИспользования> должны совпадать");
Команда = ПодготовитьТестовуюКоманду();
ARG2 = Команда.Аргумент("ARG2", "", "Тестовый простой необязательный аргумент").ТМассивСтрок();
СтрокаИспользования = СокрЛП(Команда.ПолучитьСтрокуИспользования());
Утверждения.ПроверитьРавенство(СтрокаИспользования, "-- ARG2...", "Результат <СтрокаИспользования> должны совпадать");
КонецПроцедуры
Процедура ТестДолжен_ПроверитьВыводСправки() Экспорт
Спек = "";
Команда = ПодготовитьТестовуюКоманду(Спек);
ОпцияМассив = Команда.Опция("env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
АргументСтрока2 = Команда.Аргумент("ARG2", "", "Тестовый простой необязательный аргумент").Обязательный();
АргументСтрока = Команда.Аргумент("ARG", "", "Тестовый простой необязательный аргумент").ТМассивСтрок().Обязательный(Ложь);
ОпцияПеречисление = Команда.Опция("enum e em", "yellow", "Опция перечисление").ТПеречисление()
.Перечисление("yellow", "yellow", "Это желтый цвет")
.Перечисление("red", "red" , "Это красный цвет")
.Перечисление("blue", "blue", "Это синий цвет")
;
Команда.ВывестиСправку();
КонецПроцедуры
Процедура ТестДолжен_ПроверитьСбросОпцийПередАргументами() Экспорт
Команда = ПодготовитьТестовуюКоманду();
ОпцияМассив =Команда.Опция("e env", Новый Массив, "Тестовый массив опций").ТМассивСтрок();
ARG2 = Команда.Аргумент("ARG2", "", "Тестовый простой необязательный аргумент").ТМассивСтрок().Обязательный(Ложь);
Аргументы = Новый Массив;
Аргументы.Добавить("-e=Знач1");
Аргументы.Добавить("-e=Знач2");
Аргументы.Добавить("-e=Знач3");
Аргументы.Добавить("--");
Аргументы.Добавить("-v");
Аргументы.Добавить("ARG2");
Аргументы.Добавить("run");
РезультатВыполнения = ВыполнитьКомандуПриложения(Команда, Аргументы);
Утверждения.ПроверитьИстину(РезультатВыполнения, "Команда должна выполниться");
Утверждения.ПроверитьРавенство(ОпцияМассив.Значение.Количество(), 3, "Результат <ОпцияМассив> должны совпадать");
Утверждения.ПроверитьРавенство(ARG2.Значение.Количество(), 3, "Результат <ARG1> должны совпадать");
КонецПроцедуры
Функция ПодготовитьТестовуюКоманду(Спек = "")
Команда = Новый КомандаПриложения("testapp", "Тестовое приложения", ЭтотОбъект);
Если ЗначениеЗаполнено(Спек) Тогда
Команда.Спек = Спек;
КонецЕсли;
Возврат Команда;
КонецФункции
Функция АргументыИзСтроки(СтрокаАргументов)
Возврат СтрРазделить(СтрокаАргументов, " ");
КонецФункции
Функция ТестовыйСлучай(Знач Аргументы, Знач Спек, Знач Результат)
Тест = Новый Структура;
Тест.Вставить("Аргументы", СтрРазделить(Аргументы," "));
Тест.Вставить("Спек", Спек);
Тест.Вставить("Результат", Результат);
Возврат Тест;
КонецФункции
Функция ВыполнитьКомандуПриложения(Команда, Аргументы)
Команда.НачалоЗапуска();
Попытка
Команда.Запуск(Аргументы);
Исключение
Сообщить(ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
Возврат Истина;
КонецФункции
Функция ВыполненаКомандаПриложения(Спек, ИмяПроцедурыОбъекта, Аргументы)
Команда = Новый КомандаПриложения("test", "Тестовая команда", ЭтотОбъект);
ПараметрыВыполнения = Новый Массив;
ПараметрыВыполнения.Добавить(Команда);
ОписаниеКоманды = Делегаты.Создать(ЭтотОбъект, ИмяПроцедурыОбъекта);
ОписаниеКоманды.Исполнить(ПараметрыВыполнения);
Команда.Спек = Спек;
Команда.НачалоЗапуска();
Попытка
Команда.Запуск(Аргументы);
Исключение
Сообщить(ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
Возврат Истина;
КонецФункции
Функция ВыполнитьКомандаПриложения(Спек, ИмяПроцедурыОбъекта, Аргументы)
Команда = Новый КомандаПриложения("test", "Тестовая команда", ЭтотОбъект);
ПараметрыВыполнения = Новый Массив;
ПараметрыВыполнения.Добавить(Команда);
ОписаниеКоманды = Делегаты.Создать(ЭтотОбъект, ИмяПроцедурыОбъекта);
ОписаниеКоманды.Исполнить(ПараметрыВыполнения);
Команда.Спек = Спек;
Команда.НачалоЗапуска();
Попытка
Команда.Запуск(Аргументы);
Исключение
Сообщить(ОписаниеОшибки());
Возврат Команда;
КонецПопытки;
Возврат Команда;
КонецФункции
Процедура КомандаСкоростьРаботуКомандыПриложения(Знач ВыполняемаяКоманда) Экспорт
login = ВыполняемаяКоманда.Опция("login", "", "Login for credential, e.g. username or email.").ТСтрока();
realm = ВыполняемаяКоманда.Опция("realm", "", "Realm for credential, e.g. website or WiFi AP name.").ТСтрока();
note = ВыполняемаяКоманда.Опция("note", "", "Note for credential.").ТСтрока();
noCopy = ВыполняемаяКоманда.Опция("no-copy", false, "Do not copy generated password to the clipboard.").Флаг();
gen = ВыполняемаяКоманда.Опция("gen", false, "Generate a password.").Флаг();
length = ВыполняемаяКоманда.Опция("length", 0, "Password length.").Тчисло();
minLength = ВыполняемаяКоманда.Опция("min-length", 30, "Minimum length password.").Тчисло();
maxL = ВыполняемаяКоманда.Опция("max-length", 40, "Maximum length password.").Тчисло();
noUpper = ВыполняемаяКоманда.Опция("no-upper", false, "Exclude uppercase characters in password.").Флаг();
noLow = ВыполняемаяКоманда.Опция("no-lower", false, "Exclude lowercase characters in password.").Флаг();
noDigit = ВыполняемаяКоманда.Опция("no-digit", false, "Exclude digit characters in password.").Флаг();
noSymbol = ВыполняемаяКоманда.Опция("no-symbol", false, "Exclude symbol characters in password.").Флаг();
noSimilar = ВыполняемаяКоманда.Опция("no-similar", false, "Exclude similar characters in password.").Флаг();
minUpper = ВыполняемаяКоманда.Опция("min-upper", 0, "Minimum number of uppercase characters in password.").Тчисло();
maxUpper = ВыполняемаяКоманда.Опция("max-upper", -1, "Maximum number of uppercase characters in password.").Тчисло();
minLow = ВыполняемаяКоманда.Опция("min-lower", 0, "Minimum number of lowercase characters in password.").Тчисло();
maxLow = ВыполняемаяКоманда.Опция("max-lower", -1, "Maximum number of lowercase characters in password.").Тчисло();
minDigit = ВыполняемаяКоманда.Опция("min-digit", 0, "Minimum number of digit characters in password.").Тчисло();
maxDigit = ВыполняемаяКоманда.Опция("max-digit", -1, "Maximum number of digit characters in password.").Тчисло();
minSym = ВыполняемаяКоманда.Опция("min-symbol", 0, "Minimum number of symbol characters in password.").Тчисло();
maxSym = ВыполняемаяКоманда.Опция("max-symbol", -1, "Maximum number of symbol characters in password.").Тчисло();
ex = ВыполняемаяКоманда.Опция("exclude", "", "Exclude specific characters from password.").ТСтрока();
КонецПроцедуры
Процедура КомандаПростыеОпции(Знач ВыполняемаяКоманда) Экспорт
ВыполняемаяКоманда.Опция("bool", Ложь, "Login for credential, e.g. username or email.");
ВыполняемаяКоманда.Опция("string", "", "Realm for credential, e.g. website or WiFi AP name.");
ВыполняемаяКоманда.Опция("int", 0, "Note for credential.");
КонецПроцедуры
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_command");
//Лог.УстановитьУровень(УровниЛога.Отладка);

View File

@@ -0,0 +1,120 @@
#использовать "../src/core"
#Использовать asserts
Перем V, B, S, ARG, SRC;
Перем юТест;
Функция ПолучитьСписокТестов(Знач Тестирование) Экспорт
юТест = Тестирование;
ИменаТестов = Новый Массив;
ИменаТестов.Добавить("ТестДолжен_ТолькоАргументы");
//ИменаТестов.Добавить("ТестДолжен_ТолькоОпции");
//ИменаТестов.Добавить("ТестДолжен_ПроверитьПриложения");
ИменаТестов.Добавить("ТестДолжен_ПараметрыПеречисленияОпции");
ИменаТестов.Добавить("ТестДолжен_ПараметрыПеречисленияОпцииВыводHelp");
ИменаТестов.Добавить("ТестДолжен_ПроверитьВыводВерсииПриложения");
Возврат ИменаТестов;
КонецФункции
Процедура ТестДолжен_ТолькоАргументы() Экспорт
Приложение = Новый КонсольноеПриложение("cp", "");
DST = Приложение.Аргумент("DST", "", "Тест");
SRC = Приложение.Аргумент("SRC", "", "Тест").ТМассивСтрок();;
Приложение.УстановитьСпек("SRC... DST");
Приложение.УстановитьОсновноеДействие(ЭтотОбъект);
МассивSRC = Новый Массив;
МассивSRC.Добавить("src1");
МассивSRC.Добавить("src2");
ВходящиеАргументы = Новый Массив;
ВходящиеАргументы.Добавить("src1");
ВходящиеАргументы.Добавить("src2");
ВходящиеАргументы.Добавить("dst");
Приложение.Запустить(ВходящиеАргументы);
Утверждения.ПроверитьРавенство(DST.Значение, "dst", "Аргумент DST не равен ожидаемому");
Утверждения.ПроверитьРавенство(SRC.Значение.Количество(), МассивSRC.Количество(), "Аргумент SRC не равен ожидаемому");
КонецПроцедуры
Процедура ТестДолжен_ПроверитьВыводВерсииПриложения() Экспорт
Приложение = Новый КонсольноеПриложение("cp", "");
Приложение.Версия("v version", "1.0");
ВходящиеАргументы = Новый Массив;
ВходящиеАргументы.Добавить("-v");
// TODO: При выполнении этого теста происходить завершение тестирования
// Переписать после написания нормального флоу
//Приложение.Запустить(ВходящиеАргументы);
КонецПроцедуры
Процедура ТестДолжен_ПараметрыПеречисленияОпции() Экспорт
Приложение = Новый КонсольноеПриложение("cp", "");
enum = Приложение.Опция("enum e", "yellow", "Опция перечисление").ТПеречисление()
.Перечисление("yellow", "yellow", "Это желтый цвет")
.Перечисление("red", "red" , "Это красный цвет")
.Перечисление("blue", "blue", "Это синий цвет")
;
Приложение.УстановитьОсновноеДействие(ЭтотОбъект);
ВходящиеАргументы = Новый Массив;
ВходящиеАргументы.Добавить("-e");
ВходящиеАргументы.Добавить("yellow");
Приложение.Запустить(ВходящиеАргументы);
Утверждения.ПроверитьРавенство(enum.Значение, "yellow", "Аргумент enum не равен ожидаемому");
КонецПроцедуры
Процедура ТестДолжен_ПараметрыПеречисленияОпцииВыводHelp() Экспорт
Приложение = Новый КонсольноеПриложение("cp", "");
enum = Приложение.Опция("enum e", "yellow", "Опция перечисление").ТПеречисление()
.Перечисление("yellow", "yellow", "Это желтый цвет")
.Перечисление("red", "rediiii" , "Это красный цвет")
.Перечисление("blue", "blue", "Это синий цвет")
;
Приложение.УстановитьОсновноеДействие(ЭтотОбъект);
ВходящиеАргументы = Новый Массив;
// ВходящиеАргументы.Добавить("--help");
ВходящиеАргументы.Добавить("--enum");
ВходящиеАргументы.Добавить("red");
Приложение.Запустить(ВходящиеАргументы);
Утверждения.ПроверитьРавенство(enum.Значение, "rediiii", "Аргумент enum не равен ожидаемому");
КонецПроцедуры
Процедура ВыполнитьКоманду(Знач Команда) Экспорт
КонецПроцедуры
Функция ИмяФункции()
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_command");
//Лог.УстановитьУровень(УровниЛога.Отладка);

View File

@@ -0,0 +1,283 @@
#использовать "../src/core"
#Использовать asserts
#Использовать logos
Перем юТест;
Перем Лог;
Функция ПолучитьСписокТестов(Знач Тестирование) Экспорт
юТест = Тестирование;
ИменаТестов = Новый Массив;
ИменаТестов.Добавить("ТестДолжен_ПроверитьЛексерНаРазборТокенов");
Возврат ИменаТестов;
КонецФункции
Процедура ТестДолжен_ПроверитьЛексерНаРазборТокенов() Экспорт
ПроверочныеДанные = ТестовыеСлучаи();
Для каждого КлючЗначение Из ПроверочныеДанные Цикл
Лог.Отладка("Проверяю spec: %1", КлючЗначение.Ключ);
Лексер = Новый Лексер(КлючЗначение.Ключ).Прочитать();
Утверждения.ПроверитьЛожь(Лексер.ЕстьОшибка(), СтрШаблон("Лексер должен отработать успешно. Спек: %1 -- Ошибка: %2", КлючЗначение.Ключ, Лексер.ПолучитьИнформациюОбОшибке()));
СпекМассив = Лексер.ПолучитьТокены();
Утверждения.ПроверитьРавенство(СпекМассив.Количество(), КлючЗначение.Значение.Количество(), "Набор токенов должен быть одинаковым: "+ КлючЗначение.Ключ);
Утверждения.ПроверитьИстину(СверитьМассивыТокенов(СпекМассив, КлючЗначение.Значение),"Токены не равны " + КлючЗначение.Ключ);
КонецЦикла;
КонецПроцедуры
Функция СверитьТокены(ПроверяемыйТокен, ИдеальныйТокен)
Для каждого КлючЗначение Из ИдеальныйТокен Цикл
Если Не КлючЗначение.Значение = ПроверяемыйТокен[КлючЗначение.Ключ] Тогда
Лог.Отладка("Не равны ключи %1 = %2", КлючЗначение.Значение, ПроверяемыйТокен[КлючЗначение.Ключ]);
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Функция СверитьМассивыТокенов(ПроверяемыйМассив, ИдеальныйМассив)
Для ИндексТокена = 0 По ИдеальныйМассив.ВГраница() Цикл
ИдеальныйТокен = ИдеальныйМассив[ИндексТокена];
ПроверяемыйТокен = ПроверяемыйМассив[ИндексТокена];
ТокеныРавны = СверитьТокены(ПроверяемыйТокен, ИдеальныйТокен);
Если НЕ ТокеныРавны Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Функция ПравильныйОтвет(Ответ1, Ответ2 = Неопределено, Ответ3 = Неопределено, Ответ4 = Неопределено, Ответ5 = Неопределено, Ответ6 = Неопределено, Ответ7 = Неопределено)
Массив = Новый Массив;
Массив.Добавить(Ответ1);
Если ЗначениеЗаполнено(Ответ2) Тогда
Массив.Добавить(Ответ2);
КонецЕсли;
Если ЗначениеЗаполнено(Ответ3) Тогда
Массив.Добавить(Ответ3);
КонецЕсли;
Если ЗначениеЗаполнено(Ответ4) Тогда
Массив.Добавить(Ответ4);
КонецЕсли;
Если ЗначениеЗаполнено(Ответ5) Тогда
Массив.Добавить(Ответ5);
КонецЕсли;
Если ЗначениеЗаполнено(Ответ6) Тогда
Массив.Добавить(Ответ6);
КонецЕсли;
Если ЗначениеЗаполнено(Ответ7) Тогда
Массив.Добавить(Ответ7);
КонецЕсли;
Возврат Массив;
КонецФункции
Функция ТестовыеСлучаи()
ПроверочныеДанные = Новый Соответствие;
ПроверочныеДанные.Вставить("XOPTIONS", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "XOPTIONS", 0)));
ПроверочныеДанные.Вставить("OPTIONSX", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "OPTIONSX", 0)));
ПроверочныеДанные.Вставить("ARG_EXTRA", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG_EXTRA", 0)));
ПроверочныеДанные.Вставить("OPTIONS", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTOptions, "OPTIONS", 0)));
ПроверочныеДанные.Вставить("ОПЦИИ", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTOptions, "ОПЦИИ", 0)));
ПроверочныеДанные.Вставить("[OPTIONS] ", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOpenSq, "[", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTOptions, "OPTIONS", 1),
Токены.НовыйТокен(Токены.ТипыТокенов().TTCloseSq, "]", 8)
));
ПроверочныеДанные.Вставить("ARG1 ARG2", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG1", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG2", 5)));
ПроверочныеДанные.Вставить("ARG1 ARG2", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG1", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG2", 6)));
ПроверочныеДанные.Вставить("(", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTOpenPar, "(", 0)));
ПроверочныеДанные.Вставить(")", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTClosePar, ")", 0)));
ПроверочныеДанные.Вставить("...", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTRep, "...", 0)));
ПроверочныеДанные.Вставить("ARG...", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTRep, "...", 3)));
ПроверочныеДанные.Вставить("-a...", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTShortOpt, "-a", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTRep, "...", 2)));
ПроверочныеДанные.Вставить("[-a...]", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOpenSq, "[", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTShortOpt, "-a", 1),
Токены.НовыйТокен(Токены.ТипыТокенов().TTRep, "...", 3),
Токены.НовыйТокен(Токены.ТипыТокенов().TTCloseSq, "]", 6)
)
);
ПроверочныеДанные.Вставить("|", ПравильныйОтвет(Токены.НовыйТокен(Токены.ТипыТокенов().TTChoice, "|", 0)));
ПроверочныеДанные.Вставить("ARG1 |ARG2", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG1", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTChoice, "|", 5),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG2", 6)
)
);
ПроверочныеДанные.Вставить("ARG1| ARG2", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG1", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTChoice, "|", 4),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG2", 6)
)
);
ПроверочныеДанные.Вставить("ARG1|ARG2", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG1", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTChoice, "|", 4),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG2", 5)
)
);
ПроверочныеДанные.Вставить("(ARG)", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOpenPar, "(", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG", 1),
Токены.НовыйТокен(Токены.ТипыТокенов().TTClosePar, ")", 4)
)
);
ПроверочныеДанные.Вставить("(-v|-s -b)", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOpenPar, "(", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTShortOpt, "-v", 1),
Токены.НовыйТокен(Токены.ТипыТокенов().TTChoice, "|", 3),
Токены.НовыйТокен(Токены.ТипыТокенов().TTShortOpt, "-s", 4),
Токены.НовыйТокен(Токены.ТипыТокенов().TTShortOpt, "-b", 7),
Токены.НовыйТокен(Токены.ТипыТокенов().TTClosePar, ")", 9)
)
);
ПроверочныеДанные.Вставить("( ARG )", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOpenPar, "(", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG", 2),
Токены.НовыйТокен(Токены.ТипыТокенов().TTClosePar, ")", 6)
)
);
ПроверочныеДанные.Вставить("[ARG]", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOpenSq, "[", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG", 1),
Токены.НовыйТокен(Токены.ТипыТокенов().TTCloseSq, "]", 4)
)
);
ПроверочныеДанные.Вставить("[ ARG ]", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOpenSq, "[", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG", 2),
Токены.НовыйТокен(Токены.ТипыТокенов().TTCloseSq, "]", 6)
)
);
ПроверочныеДанные.Вставить("ARG [ARG2 ]", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTOpenSq, "[", 4),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG2", 5),
Токены.НовыйТокен(Токены.ТипыТокенов().TTCloseSq, "]", 10)
)
);
ПроверочныеДанные.Вставить("ARG [ ARG2]", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTOpenSq, "[", 4),
Токены.НовыйТокен(Токены.ТипыТокенов().TTArg, "ARG2", 6),
Токены.НовыйТокен(Токены.ТипыТокенов().TTCloseSq, "]", 10)
)
);
ПроверочныеДанные.Вставить("-p", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTShortOpt, "-p", 0),
)
);
ПроверочныеДанные.Вставить(" -x", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTShortOpt, "-x", 1),
)
);
ПроверочныеДанные.Вставить("--force", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTLongOpt, "--force", 0),
)
);
ПроверочныеДанные.Вставить("--sig-proxy", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTLongOpt, "--sig-proxy", 0),
)
);
ПроверочныеДанные.Вставить("-aBc", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOptSeq, "-aBc", 0),
)
);
ПроверочныеДанные.Вставить("--", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTDoubleDash, "--", 0),
)
);
ПроверочныеДанные.Вставить("=<bla>", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=<bla>", 0),
)
);
ПроверочныеДанные.Вставить("=<bla>", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=<bla>", 0),
)
);
ПроверочныеДанные.Вставить("=<bla-bla>", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=<bla-bla>", 0),
)
);
ПроверочныеДанные.Вставить("=<bla--bla>", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=<bla--bla>", 0),
)
);
ПроверочныеДанные.Вставить("-p=<file-path>", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTShortOpt, "-p", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=<file-path>", 2),
)
);
ПроверочныеДанные.Вставить("--path=<file- path>", ПравильныйОтвет(
Токены.НовыйТокен(Токены.ТипыТокенов().TTLongOpt, "--path", 0),
Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=<file- path>", 6),
)
);
Возврат ПроверочныеДанные
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_lexer");
//Лог.УстановитьУровень(УровниЛога.Отладка);

View File

@@ -0,0 +1,28 @@
#использовать "../src/core"
#Использовать asserts
&Тест
Процедура ПроверитьТМассивДат() Экспорт
// Дано
Команда = ЗагрузитьСценарий("tests/fixtures/КомандаСМассивами.os");
Приложение = Новый КонсольноеПриложение("cp", "");
Приложение.Версия("v version", "1.0");
ПараметрыКоманды = Новый Массив();
ПараметрыКоманды.Добавить("testingarray");
ПараметрыКоманды.Добавить("-a");
ПараметрыКоманды.Добавить("2023-04-13;2023-04-14");
Приложение.ДобавитьКоманду("testingarray", "Тестируем массив", Команда);
// Когда
Приложение.Запустить(ПараметрыКоманды);
// Тогда
Ожидаем.Что(Команда.МассивДат[0], "дата1").Равно(Дата("20230413000000"));
Ожидаем.Что(Команда.МассивДат[1], "дата2").Равно(Дата("20230414000000"));
КонецПроцедуры

View File

@@ -0,0 +1,289 @@
#использовать "../src/core"
#Использовать asserts
#Использовать logos
Перем юТест;
Перем Лог;
Функция ПолучитьСписокТестов(Знач Тестирование) Экспорт
юТест = Тестирование;
ИменаТестов = Новый Массив;
ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсингБулевоОпций");
ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсингМассивовБулевоОпций");
ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсингОпций");
ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсингМассивовОпций");
Возврат ИменаТестов;
КонецФункции
Процедура ТестДолжен_ПроверитьПарсингБулевоОпций() Экспорт
force = Опция("f force", Ложь).Флаг();
g = Опция("g", Ложь).Флаг();
x = Опция("x", Ложь).Флаг();
y = Опция("y", Ложь).Флаг();
ИндексОпций = Новый Соответствие;
ИндексОпций.Вставить("-f", force);
ИндексОпций.Вставить("--force", force);
ИндексОпций.Вставить("-g", g);
ИндексОпций.Вставить("-x", x);
ИндексОпций.Вставить("-y", y);
О_Парсера = Новый ОпцияПарсера(force, ИндексОпций);
Утверждения.ПроверитьРавенство("-f", О_Парсера.ВСтроку(), "Парсер опции должен быть равен -f");
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f x", "x", "Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f=true x", "x", "Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f=false x", "x", "Ложь"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force x", "x", "Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force=true x", "x", "Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force=false x", "x", "Ложь"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-fgxy x", "-gxy x", "Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-gfxy x", "-gxy x", "Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-gxfy x", "-gxy x", "Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-gxyf x", "-gxy x", "Истина"));
Для каждого Тест Из ТестовыеСлучаи Цикл
НачальноеКоличество = Тест.Аргументы.Количество();
Лог.Отладка("Проверяю тестовый случай: %1", СтрСоединить(Тест.Аргументы, " "));
Контекст = Новый КонтекстПарсеров();
Результат = О_Парсера.Поиск(Тест.Аргументы, Контекст);
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Опция (-f) должен быть найдена");
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
Утверждения.ПроверитьРавенство(СтрСоединить(Результат.Аргументы, " "), СтрСоединить(Тест.АргументыВыхода, " "), "Аргументы выходные должны быть равны");
Утверждения.ПроверитьРавенство(1, Контекст.Опции[О_Парсера.Опция].Количество(), "Количество результатов должно быть 1");
Утверждения.ПроверитьРавенство(Булево(Контекст.Опции[О_Парсера.Опция][0]), Булево(Тест.ЗначениеОпции[0]), "Ожидаемые результаты должны быть равны");
КонтекстСброса = Новый КонтекстПарсеров();
КонтекстСброса.СбросОпций = Истина;
Результат = О_Парсера.Поиск(Тест.Аргументы, КонтекстСброса);
Утверждения.ПроверитьЛожь(Результат.РезультатПоиска, "Опция (-f) не должена быть найдена");
КонецЦикла;
КонецПроцедуры
Процедура ТестДолжен_ПроверитьПарсингМассивовБулевоОпций() Экспорт
force = Опция("f force", Ложь).ТМассивБулево();
g = Опция("g", Ложь).Флаг();
x = Опция("x", Ложь).Флаг();
y = Опция("y", Ложь).Флаг();
ИндексОпций = Новый Соответствие;
ИндексОпций.Вставить("-f", force);
ИндексОпций.Вставить("--force", force);
ИндексОпций.Вставить("-g", g);
ИндексОпций.Вставить("-x", x);
ИндексОпций.Вставить("-y", y);
О_Парсера = Новый ОпцияПарсера(force, ИндексОпций);
Утверждения.ПроверитьРавенство("-f", О_Парсера.ВСтроку(), "Парсер опции должен быть равен -f");
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f -f x", "x", "Истина Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f=true -f=true x", "x", "Истина Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f=false -f=false x", "x", "Ложь Ложь"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f=true -f=false x", "x", "Истина Ложь"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force --force x", "x", "Истина Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force=true --force=true x", "x", "Истина Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force=false --force=false x", "x", "Ложь Ложь"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force=true --force=false x", "x", "Истина Ложь"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f -fgxy x", "-gxy x", "Истина Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f -gfxy x", "-gxy x", "Истина Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f -gxfy x", "-gxy x", "Истина Истина"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f -gxyf x", "-gxy x", "Истина Истина"));
ТипМассивБулево = Новый ТипМассивБулево();
Для каждого Тест Из ТестовыеСлучаи Цикл
НачальноеКоличество = Тест.Аргументы.Количество();
Лог.Отладка("Проверяю тестовый случай: %1", СтрСоединить(Тест.Аргументы, " "));
Контекст = Новый КонтекстПарсеров();
Результат = О_Парсера.Поиск(Тест.Аргументы, Контекст);
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Опция (-f) должен быть найдена");
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
Результат = О_Парсера.Поиск(Результат.Аргументы, Контекст);
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Опция (-f) должен быть найдена");
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
МассивЗначений = Новый Массив;
Для Каждого Значение Из Контекст.Опции[О_Парсера.Опция] Цикл
ТипМассивБулево.УстановитьЗначение(Значение, МассивЗначений);
КонецЦикла;
Утверждения.ПроверитьРавенство(СтрСоединить(Результат.Аргументы, " "), СтрСоединить(Тест.АргументыВыхода, " "), "Аргументы выходные должны быть равны");
Утверждения.ПроверитьРавенство(ТипМассивБулево.ВСтроку(МассивЗначений), СтрСоединить(Тест.ЗначениеОпции, ", "), "Ожидаемые результаты должны быть равны");
КонтекстСброса = Новый КонтекстПарсеров();
КонтекстСброса.СбросОпций = Истина;
Результат = О_Парсера.Поиск(Тест.Аргументы, КонтекстСброса);
Утверждения.ПроверитьЛожь(Результат.РезультатПоиска, "Опция (-f) не должена быть найдена");
КонецЦикла;
КонецПроцедуры
Функция ТестовыйСлучай(Знач Аргументы, Знач АргументыВыхода, Знач ЗначениеОпции)
Тест = Новый Структура;
Тест.Вставить("Аргументы", СтрРазделить(Аргументы," "));
Тест.Вставить("АргументыВыхода", СтрРазделить(АргументыВыхода," "));
Тест.Вставить("ЗначениеОпции", СтрРазделить(ЗначениеОпции," "));
Возврат Тест;
КонецФункции
Процедура ТестДолжен_ПроверитьПарсингОпций() Экспорт
НаименованияОпции = Новый Массив;
НаименованияОпции.Добавить("-f");
НаименованияОпции.Добавить("--force");
МассивОпций = Новый Массив;
МассивОпций.Добавить(Опция("f force", "").ТСтрока());
МассивОпций.Добавить(Опция("f force", "").ТЧисло());
// TODO Написать отдельную проверку для дат
МассивОпций.Добавить(Опция("f force", "").ТДата());
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f x", "", "x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f=x y", "y", "x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-fx y", "y", "x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-afx y", "-a y", "x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-af x y", "-a y", "x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force x", "", "x"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force=x y", "y", "x"));
a = Новый ПараметрКоманды("опция", "a", Ложь, "Тестовый параметр a");
Для каждого Тест Из ТестовыеСлучаи Цикл
Для каждого ОпцияForce Из МассивОпций Цикл
НачальноеКоличество = Тест.Аргументы.Количество();
Лог.Отладка("Проверяю тестовый случай: %1", СтрСоединить(Тест.Аргументы, " "));
Лог.Отладка("-> тип опции: %1", ОпцияForce.ТипОпции);
ИндексОпций = Новый Соответствие;
ИндексОпций.Вставить("-f", ОпцияForce);
ИндексОпций.Вставить("--force", ОпцияForce);
ИндексОпций.Вставить("-a", a);
АргументыТеста = Тест.Аргументы;
О_Парсера = Новый ОпцияПарсера(ОпцияForce, ИндексОпций);
Утверждения.ПроверитьРавенство("-f", О_Парсера.ВСтроку(), "Парсер опции должен быть равен -f");
Контекст = Новый КонтекстПарсеров();
Результат = О_Парсера.Поиск(АргументыТеста, Контекст);
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Опция (-f) должна быть найдена");
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
Утверждения.ПроверитьРавенство(СтрСоединить(Результат.Аргументы, " "), СтрСоединить(Тест.АргументыВыхода, " "), "Аргументы выходные должны быть равны");
Утверждения.ПроверитьРавенство(1, Контекст.Опции[О_Парсера.Опция].Количество(), "Количество результатов должно быть 1");
Утверждения.ПроверитьРавенство(Контекст.Опции[О_Парсера.Опция][0], Тест.ЗначениеОпции[0], "Ожидаемые результаты должны быть равны");
КонтекстСброса = Новый КонтекстПарсеров();
КонтекстСброса.СбросОпций = Истина;
Результат = О_Парсера.Поиск(АргументыТеста, КонтекстСброса);
Утверждения.ПроверитьЛожь(Результат.РезультатПоиска, "Опция (-f) не должна быть найдена");
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура ТестДолжен_ПроверитьПарсингМассивовОпций() Экспорт
НаименованияОпции = Новый Массив;
НаименованияОпции.Добавить("-f");
НаименованияОпции.Добавить("--force");
МассивОпций = Новый Массив;
МассивОпций.Добавить(Опция("f force", Новый Массив).ТМассивСтрок());
МассивОпций.Добавить(Опция("f force", Новый Массив).ТМассивЧисел());
// TODO Написать отдельную проверку для дат
МассивОпций.Добавить(Опция("f force", Новый Массив).ТМассивДат());
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f x -f z", "", "x z"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-f=x -f=z y", "y", "x z"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-fx -fz y", "y", "x z"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-afx -yfz", "-a -y", "x z"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-af x -yf z", "-a -y", "x z"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force x --force z", "", "x z"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--force=x --force=z y", "y", "x z"));
a = Новый ПараметрКоманды("опция", "a", Ложь, "Тестовый параметр a");
y = Новый ПараметрКоманды("опция", "y", Ложь, "Тестовый параметр a");
Для каждого Тест Из ТестовыеСлучаи Цикл
Для каждого ОпцияForce Из МассивОпций Цикл
НачальноеКоличество = Тест.Аргументы.Количество();
Лог.Отладка("Проверяю тестовый случай: %1", СтрСоединить(Тест.Аргументы, " "));
Лог.Отладка("-> тип опции: %1", ОпцияForce.ТипОпции);
ИндексОпций = Новый Соответствие;
ИндексОпций.Вставить("-f", ОпцияForce);
ИндексОпций.Вставить("--force", ОпцияForce);
ИндексОпций.Вставить("-a", a);
ИндексОпций.Вставить("-y", y);
АргументыТеста = Тест.Аргументы;
О_Парсера = Новый ОпцияПарсера(ОпцияForce, ИндексОпций);
Утверждения.ПроверитьРавенство("-f", О_Парсера.ВСтроку(), "Парсер опции должен быть равен -f");
Контекст = Новый КонтекстПарсеров();
Результат = О_Парсера.Поиск(АргументыТеста, Контекст);
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Опция (-f) должна быть найдена");
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
Результат = О_Парсера.Поиск(Результат.Аргументы, Контекст);
Утверждения.ПроверитьИстину(Результат.РезультатПоиска, "Опция (-f) должна быть найдена");
Утверждения.ПроверитьРавенство(НачальноеКоличество, Тест.Аргументы.Количество(), "Количество аргументов не должно измениться");
Утверждения.ПроверитьРавенство(СтрСоединить(Результат.Аргументы, " "), СтрСоединить(Тест.АргументыВыхода, " "), "Аргументы выходные должны быть равны");
Утверждения.ПроверитьРавенство(СтрСоединить(Контекст.Опции[О_Парсера.Опция], " "), СтрСоединить(Тест.ЗначениеОпции, " "), "Ожидаемые результаты должны быть равны");
КонтекстСброса = Новый КонтекстПарсеров();
КонтекстСброса.СбросОпций = Истина;
Результат = О_Парсера.Поиск(АргументыТеста, КонтекстСброса);
Утверждения.ПроверитьЛожь(Результат.РезультатПоиска, "Опция (-f) не должна быть найдена");
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функция Опция(Наименование, ЗначениеПоУмолчанию)
Возврат Новый ПараметрКоманды("опция", Наименование, ЗначениеПоУмолчанию, "Тестовый параметр f");
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.cli_class_opt");
//Лог.УстановитьУровень(УровниЛога.Отладка);

View File

@@ -0,0 +1,132 @@
#использовать "../src/core"
#Использовать asserts
#Использовать logos
Перем юТест;
Перем Лог;
Функция ПолучитьСписокТестов(Знач Тестирование) Экспорт
юТест = Тестирование;
ИменаТестов = Новый Массив;
ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсинг");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсингОпций");
// ИменаТестов.Добавить("ТестДолжен_ПроверитьПарсингМассивовОпций");
Возврат ИменаТестов;
КонецФункции
Процедура ТестДолжен_ПроверитьПарсинг() Экспорт
опция_a = Опция("a all", "");
опция_b = Опция("b ball", "");
ИндексОпций = Новый Соответствие;
ИндексОпций.Вставить("-a", опция_a);
ИндексОпций.Вставить("--all", опция_a);
ИндексОпций.Вставить("-b", опция_b);
ИндексОпций.Вставить("--ball", опция_b);
Опции = Новый Соответствие;
Опции.Вставить(опция_a, опция_a);
Опции.Вставить(опция_b, опция_b);
аргумент_ARG = Аргумент("ARG", "");
Аргументы = Новый Соответствие;
Аргументы.Вставить(аргумент_ARG, аргумент_ARG);
ИндексАргументов = Новый Соответствие;
ИндексАргументов.Вставить("ARG", аргумент_ARG);
ТестовыеСлучаи = Новый Массив;
ТестовыеСлучаи.Добавить(ТестовыйСлучай("", ""));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-a", "S1 -a (S2)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("--all", "S1 -a (S2)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-a -b", "S1 -a S2
|S2 -b (S3)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-a -b", "S1 -a S2
|S2 -b (S3)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-a | -b", "S1 -a (S2)
|S1 -b (S3)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-a...", "S1 -a (S2)
|(S2) -a (S2)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("[-a...]", "(S1) -a (S2)
|(S2) -a (S2)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("[-a]...", "(S1) -a (S2)
|(S2) -a (S2)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-a -b | ARG", "S1 -a S2
|S2 -b (S3)
|S2 ARG (S4)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-a (-b | ARG)", "S1 -a S2
|S2 -b (S3)
|S2 ARG (S4)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("(-a -b) | ARG...", "S1 -a S2
|S1 ARG (S4)
|S2 -b (S3)
|(S4) ARG (S4)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-ab", "S1 -ab (S2)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("-a -- ARG", "S1 -a S2
|S2 -- S3
|S3 ARG (S4)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("[OPTIONS]", "(S1) -ab (S2)"));
ТестовыеСлучаи.Добавить(ТестовыйСлучай("[ОПЦИИ]", "(S1) -ab (S2)"));
Для каждого Тест Из ТестовыеСлучаи Цикл
fsm = Новый ВыборСовпадений();
Лог.Отладка("Проверяю тестовый случай: %1", Тест.Спек);
Лог.Отладка("Строка состояния: %1", Тест.Соединения);
Лексер = Новый Лексер(Тест.Спек).Прочитать();
Утверждения.ПроверитьЛожь(Лексер.ЕстьОшибка(), "Лексер должен отработать успешно. Ошибка: " + Лексер.ПолучитьИнформациюОбОшибке());
ТокеныПарсера = Лексер.ПолучитьТокены();
ПараметрыПарсера = Новый Структура;
ПараметрыПарсера.Вставить("Спек", Тест.Спек);
ПараметрыПарсера.Вставить("Опции", Опции);
ПараметрыПарсера.Вставить("Аргументы", Аргументы);
ПараметрыПарсера.Вставить("ОпцииИндекс", ИндексОпций);
ПараметрыПарсера.Вставить("АргументыИндекс", ИндексАргументов);
парсер = Новый Парсер(ТокеныПарсера, ПараметрыПарсера);
НачальноеСостояние = парсер.Прочитать();
СтрокаПути = fsm.СгенеритьСтрокуПути(НачальноеСостояние);
МассивОжиданийСтрок = СтрРазделить(Тест.Соединения, Символы.ПС);
Для каждого ОжидаемаяСтрока Из МассивОжиданийСтрок Цикл
Утверждения.ПроверитьВхождение(СтрокаПути, ОжидаемаяСтрока, "Ожидали, что все строки будут найдены. Тестовый спек: " + Тест.Спек);
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функция Опция(Наименование, ЗначениеПоУмолчанию)
Возврат Новый ПараметрКоманды("опция", Наименование, ЗначениеПоУмолчанию, "Тестовый параметр f");
КонецФункции
Функция Аргумент(Наименование, ЗначениеПоУмолчанию)
Возврат Новый ПараметрКоманды("Аргумент", Наименование, ЗначениеПоУмолчанию, "Тестовый параметр f");
КонецФункции
Функция ТестовыйСлучай(Знач Спек, Знач Соединения)
Тест = Новый Структура;
Тест.Вставить("Спек",Спек);
Тест.Вставить("Соединения",Соединения);
Возврат Тест;
КонецФункции
Лог = Логирование.ПолучитьЛог("oscript.lib.spec_parse");
//Лог.УстановитьУровень(УровниЛога.Отладка);

16
lib/cli/travis-ci.sh Normal file
View File

@@ -0,0 +1,16 @@
set -e
echo "Устанавливаю версию OScript <$OSCRIPT_VERSION>"
curl http://oscript.io/downloads/$OSCRIPT_VERSION/deb > oscript.deb
dpkg -i oscript.deb
rm -f oscript.deb
opm install 1testrunner;
opm install 1bdd;
opm install coverage;
opm install;
opm run coverage;
# oscript ./tasks/coverage.os

View File

@@ -10,7 +10,6 @@
.ВключитьФайл("lib.config")
.ВключитьФайл("README.md")
.ЗависитОт("tokenizer")
.ЗависитОт("cli")
.ЗависитОт("logos")
.ЗависитОт("winow", "0.8.3")
.РазработкаЗависитОт("1testrunner")

View File

@@ -1,5 +1,5 @@
#Использовать cli
#Использовать "../internal"
#Использовать "../internal"
#Использовать "../../lib/cli/src/core"
Перем ОписаниеЗапроса;
Перем КаталогСохраненияФайлов;