From 996722c4334c24e11b3914d7d34b738d5f09e4a7 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanov Date: Mon, 23 Dec 2024 23:24:34 +0300 Subject: [PATCH] =?UTF-8?q?feat(cli):=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8=D1=81=D1=85=D0=BE=D0=B4?= =?UTF-8?q?=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8?= =?UTF-8?q?=D0=BE=D1=82=D0=B5=D0=BA=D0=B8=20cli?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/cli/.gitignore | 5 + lib/cli/.travis.yml | 77 + lib/cli/CODE_OF_CONDUCT.md | 46 + lib/cli/LICENSE | 201 +++ lib/cli/README.md | 602 ++++++++ lib/cli/appveyor.yml | 63 + lib/cli/docs/readme.md | 893 +++++++++++ lib/cli/features/.gitkeep | 0 .../features/Запуск без параметров.feature | 25 + lib/cli/packagedef | 28 + lib/cli/sonar-project.properties | 18 + lib/cli/sonar-qube.sh | 22 + .../Классы/internal/lexer/Классы/Лексер.os | 243 +++ .../Классы/internal/lexer/Модули/Токены.os | 60 + .../internal/parser/Классы/АргументыПарсера.os | 92 ++ .../internal/parser/Классы/ВсеОпцииПарсера.os | 139 ++ .../internal/parser/Классы/КонтекстПарсеров.os | 72 + .../internal/parser/Классы/ЛюбойСимвол.os | 36 + .../parser/Классы/ОпцииЗавершениеПарсера.os | 36 + .../internal/parser/Классы/ОпцияПарсера.os | 408 +++++ .../Классы/internal/parser/Классы/Парсер.os | 345 +++++ .../internal/path/Классы/ВыборСовпадений.os | 226 +++ .../Классы/internal/path/Классы/Совпадение.os | 265 ++++ .../internal/tools/Классы/ЧтениеСтроки.os | 570 +++++++ .../Классы/internal/types/Классы/ТипБулево.os | 60 + .../internal/types/Классы/ТипДатаВремя.os | 68 + .../internal/types/Классы/ТипМассивБулево.os | 76 + .../internal/types/Классы/ТипМассивДат.os | 85 ++ .../internal/types/Классы/ТипМассивСтрок.os | 67 + .../internal/types/Классы/ТипМассивЧисел.os | 68 + .../internal/types/Классы/ТипПеречисление.os | 123 ++ .../Классы/internal/types/Классы/ТипСтрока.os | 53 + .../Классы/internal/types/Классы/ТипЧисло.os | 57 + lib/cli/src/core/Классы/КомандаПриложения.os | 1317 +++++++++++++++++ .../src/core/Классы/КонсольноеПриложение.os | 211 +++ lib/cli/src/core/Классы/ПараметрКоманды.os | 643 ++++++++ lib/cli/tasks/coverage.os | 30 + lib/cli/tasks/test.os | 87 ++ lib/cli/tests/fixtures/КомандаСМассивами.os | 16 + lib/cli/tests/fixtures/ТестовоеПриложение.os | 32 + lib/cli/tests/АргументыПарсера_test.os | 133 ++ lib/cli/tests/ВсеОпцииПарсера_test.os | 212 +++ lib/cli/tests/КомандаПриложения_test.os | 559 +++++++ lib/cli/tests/КонсольноеПриложение_test.os | 120 ++ lib/cli/tests/Лексер_test.os | 283 ++++ lib/cli/tests/МассивыПараметров.os | 28 + lib/cli/tests/ОпцияПарсера_test.os | 289 ++++ lib/cli/tests/Парсер_test.os | 132 ++ lib/cli/travis-ci.sh | 16 + packagedef | 1 - src/Классы/КонвертерКомандыCURL.os | 4 +- 51 files changed, 9239 insertions(+), 3 deletions(-) create mode 100644 lib/cli/.gitignore create mode 100644 lib/cli/.travis.yml create mode 100644 lib/cli/CODE_OF_CONDUCT.md create mode 100644 lib/cli/LICENSE create mode 100644 lib/cli/README.md create mode 100644 lib/cli/appveyor.yml create mode 100644 lib/cli/docs/readme.md create mode 100644 lib/cli/features/.gitkeep create mode 100644 lib/cli/features/Запуск без параметров.feature create mode 100644 lib/cli/packagedef create mode 100644 lib/cli/sonar-project.properties create mode 100644 lib/cli/sonar-qube.sh create mode 100644 lib/cli/src/core/Классы/internal/lexer/Классы/Лексер.os create mode 100644 lib/cli/src/core/Классы/internal/lexer/Модули/Токены.os create mode 100644 lib/cli/src/core/Классы/internal/parser/Классы/АргументыПарсера.os create mode 100644 lib/cli/src/core/Классы/internal/parser/Классы/ВсеОпцииПарсера.os create mode 100644 lib/cli/src/core/Классы/internal/parser/Классы/КонтекстПарсеров.os create mode 100644 lib/cli/src/core/Классы/internal/parser/Классы/ЛюбойСимвол.os create mode 100644 lib/cli/src/core/Классы/internal/parser/Классы/ОпцииЗавершениеПарсера.os create mode 100644 lib/cli/src/core/Классы/internal/parser/Классы/ОпцияПарсера.os create mode 100644 lib/cli/src/core/Классы/internal/parser/Классы/Парсер.os create mode 100644 lib/cli/src/core/Классы/internal/path/Классы/ВыборСовпадений.os create mode 100644 lib/cli/src/core/Классы/internal/path/Классы/Совпадение.os create mode 100644 lib/cli/src/core/Классы/internal/tools/Классы/ЧтениеСтроки.os create mode 100644 lib/cli/src/core/Классы/internal/types/Классы/ТипБулево.os create mode 100644 lib/cli/src/core/Классы/internal/types/Классы/ТипДатаВремя.os create mode 100644 lib/cli/src/core/Классы/internal/types/Классы/ТипМассивБулево.os create mode 100644 lib/cli/src/core/Классы/internal/types/Классы/ТипМассивДат.os create mode 100644 lib/cli/src/core/Классы/internal/types/Классы/ТипМассивСтрок.os create mode 100644 lib/cli/src/core/Классы/internal/types/Классы/ТипМассивЧисел.os create mode 100644 lib/cli/src/core/Классы/internal/types/Классы/ТипПеречисление.os create mode 100644 lib/cli/src/core/Классы/internal/types/Классы/ТипСтрока.os create mode 100644 lib/cli/src/core/Классы/internal/types/Классы/ТипЧисло.os create mode 100644 lib/cli/src/core/Классы/КомандаПриложения.os create mode 100644 lib/cli/src/core/Классы/КонсольноеПриложение.os create mode 100644 lib/cli/src/core/Классы/ПараметрКоманды.os create mode 100644 lib/cli/tasks/coverage.os create mode 100644 lib/cli/tasks/test.os create mode 100644 lib/cli/tests/fixtures/КомандаСМассивами.os create mode 100644 lib/cli/tests/fixtures/ТестовоеПриложение.os create mode 100644 lib/cli/tests/АргументыПарсера_test.os create mode 100644 lib/cli/tests/ВсеОпцииПарсера_test.os create mode 100644 lib/cli/tests/КомандаПриложения_test.os create mode 100644 lib/cli/tests/КонсольноеПриложение_test.os create mode 100644 lib/cli/tests/Лексер_test.os create mode 100644 lib/cli/tests/МассивыПараметров.os create mode 100644 lib/cli/tests/ОпцияПарсера_test.os create mode 100644 lib/cli/tests/Парсер_test.os create mode 100644 lib/cli/travis-ci.sh diff --git a/lib/cli/.gitignore b/lib/cli/.gitignore new file mode 100644 index 0000000..f622095 --- /dev/null +++ b/lib/cli/.gitignore @@ -0,0 +1,5 @@ +*.ospx +tests.xml +coverage/* +bdd-log.xml +tests-reports/* \ No newline at end of file diff --git a/lib/cli/.travis.yml b/lib/cli/.travis.yml new file mode 100644 index 0000000..64716c3 --- /dev/null +++ b/lib/cli/.travis.yml @@ -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 diff --git a/lib/cli/CODE_OF_CONDUCT.md b/lib/cli/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..10838b8 --- /dev/null +++ b/lib/cli/CODE_OF_CONDUCT.md @@ -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/ diff --git a/lib/cli/LICENSE b/lib/cli/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/lib/cli/LICENSE @@ -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. diff --git a/lib/cli/README.md b/lib/cli/README.md new file mode 100644 index 0000000..6252e1c --- /dev/null +++ b/lib/cli/README.md @@ -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`. diff --git a/lib/cli/appveyor.yml b/lib/cli/appveyor.yml new file mode 100644 index 0000000..0c382c5 --- /dev/null +++ b/lib/cli/appveyor.yml @@ -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 \ No newline at end of file diff --git a/lib/cli/docs/readme.md b/lib/cli/docs/readme.md new file mode 100644 index 0000000..db47911 --- /dev/null +++ b/lib/cli/docs/readme.md @@ -0,0 +1,893 @@ +Описание публичного интерфейса библиотеки +======================== + + + +- [Класс КонсольноеПриложение:](#класс-консольноеприложение) + - [Публичные свойства](#публичные-свойства) + - [ФлагВерсия](#флагверсия) + - [ВерсияПриложения](#версияприложения) + - [Версия](#версия) + - [УстановитьСпек](#установитьспек) + - [ПолучитьКоманду](#получитькоманду) + - [Запустить](#запустить) + - [ДобавитьКоманду](#добавитькоманду) + - [УстановитьОсновноеДействие](#установитьосновноедействие) + - [УстановитьДействиеПередВыполнением](#установитьдействиепередвыполнением) + - [УстановитьДействиеПослеВыполнения](#установитьдействиепослевыполнения) + - [Опция](#опция) + - [Аргумент](#аргумент) + - [ВыполнитьКоманду](#выполнитькоманду) +- [Класс КомандаПриложения:](#класс-командаприложения) + - [Публичные свойства](#публичные-свойства-1) + - [Спек](#спек) + - [ПодробноеОписание](#подробноеописание) + - [Приложение](#приложение) + - [КомандыРодители](#командыродители) + - [ДобавитьПодкоманду](#добавитьподкоманду) + - [ПолучитьПодкоманды](#получитьподкоманды) + - [ПолучитьИмяКоманды](#получитьимякоманды) + - [ПолучитьСинонимы](#получитьсинонимы) + - [ПолучитьОписание](#получитьописание) + - [ЗначениеОпции](#значениеопции) + - [ЗначениеАргумента](#значениеаргумента) + - [ПараметрыКоманды](#параметрыкоманды) + - [ПередВыполнениемКоманды](#передвыполнениемкоманды) + - [ПослеВыполненияКоманды](#послевыполнениякоманды) + - [ВывестиСправку](#вывестисправку) + - [Запуск](#запуск) + - [НачалоЗапуска](#началозапуска) + - [ЭтоСинонимКоманды](#этосинонимкоманды) + - [Опция](#опция-1) + - [Аргумент](#аргумент-1) + - [УстановитьДействиеВыполнения](#установитьдействиевыполнения) + - [УстановитьДействиеПередВыполнением](#установитьдействиепередвыполнением-1) + - [УстановитьДействиеПослеВыполнения](#установитьдействиепослевыполнения-1) +- [Класс ПараметрКоманды:](#класс-параметркоманды) + - [Публичные свойства](#публичные-свойства-2) + - [Имя](#имя) + - [Описание](#описание) + - [ПодробноеОписание](#подробноеописание-1) + - [ПеременнаяОкружения](#переменнаяокружения) + - [Синонимы](#синонимы) + - [НаименованияПараметров](#наименованияпараметров) + - [СкрытьЗначение](#скрытьзначение) + - [УстановленаИзПеременнойОкружения](#установленаизпеременнойокружения) + - [УстановленаПользователем](#установленапользователем) + - [ТребоватьУстановкиПользователем](#требоватьустановкипользователем) + - [Значение](#значение) + - [ТипОпции](#типопции) + - [ЭтоМассив](#этомассив) + - [Очистить](#очистить) + - [ЗначениеВСтроку](#значениевстроку) + - [ПолучитьОбязательностьВвода](#получитьобязательностьввода) + - [УстановитьЗначение](#установитьзначение) + - [ИзПеременнойОкружения](#изпеременнойокружения) + - [Текучие функции](#текучие-функции) + - [ВОкружении](#вокружении) + - [СкрытьВСправке](#скрытьвсправке) + - [ПоУмолчанию](#поумолчанию) + - [Флаговый](#флаговый) + - [Флаг](#флаг) + - [ТБулево](#тбулево) + - [ТДата](#тдата) + - [ТЧисло](#тчисло) + - [ТСтрока](#тстрока) + - [ТМассивДат](#тмассивдат) + - [ТМассивЧисел](#тмассивчисел) + - [ТМассивСтрок](#тмассивстрок) + - [ТМассивБулево](#тмассивбулево) + - [ТПеречисление](#тперечисление) + - [Перечисление](#перечисление) + - [Описание](#описание-1) + - [ПодробноеОписание](#подробноеописание-2) + - [Псевдоним](#псевдоним) + - [Обязательный](#обязательный) + - [ВФайле](#вфайле) + - [ПроизвольныйТип](#произвольныйтип) + + + +### Класс КонсольноеПриложение: +> Основной класс для реализации консольного приложения + +#### Публичные свойства + +##### ФлагВерсия + +```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 +// Функция устанавливает произвольный тип параметра +// возвращает текущий параметр команды +// +// Параметры: +// ВходящийКлассЗначенияПараметра - класс - Произвольный класс, реализующий ряд обязательных функций +// ВходящийТипПараметра - тип - тип значения параметра +// ВходящийТипЭлементаПараметра - Тип - тип элементов значения параметра, если тип Массив +// +// Возвращаемое значение: +// ПараметрКоманды - значение из переменной ЭтотОбъект +``` \ No newline at end of file diff --git a/lib/cli/features/.gitkeep b/lib/cli/features/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/lib/cli/features/Запуск без параметров.feature b/lib/cli/features/Запуск без параметров.feature new file mode 100644 index 0000000..8e8b3cc --- /dev/null +++ b/lib/cli/features/Запуск без параметров.feature @@ -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 diff --git a/lib/cli/packagedef b/lib/cli/packagedef new file mode 100644 index 0000000..597ddd9 --- /dev/null +++ b/lib/cli/packagedef @@ -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") + ; diff --git a/lib/cli/sonar-project.properties b/lib/cli/sonar-project.properties new file mode 100644 index 0000000..2322944 --- /dev/null +++ b/lib/cli/sonar-project.properties @@ -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 diff --git a/lib/cli/sonar-qube.sh b/lib/cli/sonar-qube.sh new file mode 100644 index 0000000..1271e0f --- /dev/null +++ b/lib/cli/sonar-qube.sh @@ -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 diff --git a/lib/cli/src/core/Классы/internal/lexer/Классы/Лексер.os b/lib/cli/src/core/Классы/internal/lexer/Классы/Лексер.os new file mode 100644 index 0000000..8b749af --- /dev/null +++ b/lib/cli/src/core/Классы/internal/lexer/Классы/Лексер.os @@ -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"); \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/lexer/Модули/Токены.os b/lib/cli/src/core/Классы/internal/lexer/Модули/Токены.os new file mode 100644 index 0000000..3717ccf --- /dev/null +++ b/lib/cli/src/core/Классы/internal/lexer/Модули/Токены.os @@ -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", Токен.Тип, Токен.Значение, Токен.Позиция)); + +КонецПроцедуры \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/parser/Классы/АргументыПарсера.os b/lib/cli/src/core/Классы/internal/parser/Классы/АргументыПарсера.os new file mode 100644 index 0000000..dd60fe7 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/parser/Классы/АргументыПарсера.os @@ -0,0 +1,92 @@ +#Использовать logos + +// Ссылка на класс аргумента +Перем Аргумент Экспорт; +Перем Лог; + +Процедура ПриСозданииОбъекта(КлассОпции) + + Аргумент = КлассОпции; + +КонецПроцедуры + +// Выполняет поиск аргумента в массиве входящих аргументов +// +// Параметры: +// ВходящиеАргументы - массив - входящие аргументы приложения +// КонтекстПоиска - Объект - класс "КонтекстПарсера" +// +// Возвращаемое значение: +// Структура - структура описания токена +// * РезультатПоиска - булево - признак успешного поиска +// * Аргументы - Массив - массив оставшихся аргументов после поиска +// +Функция Поиск(Знач ВходящиеАргументы, КонтекстПоиска) Экспорт + + Аргументы = Новый Массив; + + Для каждого Арг Из ВходящиеАргументы Цикл + Аргументы.Добавить(Арг); + КонецЦикла; + + Результат = Новый Структура("РезультатПоиска, Аргументы", Аргумент.УстановленаИзПеременнойОкружения, Аргументы); + Лог.Отладка(" АргументыПарсера: + |УстановленаИзПеременнойОкружения <%1> + |УстановленаПользователем <%2>", Аргумент.УстановленаИзПеременнойОкружения, Аргумент.УстановленаПользователем); + Если Аргументы.Количество() = 0 Тогда + + Если Аргумент.УстановленаИзПеременнойОкружения + И КонтекстПоиска.НеВключенныеАргументы[Аргумент] = Истина Тогда + Результат.РезультатПоиска = Ложь; + Иначе + КонтекстПоиска.НеВключенныеАргументы.Вставить(Аргумент, Истина); + КонецЕсли; + + Возврат Результат; + + КонецЕсли; + + Если (НЕ КонтекстПоиска.СбросОпций И + СтрНачинаетсяС(Аргументы[0], "-") + И НЕ Аргументы[0] = "-") + ИЛИ ПустаяСтрока(Аргументы[0]) + Тогда + Возврат Результат; + + КонецЕсли; + + АргументКонтекст = КонтекстПоиска.Аргументы[Аргумент]; + Если АргументКонтекст = Неопределено Тогда + АргументКонтекст = Новый Массив; + КонецЕсли; + + АргументКонтекст.Добавить(Аргументы[0]); + КонтекстПоиска.Аргументы.Вставить(Аргумент, АргументКонтекст); + + Результат.РезультатПоиска = Истина; + Аргументы.Удалить(0); + + Результат.Аргументы = Аргументы; + Возврат Результат; + +КонецФункции + +// Возвращает приоритет текущего парсера +// +// Возвращаемое значение: +// число - приоритет текущего парсера +// +Функция Приоритет() Экспорт + Возврат 8; +КонецФункции + +// Возвращает имя текущего парсера +// +// Возвращаемое значение: +// строка - имя текущего парсера, на основании имени аргумента +// +Функция ВСтроку() Экспорт + Возврат Аргумент.Имя; +КонецФункции + +Лог = Логирование.ПолучитьЛог("oscript.lib.cli_class_arg"); diff --git a/lib/cli/src/core/Классы/internal/parser/Классы/ВсеОпцииПарсера.os b/lib/cli/src/core/Классы/internal/parser/Классы/ВсеОпцииПарсера.os new file mode 100644 index 0000000..ca1b570 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/parser/Классы/ВсеОпцииПарсера.os @@ -0,0 +1,139 @@ +#Использовать logos + +Перем Опции Экспорт; // Массив - элементы ПараметрКоманды - Ссылка на класс опции +Перем ОпцииИндекс Экспорт; // Соответствие - Ссылка на текущий индекс опций + +Перем Лог; + +Процедура ПриСозданииОбъекта(ВходящиеОпции, Индекс) + Опции = ВходящиеОпции; + Лог.Отладка("Тип входящей опции: %1", ТипЗнч(ВходящиеОпции)); + + ОпцииИндекс = Индекс; +КонецПроцедуры + +// Выполняет поиск опций в массиве входящих аргументов +// +// Параметры: +// ВходящиеАргументы - массив - входящие аргументы приложения +// КонтекстПоиска - Объект - класс "КонтекстПарсера" +// +// Возвращаемое значение: +// Структура - структура описания токена +// * РезультатПоиска - булево - признак успешного поиска +// * Аргументы - Массив - массив оставшихся аргументов после поиска +// +Функция Поиск(Знач ВходящиеАргументы, КонтекстПоиска) Экспорт + + Аргументы = Новый Массив; + + Для каждого Арг Из ВходящиеАргументы Цикл + Аргументы.Добавить(Арг); + КонецЦикла; + + Результат = Новый Структура("РезультатПоиска, Аргументы", Ложь, Аргументы); + + РезультатПопыткиПоиска = ПопыткаПоиска(Аргументы, КонтекстПоиска); + + Если НЕ РезультатПопыткиПоиска.РезультатПоиска Тогда + Возврат Результат; + КонецЕсли; + + АргументыДляЦикла = РезультатПопыткиПоиска.Аргументы; + + Пока Истина Цикл + + РезультатПопыткиПоискаВЦикле = ПопыткаПоиска(АргументыДляЦикла, КонтекстПоиска); + + Если НЕ РезультатПопыткиПоискаВЦикле.РезультатПоиска Тогда + Результат.РезультатПоиска = Истина; + Результат.Аргументы = РезультатПопыткиПоискаВЦикле.Аргументы; + Возврат Результат; + КонецЕсли; + + АргументыДляЦикла = РезультатПопыткиПоискаВЦикле.Аргументы; + + КонецЦикла; + + Возврат Результат; + +КонецФункции + +Функция ПопыткаПоиска(Знач Аргументы, КонтекстПоиска) + + Результат = Новый Структура("РезультатПоиска, Аргументы", Ложь, Аргументы); + + Если Аргументы.Количество() = 0 + ИЛИ КонтекстПоиска.СбросОпций Тогда + + Возврат Результат; + + КонецЕсли; + + Для каждого ОпцияПоиска Из Опции Цикл + + Если Не КонтекстПоиска.НеВключенныеОпции[ОпцияПоиска.Значение] = Неопределено Тогда + Лог.Отладка("Исключен поиск опцию %1", ОпцияПоиска.Ключ.Имя); + Продолжить; + КонецЕсли; + + Лог.Отладка("Ищу опцию %1", ОпцияПоиска.Ключ.Имя); + Лог.Отладка("Ищу опцию тип %1", ОпцияПоиска.Значение); + + КлассПоиска = Новый ОпцияПарсера(ОпцияПоиска.Значение, ОпцииИндекс); + РезультатПоиска = КлассПоиска.Поиск(Аргументы, КонтекстПоиска); + + Лог.Отладка("Длина аргументов <%1> ", Аргументы.Количество()); + Лог.Отладка("Результат поиска опции %1 = <%2>", ОпцияПоиска.Ключ.Имя, РезультатПоиска.РезультатПоиска); + Лог.Отладка("Длина аргументов после поиска <%1> ", РезультатПоиска.Аргументы.Количество()); + + Если РезультатПоиска.РезультатПоиска Тогда + + Если ОпцияПоиска.Значение.УстановленаИзПеременнойОкружения Тогда + + КонтекстПоиска.НеВключенныеОпции.Вставить(ОпцияПоиска.Значение, Истина); + + КонецЕсли; + + Возврат Новый Структура("РезультатПоиска, Аргументы", Истина, РезультатПоиска.Аргументы); + КонецЕсли; + + КонецЦикла; + + Возврат Новый Структура("РезультатПоиска, Аргументы", Ложь, Аргументы); + +КонецФункции + +// Возвращает приоритет текущего парсера +// +// Возвращаемое значение: +// число - приоритет текущего парсера +// +Функция Приоритет() Экспорт + Возврат 2; +КонецФункции + +// Возвращает имя текущего парсера +// +// Возвращаемое значение: +// строка - имя текущего парсера, на основании имени опции +// +Функция ВСтроку() Экспорт + Представление = "-"; + ДлинаОпции = 2; + + Для каждого Опция Из Опции Цикл + + ИмяОпции = Опция.Ключ.Синонимы[0]; + Если СтрНачинаетсяС(ИмяОпции, "-") Тогда + ИмяОпции = Сред(ИмяОпции, ДлинаОпции); + КонецЕсли; + + Представление = Представление + ИмяОпции; + + КонецЦикла; + + Возврат Представление; +КонецФункции + +Лог = Логирование.ПолучитьЛог("oscript.lib.cli_class_options"); \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/parser/Классы/КонтекстПарсеров.os b/lib/cli/src/core/Классы/internal/parser/Классы/КонтекстПарсеров.os new file mode 100644 index 0000000..f077029 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/parser/Классы/КонтекстПарсеров.os @@ -0,0 +1,72 @@ +Перем Опции Экспорт; // Структура Ключ - Значение (Структура описание опции) +Перем Аргументы Экспорт; // Структура + +Перем НеВключенныеОпции Экспорт; // Структура Ключ - Значение (Структура описание опции) +Перем НеВключенныеАргументы Экспорт; // Структура Ключ - Значение (Структура описание опции) + +Перем СбросОпций Экспорт; + +// Соединяет текущий контекст с входящим контекстом +// +// Параметры: +// ВходящийКонтекст - Объект - присоединяемый класс "КонтекстПарсеров" +// +Процедура ПрисоединитьКонтекст(Знач ВходящийКонтекст) Экспорт + + ОбработатьОпции(ВходящийКонтекст.Опции); + + ОбработатьАргументы(ВходящийКонтекст.Аргументы); + +КонецПроцедуры + +Процедура ОбработатьАргументы(Знач ВходящиеАргументы) + + Для каждого ВходящийАргументы Из ВходящиеАргументы Цикл + + Если ВходящийАргументы.Значение = Неопределено Тогда + Продолжить; + КонецЕсли; + + АргументыКонтекст = Аргументы[ВходящийАргументы.Ключ]; + Если АргументыКонтекст = Неопределено Тогда + АргументыКонтекст = Новый Массив; + КонецЕсли; + + Для каждого ЭлементМассива Из ВходящийАргументы.Значение Цикл + АргументыКонтекст.Добавить(ЭлементМассива); + КонецЦикла; + + Аргументы.Вставить(ВходящийАргументы.Ключ, АргументыКонтекст); + + КонецЦикла; + +КонецПроцедуры + +Процедура ОбработатьОпции(Знач ВходящиеОпции) + + Для каждого ВходящаяОпции Из ВходящиеОпции Цикл + + Если ВходящаяОпции.Значение = Неопределено Тогда + Продолжить; + КонецЕсли; + + ОпцииКонтекст = Опции[ВходящаяОпции.Ключ]; + Если ОпцииКонтекст = Неопределено Тогда + ОпцииКонтекст = Новый Массив; + КонецЕсли; + + Для каждого ЭлементМассива Из ВходящаяОпции.Значение Цикл + ОпцииКонтекст.Добавить(ЭлементМассива); + КонецЦикла; + + Опции.Вставить(ВходящаяОпции.Ключ, ОпцииКонтекст); + + КонецЦикла; + +КонецПроцедуры + +Опции = Новый Соответствие; +Аргументы = Новый Соответствие; +НеВключенныеОпции = Новый Соответствие; +НеВключенныеАргументы = Новый Соответствие; +СбросОпций = Ложь; \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/parser/Классы/ЛюбойСимвол.os b/lib/cli/src/core/Классы/internal/parser/Классы/ЛюбойСимвол.os new file mode 100644 index 0000000..80050c0 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/parser/Классы/ЛюбойСимвол.os @@ -0,0 +1,36 @@ +// Выполняет поиск любого парсера в массиве входящих аргументов +// +// Параметры: +// Аргументы - массив - входящие аргументы приложения +// КонтекстПоиска - Объект - класс "КонтекстПарсера" +// +// Возвращаемое значение: +// Структура - структура описания токена +// * РезультатПоиска - булево - признак успешного поиска +// * Аргументы - Массив - массив оставшихся аргументов после поиска +// +Функция Поиск(Аргументы, КонтекстПоиска) Экспорт + + Результат = Новый Структура("РезультатПоиска, Аргументы", Истина, Аргументы); + + Возврат Результат; + +КонецФункции + +// Возвращает приоритет текущего парсера +// +// Возвращаемое значение: +// число - приоритет текущего парсера +// +Функция Приоритет() Экспорт + Возврат 10; +КонецФункции + +// Возвращает имя текущего парсера +// +// Возвращаемое значение: +// строка - имя текущего парсера всегда "*" +// +Функция ВСтроку() Экспорт + Возврат "*"; +КонецФункции diff --git a/lib/cli/src/core/Классы/internal/parser/Классы/ОпцииЗавершениеПарсера.os b/lib/cli/src/core/Классы/internal/parser/Классы/ОпцииЗавершениеПарсера.os new file mode 100644 index 0000000..e8f7b2f --- /dev/null +++ b/lib/cli/src/core/Классы/internal/parser/Классы/ОпцииЗавершениеПарсера.os @@ -0,0 +1,36 @@ +// Выполняет поиск парсера в массиве входящих аргументов +// +// Параметры: +// Аргументы - массив - входящие аргументы приложения +// КонтекстПоиска - Объект - класс "КонтекстПарсера" +// +// Возвращаемое значение: +// Структура - структура описания токена +// * РезультатПоиска - булево - признак успешного поиска +// * Аргументы - Массив - массив оставшихся аргументов после поиска +// +Функция Поиск(Аргументы, КонтекстПоиска) Экспорт + + Результат = Новый Структура("РезультатПоиска, Аргументы", Истина, Аргументы); + + Возврат Результат; + +КонецФункции + +// Возвращает приоритет текущего парсера +// +// Возвращаемое значение: +// число - приоритет текущего парсера +// +Функция Приоритет() Экспорт + Возврат 9; +КонецФункции + +// Возвращает имя текущего парсера +// +// Возвращаемое значение: +// строка - имя текущего парсера всегда "--" +// +Функция ВСтроку() Экспорт + Возврат "--"; +КонецФункции diff --git a/lib/cli/src/core/Классы/internal/parser/Классы/ОпцияПарсера.os b/lib/cli/src/core/Классы/internal/parser/Классы/ОпцияПарсера.os new file mode 100644 index 0000000..9fac891 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/parser/Классы/ОпцияПарсера.os @@ -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"); \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/parser/Классы/Парсер.os b/lib/cli/src/core/Классы/internal/parser/Классы/Парсер.os new file mode 100644 index 0000000..f1d583b --- /dev/null +++ b/lib/cli/src/core/Классы/internal/parser/Классы/Парсер.os @@ -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"); \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/path/Классы/ВыборСовпадений.os b/lib/cli/src/core/Классы/internal/path/Классы/ВыборСовпадений.os new file mode 100644 index 0000000..95cd581 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/path/Классы/ВыборСовпадений.os @@ -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"); \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/path/Классы/Совпадение.os b/lib/cli/src/core/Классы/internal/path/Классы/Совпадение.os new file mode 100644 index 0000000..36570f9 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/path/Классы/Совпадение.os @@ -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"); \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/tools/Классы/ЧтениеСтроки.os b/lib/cli/src/core/Классы/internal/tools/Классы/ЧтениеСтроки.os new file mode 100644 index 0000000..b987f4a --- /dev/null +++ b/lib/cli/src/core/Классы/internal/tools/Классы/ЧтениеСтроки.os @@ -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"); \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/types/Классы/ТипБулево.os b/lib/cli/src/core/Классы/internal/types/Классы/ТипБулево.os new file mode 100644 index 0000000..645e332 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/types/Классы/ТипБулево.os @@ -0,0 +1,60 @@ +Перем ОписаниеОшибкиКласса; + +// Возвращает строковое представление значения типа +// +// Параметры: +// Значение - Булево - значение типа +// +// Возвращаемое значение: +// строка - значение в строковом представлении +// +Функция ВСтроку(Значение) Экспорт + + Возврат Строка(Значение); + +КонецФункции + +// Преобразует и устанавливает входящее значение к значению типа +// +// Параметры: +// ВходящееЗначение - строка - строковое представление значения +// Значение - булево - переменная для установки значения +// +// Возвращаемое значение: +// булево - конвертированные значение +// +Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт + + Если ТипЗнч(ВходящееЗначение) = Тип("Булево") Тогда + Возврат ВходящееЗначение; + КонецЕсли; + + Попытка + Значение = Булево(ВходящееЗначение); + Исключение + ОписаниеОшибкиКласса = ОписаниеОшибки(); + КонецПопытки; + + Возврат Значение; + +КонецФункции + +// Возвращает описание ошибки и устанавливает признак ошибки +// +// Параметры: +// ЕстьОшибка - булево - произвольная переменная +// +// Возвращаемое значение: +// Строка - описание текущей ошибки преобразования типов +// +Функция Ошибка(ЕстьОшибка = Ложь) Экспорт + + Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда + ЕстьОшибка = Истина; + КонецЕсли; + + Возврат ОписаниеОшибкиКласса; + +КонецФункции + +ОписаниеОшибкиКласса = ""; \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/types/Классы/ТипДатаВремя.os b/lib/cli/src/core/Классы/internal/types/Классы/ТипДатаВремя.os new file mode 100644 index 0000000..d1fa3c2 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/types/Классы/ТипДатаВремя.os @@ -0,0 +1,68 @@ +#Использовать datetime + +Перем ОписаниеОшибкиКласса; +Перем ФорматДаты; + +Процедура ПриСозданииОбъекта(Знач ВходящийФормат = "yyyy-MM-dd HH:mm:ss") + + ФорматДаты = ВходящийФормат; + +КонецПроцедуры + +// Возвращает строковое представление значения типа +// +// Параметры: +// Значение - Дата - значение типа +// +// Возвращаемое значение: +// строка - значение в строковом представлении +// +Функция ВСтроку(Значение) Экспорт + + Возврат Формат(Значение, ФорматДаты); + +КонецФункции + +// Преобразует и устанавливает входящее значение к значению типа +// +// Параметры: +// ВходящаяСтрока - строка - строковое представление значения +// Значение - Дата - переменная для установки значения +// +// Возвращаемое значение: +// дата - конвертированные значение +// +Функция УстановитьЗначение(Знач ВходящаяСтрока, Значение) Экспорт + + Попытка + ПроцессорДаты = Новый ДатаВремя(); + + Значение = ПроцессорДаты.СтрокаВДату(ВходящаяСтрока, ФорматДаты); + Исключение + Значение = Дата("20010101"); + ОписаниеОшибкиКласса = ОписаниеОшибки(); + КонецПопытки; + + Возврат Значение; + +КонецФункции + +// Возвращает описание ошибки и устанавливает признак ошибки +// +// Параметры: +// ЕстьОшибка - булево - произвольная переменная +// +// Возвращаемое значение: +// Строка - описание текущей ошибки преобразования типов +// +Функция Ошибка(ЕстьОшибка = Ложь) Экспорт + + Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда + ЕстьОшибка = Истина; + КонецЕсли; + + Возврат ОписаниеОшибкиКласса; + +КонецФункции + +ОписаниеОшибкиКласса = ""; \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивБулево.os b/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивБулево.os new file mode 100644 index 0000000..e599408 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивБулево.os @@ -0,0 +1,76 @@ + +Перем ОписаниеОшибкиКласса; + +// Возвращает строковое представление значения типа +// +// Параметры: +// Значение - массив - значение типа +// +// Возвращаемое значение: +// строка - значение в строковом представлении +// +Функция ВСтроку(Значение) Экспорт + + Возврат ПреобразоватьМассивВСтроку(Значение); + +КонецФункции + +// Преобразует и устанавливает входящее значение к значению типа +// +// Параметры: +// ВходящееЗначение - Булево - Значение флага +// Значение - массив - переменная для установки значения +// +// Возвращаемое значение: +// массив - конвертированные значение +// +Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт + + Если ТипЗнч(ВходящееЗначение) = Тип("Булево") Тогда + Значение.Добавить(ВходящееЗначение); + Иначе + Попытка + Значение.Добавить(Булево(ВходящееЗначение)); + Исключение + ОписаниеОшибкиКласса = ОписаниеОшибки(); + КонецПопытки; + КонецЕсли; + + Возврат Значение; + +КонецФункции + +// Возвращает описание ошибки и устанавливает признак ошибки +// +// Параметры: +// ЕстьОшибка - булево - произвольная переменная +// +// Возвращаемое значение: +// Строка - описание текущей ошибки преобразования типов +// +Функция Ошибка(ЕстьОшибка = Ложь) Экспорт + + Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда + ЕстьОшибка = Истина; + КонецЕсли; + + Возврат ОписаниеОшибкиКласса; + +КонецФункции + +Функция ПреобразоватьМассивВСтроку(МассивЗначений) + + Если НЕ ТипЗнч(МассивЗначений) = Тип("Массив") Тогда + Возврат ""; + КонецЕсли; + + МассивСтрок = Новый Массив; + Для Каждого Значение Из МассивЗначений Цикл + МассивСтрок.Добавить(Формат(Значение, "БЛ=Ложь; БИ=Истина")); + КонецЦикла; + + Возврат СтрСоединить(МассивСтрок, ", "); + +КонецФункции + +ОписаниеОшибкиКласса = ""; \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивДат.os b/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивДат.os new file mode 100644 index 0000000..80a87eb --- /dev/null +++ b/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивДат.os @@ -0,0 +1,85 @@ +#Использовать datetime + +Перем ОписаниеОшибкиКласса; +Перем ФорматДаты; + +Процедура ПриСозданииОбъекта(Знач ВходящийФорматДаты = "yyyy-MM-dd HH:mm:ss") + + ФорматДаты = ВходящийФорматДаты; + +КонецПроцедуры + +// Возвращает строковое представление значения типа +// +// Параметры: +// Значение - Массив - значение типа +// +// Возвращаемое значение: +// строка - значение в строковом представлении +// +Функция ВСтроку(Знач Значение) Экспорт + + Возврат ПреобразоватьМассивВСтроку(Значение); + +КонецФункции + +// Преобразует и устанавливает входящее значение к значению типа +// +// Параметры: +// ВходящееЗначение - строка - строковое представление значения +// Значение - массив - переменная для установки значения +// +// Возвращаемое значение: +// массив - конвертированные значение +// +Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт + + Попытка + ПроцессорДаты = Новый ДатаВремя(); + + ВходящееЗначение = ПроцессорДаты.СтрокаВДату(ВходящееЗначение, ФорматДаты); + Значение.Добавить(ВходящееЗначение); + Исключение + Значение = Дата("20010101"); + ОписаниеОшибкиКласса = ОписаниеОшибки(); + КонецПопытки; + + Возврат Значение; + +КонецФункции + +// Возвращает описание ошибки и устанавливает признак ошибки +// +// Параметры: +// ЕстьОшибка - булево - произвольная переменная +// +// Возвращаемое значение: +// Строка - описание текущей ошибки преобразования типов +// +Функция Ошибка(ЕстьОшибка = Ложь) Экспорт + + Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда + ЕстьОшибка = Истина; + КонецЕсли; + + Возврат ОписаниеОшибкиКласса; + +КонецФункции + +Функция ПреобразоватьМассивВСтроку(Знач Значение) + + Если НЕ ТипЗнч(Значение) = Тип("Массив") Тогда + Возврат ""; + КонецЕсли; + + Для каждого ЭлементМассива Из Значение Цикл + + ЭлементМассива = Формат(ЭлементМассива, ФорматДаты); + + КонецЦикла; + + Возврат СтрСоединить(Значение, ", "); + +КонецФункции + +ОписаниеОшибкиКласса = ""; \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивСтрок.os b/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивСтрок.os new file mode 100644 index 0000000..8a74c9f --- /dev/null +++ b/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивСтрок.os @@ -0,0 +1,67 @@ + +Перем ОписаниеОшибкиКласса; + +// Возвращает строковое представление значения типа +// +// Параметры: +// Значение - массив - значение типа +// +// Возвращаемое значение: +// строка - значение в строковом представлении +// +Функция ВСтроку(Значение) Экспорт + + Возврат ПреобразоватьМассивВСтроку(Значение); + +КонецФункции + +// Преобразует и устанавливает входящее значение к значению типа +// +// Параметры: +// ВходящееЗначение - строка - строковое представление значения +// Значение - массив - переменная для установки значения +// +// Возвращаемое значение: +// массив - конвертированные значение +// +Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт + + Попытка + Значение.Добавить(ВходящееЗначение); + Исключение + ОписаниеОшибкиКласса = ОписаниеОшибки(); + КонецПопытки; + + Возврат Значение; + +КонецФункции + +// Возвращает описание ошибки и устанавливает признак ошибки +// +// Параметры: +// ЕстьОшибка - булево - произвольная переменная +// +// Возвращаемое значение: +// Строка - описание текущей ошибки преобразования типов +// +Функция Ошибка(ЕстьОшибка = Ложь) Экспорт + + Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда + ЕстьОшибка = Истина; + КонецЕсли; + + Возврат ОписаниеОшибкиКласса; + +КонецФункции + +Функция ПреобразоватьМассивВСтроку(Значение) + + Если НЕ ТипЗнч(Значение) = Тип("Массив") Тогда + Возврат ""; + КонецЕсли; + + Возврат СтрСоединить(Значение, ", "); + +КонецФункции + +ОписаниеОшибкиКласса = ""; \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивЧисел.os b/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивЧисел.os new file mode 100644 index 0000000..ffc82c9 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/types/Классы/ТипМассивЧисел.os @@ -0,0 +1,68 @@ + +Перем ОписаниеОшибкиКласса; + +// Возвращает строковое представление значения типа +// +// Параметры: +// Значение - Массив - значение типа +// +// Возвращаемое значение: +// строка - значение в строковом представлении +// +Функция ВСтроку(Значение) Экспорт + + Возврат ПреобразоватьМассивВСтроку(Значение); + +КонецФункции + +// Преобразует и устанавливает входящее значение к значению типа +// +// Параметры: +// ВходящееЗначение - строка - строковое представление значения +// Значение - массив - переменная для установки значения +// +// Возвращаемое значение: +// массив - конвертированные значение +// +Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт + + Попытка + ВходящееЗначение = Число(ВходящееЗначение); + Значение.Добавить(ВходящееЗначение); + Исключение + ОписаниеОшибкиКласса = ОписаниеОшибки(); + КонецПопытки; + + Возврат Значение; + +КонецФункции + +// Возвращает описание ошибки и устанавливает признак ошибки +// +// Параметры: +// ЕстьОшибка - булево - произвольная переменная +// +// Возвращаемое значение: +// Строка - описание текущей ошибки преобразования типов +// +Функция Ошибка(ЕстьОшибка = Ложь) Экспорт + + Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда + ЕстьОшибка = Истина; + КонецЕсли; + + Возврат ОписаниеОшибкиКласса; + +КонецФункции + +Функция ПреобразоватьМассивВСтроку(Значение) + + Если НЕ ТипЗнч(Значение) = Тип("Массив") Тогда + Возврат ""; + КонецЕсли; + + Возврат СтрСоединить(Значение, ", "); + +КонецФункции + +ОписаниеОшибкиКласса = ""; \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/types/Классы/ТипПеречисление.os b/lib/cli/src/core/Классы/internal/types/Классы/ТипПеречисление.os new file mode 100644 index 0000000..fb08760 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/types/Классы/ТипПеречисление.os @@ -0,0 +1,123 @@ + +Перем ПеречисленияКласса Экспорт; // Соответствие + +Перем ОписаниеОшибкиКласса; + +// Возвращает строковое представление значения типа +// +// Параметры: +// Значение - Строка - значение типа +// +// Возвращаемое значение: +// строка - значение в строковом представлении +// +Функция ВСтроку(Значение) Экспорт + + Если ТипЗнч(Значение) = Тип("Сценарий") Тогда + Возврат Значение.ВСтроку(); + КонецЕсли; + + Возврат Строка(Значение); + +КонецФункции + +// Возвращает подробное описание перечислений значения типа +// +// Возвращаемое значение: +// строка - значение в строковом представлении +// +Функция ПодробноеОписание() Экспорт + + СтрокаОписания = ""; + + Для каждого КлючЗначение Из ПеречисленияКласса Цикл + + СтрокаОписания = СтрокаОписания + СтрШаблон("%1: %2", + КлючЗначение.Значение.Наименование, + КлючЗначение.Значение.ДополнительнаяСправка) + Символы.ПС; + + КонецЦикла; + + Возврат СтрокаОписания; + +КонецФункции + +// Преобразует и устанавливает входящее значение к значению типа +// +// Параметры: +// ВходящееЗначение - строка - строковое представление значения +// Значение - произвольный - переменная для установки значения +// +// Возвращаемое значение: +// Произвольный - конвертированные значение +// +Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт + + ЗначениеПеречисления = ПеречисленияКласса[ВходящееЗначение]; + + Если НЕ ЗначениеПеречисления = Неопределено Тогда + Значение = ЗначениеПеречисления.Значение; + Иначе + ОписаниеОшибкиКласса = "Выбранное значение перечисления не соответствует доступным"; + КонецЕсли; + + Возврат Значение; + +КонецФункции + +// Возвращает описание ошибки и устанавливает признак ошибки +// +// Параметры: +// ЕстьОшибка - булево - произвольная переменная +// +// Возвращаемое значение: +// Строка - описание текущей ошибки преобразования типов +// +Функция Ошибка(ЕстьОшибка = Ложь) Экспорт + + Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда + ЕстьОшибка = Истина; + КонецЕсли; + + Возврат ОписаниеОшибкиКласса; + +КонецФункции + +// Устанавливает доступные перечисления из соответствия +// +// Параметры: +// СоответствиеПеречислений - Соответствие - Доступные перечисления +// * Ключ - Строка - доступные ключи ("Наименование, Значение, ДополнительнаяСправка") +// * Значение - произвольный +// +Процедура УстановитьПеречисления(Знач СоответствиеПеречислений) Экспорт + + Если Тип("Соответствие") = ТипЗнч(СоответствиеПеречислений) Тогда + ПеречисленияКласса = СоответствиеПеречислений; + КонецЕсли; + +КонецПроцедуры + +// Добавляет перечисление в коллекцию +// +// Параметры: +// ПользовательскоеЗначение - Строка - пользовательское представление значения +// Значение - произвольный - системное значение перечисления +// ДополнительнаяСправка - строка - дополнительное описание для справки +// +Процедура ДобавитьПеречисление(Знач ПользовательскоеЗначение, Знач Значение, Знач ДополнительнаяСправка = "") Экспорт + + ПеречисленияКласса.Вставить(ПользовательскоеЗначение, + НовоеПеречисление(ПользовательскоеЗначение, Значение, ДополнительнаяСправка)); + +КонецПроцедуры + +Функция НовоеПеречисление(Знач Наименование, Знач Значение, Знач ДополнительнаяСправка = "") + + Возврат Новый Структура("Наименование, Значение, ДополнительнаяСправка", Наименование, Значение, ДополнительнаяСправка); + +КонецФункции + +ПеречисленияКласса = Новый Соответствие; + +ОписаниеОшибкиКласса = ""; \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/types/Классы/ТипСтрока.os b/lib/cli/src/core/Классы/internal/types/Классы/ТипСтрока.os new file mode 100644 index 0000000..e88806d --- /dev/null +++ b/lib/cli/src/core/Классы/internal/types/Классы/ТипСтрока.os @@ -0,0 +1,53 @@ + +Перем ОписаниеОшибкиКласса; + +// Возвращает строковое представление значения типа +// +// Параметры: +// Значение - Строка - значение типа +// +// Возвращаемое значение: +// строка - значение в строковом представлении +// +Функция ВСтроку(Значение) Экспорт + + Возврат Значение; + +КонецФункции + +// Преобразует и устанавливает входящее значение к значению типа +// +// Параметры: +// ВходящееЗначение - строка - строковое представление значения +// Значение - строка - переменная для установки значения +// +// Возвращаемое значение: +// строка - конвертированные значение +// +Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт + + Значение = Строка(ВходящееЗначение); + + Возврат Значение; + +КонецФункции + +// Возвращает описание ошибки и устанавливает признак ошибки +// +// Параметры: +// ЕстьОшибка - булево - произвольная переменная +// +// Возвращаемое значение: +// Строка - описание текущей ошибки преобразования типов +// +Функция Ошибка(ЕстьОшибка = Ложь) Экспорт + + Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда + ЕстьОшибка = Истина; + КонецЕсли; + + Возврат ОписаниеОшибкиКласса; + +КонецФункции + +ОписаниеОшибкиКласса = ""; \ No newline at end of file diff --git a/lib/cli/src/core/Классы/internal/types/Классы/ТипЧисло.os b/lib/cli/src/core/Классы/internal/types/Классы/ТипЧисло.os new file mode 100644 index 0000000..2d30280 --- /dev/null +++ b/lib/cli/src/core/Классы/internal/types/Классы/ТипЧисло.os @@ -0,0 +1,57 @@ + +Перем ОписаниеОшибкиКласса; + +// Возвращает строковое представление значения типа +// +// Параметры: +// Значение - число - значение типа +// +// Возвращаемое значение: +// строка - значение в строковом представлении +// +Функция ВСтроку(Значение) Экспорт + + Возврат Строка(Значение); + +КонецФункции + +// Преобразует и устанавливает входящее значение к значению типа +// +// Параметры: +// ВходящееЗначение - строка - строковое представление значения +// Значение - число - переменная для установки значения +// +// Возвращаемое значение: +// число - конвертированные значение +// +Функция УстановитьЗначение(Знач ВходящееЗначение, Значение) Экспорт + + Попытка + Значение = Число(ВходящееЗначение); + Исключение + ОписаниеОшибкиКласса = ОписаниеОшибки(); + КонецПопытки; + + Возврат Значение; + +КонецФункции + +// Возвращает описание ошибки и устанавливает признак ошибки +// +// Параметры: +// ЕстьОшибка - булево - произвольная переменная +// +// Возвращаемое значение: +// Строка - описание текущей ошибки преобразования типов +// +Функция Ошибка(ЕстьОшибка = Ложь) Экспорт + + Если НЕ ПустаяСтрока(ОписаниеОшибкиКласса) Тогда + ЕстьОшибка = Истина; + КонецЕсли; + + Возврат ОписаниеОшибкиКласса; + +КонецФункции + +ОписаниеОшибкиКласса = ""; \ No newline at end of file diff --git a/lib/cli/src/core/Классы/КомандаПриложения.os b/lib/cli/src/core/Классы/КомандаПриложения.os new file mode 100644 index 0000000..78be19d --- /dev/null +++ b/lib/cli/src/core/Классы/КомандаПриложения.os @@ -0,0 +1,1317 @@ +#Использовать "./internal/lexer" +#Использовать "./internal/parser" +#Использовать "./internal/types" +#Использовать "./internal/tools" +#Использовать "./internal/path" +#Использовать delegate +#Использовать logos +#Использовать reflector +#Использовать fluent + +// Пользовательская строка использования текущей команды +Перем Спек Экспорт; // Строка +// (ЗАГОТОВКА) Содержит дополнительно подробное описания для справки по команде +Перем ПодробноеОписание Экспорт; // Строка + +// Содержит экземпляр класс КонсольноеПриложения, для возможности получения экспортных свойств приложения +Перем Приложение Экспорт; // Класс КонсольноеПриложения +// Содержит входящий массив родителей текущей команды +// Устанавливается при выполнении команд родителей +Перем КомандыРодители Экспорт; // Массив классов КомандаПриложения + +Перем Имя; // Строка +Перем Синонимы; // массив строк +Перем Описание; // Строка +Перем ВложенныеКоманды; // Массив классов КомандаПриложения +Перем Опции; // Соответствие +Перем Аргументы; // Соответствие + +Перем ОпцииИндекс; // Соответствие +Перем АргументыИндекс; // Соответствие + +Перем КлассРеализации; // Объект + +Перем НачальноеСостояние; // Класс Совпадение +Перем РасширенныйРефлектор; // Класс Рефлектор + +Перем ИндексДействийКоманды; // Соответствие; + +Перем Лог; + +#Область Публичное_API_класса + +// Функция добавляет вложенную команду в текущую и возвращает экземпляр данной команды +// +// Параметры: +// ИмяПодкоманды - строка - в строке допустимо задавать синоним через пробел, например "exec e" +// ОписаниеПодкоманды - строка - описание команды для справки +// КлассРеализацииПодкоманды - объект - класс, объект реализующий функции выполнения команды. +// Так же используется, для автоматической настройки опций и параметров команды +// +// Возвращаемое значение: +// объект - класс КомандаПриложения +// +Функция ДобавитьПодкоманду(ИмяПодкоманды, ОписаниеПодкоманды, КлассРеализацииПодкоманды) Экспорт + + Подкоманда = Новый КомандаПриложения(ИмяПодкоманды, ОписаниеПодкоманды, КлассРеализацииПодкоманды, Приложение); + + ВложенныеКоманды.Добавить(Подкоманда); + + Возврат Подкоманда; + +КонецФункции + +// Функция добавляет вложенную команду в текущую и возвращает экземпляр данной команды +// Симноним метода <ДобавитьПодкоманду> +// +// Параметры: +// ИмяПодкоманды - строка - в строке допустимо задавать синоним через пробел, например "exec e" +// ОписаниеПодкоманды - строка - описание команды для справки +// КлассРеализацииПодкоманды - объект - класс, объект реализующий функции выполнения команды. +// Так же используется, для автоматической настройки опций и параметров команды +// +// Возвращаемое значение: +// объект - класс КомандаПриложения +// +Функция ДобавитьКоманду(ИмяПодкоманды, ОписаниеПодкоманды, КлассРеализацииПодкоманды) Экспорт + + Возврат ДобавитьПодкоманду(ИмяПодкоманды, ОписаниеПодкоманды, КлассРеализацииПодкоманды); + +КонецФункции + +// Функция массив вложенных команд, текущей команды +// +// Возвращаемое значение: +// Массив - элементы класс КомандаПриложения +// +Функция ПолучитьПодкоманды() Экспорт + + Возврат ВложенныеКоманды; + +КонецФункции + +// Функция возвращает текущее имя команды +// +// Возвращаемое значение: +// Строка - имя текущей команды +// +Функция ПолучитьИмяКоманды() Экспорт + Возврат Имя; +КонецФункции + +// Функция массив синонимов команды +// +// Возвращаемое значение: +// Массив - элементы строка +// +Функция ПолучитьСинонимы() Экспорт + Возврат Синонимы; +КонецФункции + +// Функция возвращает описание команды +// +// Возвращаемое значение: +// Cтрока - описание текущей команды +// +Функция ПолучитьОписание() Экспорт + Возврат Описание; +КонецФункции + +// Функция возвращает строку использования (спек) команды +// +// Возвращаемое значение: +// Cтрока - строка использования (спек) текущей команды +// +Функция ПолучитьСтрокуИспользования() Экспорт + + Возврат ?(Не ПустаяСтрока(Спек), Спек, СформироватьСтандартнуюСтрокуИспользования()); + +КонецФункции + +// Функция возвращает значение опции по переданному имени/синониму опции +// +// Параметры: +// ИмяОпции - Строка - имя или синоним опции +// +// Возвращаемое значение: +// Произвольный - полученное значение в результате чтения строки использования или переменных окружения +// +Функция ЗначениеОпции(Знач ИмяОпции) Экспорт + + ОпцияИндекса = ОпцияИзИндекса(ИмяОпции); + + Если ОпцияИндекса = Неопределено Тогда + + ЗначениеОпцииРодителя = ЗначениеОпцииКомандыРодителя(ИмяОпции); + + Если Не ЗначениеОпцииРодителя = Неопределено Тогда + Возврат ЗначениеОпцииРодителя; + КонецЕсли; + + КонецЕсли; + + Если ОпцияИндекса = Неопределено Тогда + + ВызватьИсключение СтрШаблон("Ошибка получение значения опции <%1>. + |Опция не найдена в индексе опций команды", ИмяОпции); + + КонецЕсли; + + Возврат ОпцияИндекса.Значение; + +КонецФункции + +// Функция возвращает значение аргумента по переданному имени аргумента +// +// Параметры: +// ИмяАргумента - строка - имя аргумента +// +// Возвращаемое значение: +// Произвольный - полученное значение в результате чтения строки использования или переменных окружения +// +Функция ЗначениеАргумента(Знач ИмяАргумента) Экспорт + + АргументИндекса = АргументИзИндекса(ИмяАргумента); + + Если АргументИндекса = Неопределено Тогда + ЗначениеАргументаРодителя = ЗначениеАргументаКомандыРодителя(ИмяАргумента); + + Если Не ЗначениеАргументаРодителя = Неопределено Тогда + Возврат ЗначениеАргументаРодителя; + КонецЕсли; + + КонецЕсли; + + Если АргументИндекса = Неопределено Тогда + ВызватьИсключение СтрШаблон("Ошибка получение значения аргумента <%1>. + |Аргумент не найден в индексе аргументов команды", ИмяАргумента); + КонецЕсли; + + Возврат АргументИндекса.Значение; + +КонецФункции + +// Функция возвращает значение опции команды родителя по переданному имени/синониму опции +// Возвращает первое из совпадений или неопределенно в случае отсутствия опции +// +// Параметры: +// ИмяОпции - строка - имя или синоним опции +// +// Возвращаемое значение: +// Произвольный, Неопределенно - полученное значение в результате чтения строки использования или переменных окружения +// или неопределенно в случае отсутствия в индексе указанной опции +Функция ЗначениеОпцииКомандыРодителя(Знач ИмяОпции) Экспорт + + Лог.Отладка("Ищю опцию <%1> для родителей", ИмяОпции); + + Для каждого РодительКоманды Из КомандыРодители Цикл + + Лог.Отладка(" --> Проверяю родителя <%1>", РодительКоманды.ПолучитьИмяКоманды()); + + ОпцияРодителя = РодительКоманды.ОпцияИзИндекса(ИмяОпции); + + Если НЕ ОпцияРодителя = Неопределено Тогда + Возврат ОпцияРодителя.Значение; + КонецЕсли; + + ОпцияВышестоящегоРодителя = РодительКоманды.ЗначениеОпцииКомандыРодителя(ИмяОпции); + + Если НЕ ОпцияВышестоящегоРодителя = Неопределено Тогда + Возврат ОпцияВышестоящегоРодителя.Значение; + КонецЕсли; + + КонецЦикла; + + Возврат Неопределено; + +КонецФункции + +// Функция возвращает значение аргумента команды родителя по переданному имени аргумента +// Возвращает первое из совпадений или неопределенно в случае отсутствия аргумента +// +// Параметры: +// ИмяАргумента - строка - имя аргумента +// +// Возвращаемое значение: +// Произвольный, Неопределенно - полученное значение в результате чтения строки использования или переменных окружения +// или неопределенно в случае отсутствия в индексе указанного аргумента +Функция ЗначениеАргументаКомандыРодителя(Знач ИмяАргумента) Экспорт + + Лог.Отладка("Ищю аргумент <%1> для родителей", ИмяАргумента); + + Для каждого РодительКоманды Из КомандыРодители Цикл + + Лог.Отладка(" --> Проверяю родителя <%1>", РодительКоманды.ПолучитьИмяКоманды()); + + АргументРодителя = РодительКоманды.АргументИзИндекса(ИмяАргумента); + + Если НЕ АргументРодителя = Неопределено Тогда + Возврат АргументРодителя.Значение; + КонецЕсли; + + АргументВышестоящегоРодителя = РодительКоманды.ЗначениеАргументаКомандыРодителя(ИмяАргумента); + + Если НЕ АргументВышестоящегоРодителя = Неопределено Тогда + Возврат АргументВышестоящегоРодителя.Значение; + КонецЕсли; + + КонецЦикла; + + Возврат Неопределено; + +КонецФункции + +// Функция возвращает все параметры команды, для доступа к ним по синонимам +// +// Возвращаемое значение: +// Параметры - Соответствие - содержит Соответствие +// * Ключ - Строка - имя или синоним опции/аргумента команды +// * Значение - Произвольный - полученное значение в результате чтения строки использования или переменных окружения +Функция ПараметрыКоманды() Экспорт + + ПКоманды = Новый Соответствие; + + Для каждого КлючЗначение Из ОпцииИндекс Цикл + ПКоманды.Вставить(КлючЗначение.Ключ, КлючЗначение.Значение.Значение); + КонецЦикла; + + Для каждого КлючЗначение Из АргументыИндекс Цикл + ПКоманды.Вставить(КлючЗначение.Ключ, КлючЗначение.Значение.Значение); + КонецЦикла; + + Возврат ПКоманды; + +КонецФункции + +// Процедура выводит справку по команде в консоль +Процедура ВывестиСправку() Экспорт + + СправкаВыведена = ВыполнитьДействиеКоманды("ВывестиСправку"); + + Если СправкаВыведена Тогда + Возврат; + КонецЕсли; + + Представление = ?(КомандыРодители.Количество() > 0, "Команда", "Приложение"); + + Сообщить(СтрШаблон("%1: %2 + | %3", Представление, СтрСоединить(Синонимы, ", "), ?(ПустаяСтрока(ПодробноеОписание), Описание, ПодробноеОписание))); + Сообщить(""); + + ПолныйПуть = Новый Массив; + + Для каждого Родитель Из КомандыРодители Цикл + ПолныйПуть.Добавить(Родитель.ПолучитьИмяКоманды()); + КонецЦикла; + ПолныйПуть.Добавить(СокрЛП(Имя)); + + ПутьИспользования = СтрСоединить(ПолныйПуть, " "); + СуффиксВложенныхКоманды = ""; + Если ВложенныеКоманды.Количество() > 0 Тогда + + СуффиксВложенныхКоманды = "КОМАНДА [аргументы...]"; + + КонецЕсли; + + СтрокаИспользования = СокрЛП(Спек); + + Если ПустаяСтрока(СтрокаИспользования) Тогда + СтрокаИспользования = СформироватьСтандартнуюСтрокуИспользования(); + СтрокаИспользования = СтрЗаменить(СтрокаИспользования, "-- ", ""); + КонецЕсли; + + ШаблонСтрокиИспользования = "Строка запуска: %1 %2 %3"; + Сообщить(СтрШаблон(ШаблонСтрокиИспользования, + ПутьИспользования, + СтрокаИспользования, + СуффиксВложенныхКоманды)); + + Сообщить(""); + + ШаблонЗаголовкаНаименования = "%1:" + Символы.Таб; + + Если Аргументы.Количество() > 0 Тогда + + Сообщить(СтрШаблон(ШаблонЗаголовкаНаименования, "Аргументы")); + + ТаблицаАругментов = ТаблицаАргументовДляСправки(); + + ВывестиТаблицуСправки(ТаблицаАругментов); + + КонецЕсли; + + Если Опции.Количество() > 0 Тогда + + Сообщить(СтрШаблон(ШаблонЗаголовкаНаименования, "Опции")); + ТаблицаОпций = ТаблицаОпцийДляСправки(); + ВывестиТаблицуСправки(ТаблицаОпций); + + КонецЕсли; + + Если ВложенныеКоманды.Количество() > 0 Тогда + + Сообщить(СтрШаблон(ШаблонЗаголовкаНаименования, "Доступные команды")); + + МаксимальнаяДлинаКоманд = 0; + + Для каждого ВложеннаяКоманда Из ВложенныеКоманды Цикл + НоваяДлина = СтрДлина(СтрСоединить(ВложеннаяКоманда.ПолучитьСинонимы(), ", ")); + МаксимальнаяДлинаКоманд = ?(НоваяДлина > МаксимальнаяДлинаКоманд, НоваяДлина, МаксимальнаяДлинаКоманд); + КонецЦикла; + + ШаблонВложеннойКоманды = " %1" + Символы.Таб + "%2"; + + Для каждого ВложеннаяКоманда Из ВложенныеКоманды Цикл + + ПредставлениеВлКоманды = СтрСоединить(ВложеннаяКоманда.ПолучитьСинонимы(), ", "); + ТекущаяДлина = СтрДлина(ПредставлениеВлКоманды); + + НаименованиеДляСправки = ДополнитьСтрокуПробелами(ПредставлениеВлКоманды, МаксимальнаяДлинаКоманд - ТекущаяДлина); + ОписаниеДляСправки = ВложеннаяКоманда.ПолучитьОписание(); + Сообщить(СтрШаблон(ШаблонВложеннойКоманды, НаименованиеДляСправки, ОписаниеДляСправки)); + + КонецЦикла; + + Сообщить(""); + + Сообщить(СтрШаблон("Для вывода справки по доступным командам наберите: %1 КОМАНДА %2", ПутьИспользования, "--help")); + + КонецЕсли; + +КонецПроцедуры + +// Основная процедура запуска команды приложения +// +// Параметры: +// АргументыCLI - Массив - Элементы <Строка> +// +Процедура Запуск(Знач АргументыCLI) Экспорт + + Если НужноВывестиСправку(АргументыCLI) Тогда + ВывестиСправку(); + Возврат; + КонецЕсли; + + ОчиститьАргументы(АргументыCLI); + + ПоследнийИндекс = ПолучитьОпцииИАргументы(АргументыCLI); + + Лог.Отладка("Количество входящих аргументов команды: %1", АргументыCLI.Количество()); + Лог.Отладка("Последний индекс аргументов команды: %1", ПоследнийИндекс); + + КонечныйИндексКоманды = ПоследнийИндекс; + + МассивАргументовКПарсингу = Новый Массив; + + Для ИИ = 0 По КонечныйИндексКоманды Цикл + МассивАргументовКПарсингу.Добавить(АргументыCLI[ИИ]); + КонецЦикла; + + Лог.Отладка("Читаю аргументы строки"); + ОшибкаЧтения = Не НачальноеСостояние.Прочитать(МассивАргументовКПарсингу); + + Если ОшибкаЧтения Тогда + Лог.КритичнаяОшибка("Ошибка чтения параметров команды"); + ВывестиСправку(); + ВызватьИсключение "Ошибка чтения параметров команды"; + КонецЕсли; + + ВыполнитьДействиеКоманды("ПередВыполнениемКоманды"); + + Если КонечныйИндексКоманды = АргументыCLI.ВГраница() Тогда + + Лог.Отладка("Выполняю полезную работу %1", Имя); + ВыполнитьДействиеКоманды("ВыполнитьКоманду"); + + Возврат; + КонецЕсли; + + ПервыйАргумент = АргументыCLI[КонечныйИндексКоманды + 1]; + + Для каждого ВложеннаяКоманда Из ВложенныеКоманды Цикл + + Если ВложеннаяКоманда.ЭтоСинонимКоманды(ПервыйАргумент) Тогда + + АргументыПодкоманды = Новый Массив; + СмещениеНачальногоИндекса = 2; + + НачальныйИндекс = КонечныйИндексКоманды + СмещениеНачальногоИндекса; + + Если НачальныйИндекс <= АргументыCLI.ВГраница() Тогда + + Для ИИ = НачальныйИндекс По АргументыCLI.ВГраница() Цикл + АргументыПодкоманды.Добавить(АргументыCLI[ИИ]); + КонецЦикла; + + КонецЕсли; + + ВложеннаяКоманда.НачалоЗапуска(); + ВложеннаяКоманда.Запуск(АргументыПодкоманды); + + ВыполнитьДействиеКоманды("ПослеВыполненияКоманды"); + + Возврат; + + КонецЕсли; + + КонецЦикла; + + ВыполнитьДействиеКоманды("ПослеВыполненияКоманды"); + + Если СтрНачинаетсяС(ПервыйАргумент, "-") Тогда + ВывестиСправку(); + ВызватьИсключение "Не известная опция"; + + КонецЕсли; + + ВывестиСправку(); + + ВызватьИсключение "Вызвать исключение не корректное использование"; + +КонецПроцедуры + +// Функция проверяет строку, что она является ли синонимом текущей команды +// +// Параметры: +// СтрокаПроверки - Строка - имя команды, для проверки +// +// Возвращаемое значение: +// булево - истина. если это синоним или имя текущей команды, иначе ложь +Функция ЭтоСинонимКоманды(СтрокаПроверки) Экспорт + Возврат Не Синонимы.Найти(СтрокаПроверки) = Неопределено; +КонецФункции + +// Процедура подготавливает команды к запуску +// Формирует строку использования и +// настраивает парсер для выполнения парсинга входящих параметров +// Обязательно вызывается пред выполнением команды +Процедура НачалоЗапуска() Экспорт + + КомандыРодителиДляПодчиненной = Новый Массив; + + Для каждого КомандаРодитель Из КомандыРодители Цикл + КомандыРодителиДляПодчиненной.Добавить(КомандаРодитель); + КонецЦикла; + + КомандыРодителиДляПодчиненной.Добавить(ЭтотОбъект); + + Для каждого Подчиненнаякоманда Из ВложенныеКоманды Цикл + Подчиненнаякоманда.КомандыРодители = КомандыРодителиДляПодчиненной; + КонецЦикла; + + ДобавитьОпцииВИндекс(); + ДобавитьАргументыВИндекс(); + + Лог.Отладка("Входящий спек: %1", Спек); + + СтрокаИспользования = ПолучитьСтрокуИспользования(); + + Лог.Отладка("Разбираю строку использования с помощью лексера"); + + Лексер = Новый Лексер(СтрокаИспользования).Прочитать(); + Если Лексер.ЕстьОшибка() Тогда + Лексер.ВывестиИнформациюОбОшибке(); + ВызватьИсключение "Ошибка разбора строки использования"; + КонецЕсли; + + ТокеныПарсера = Лексер.ПолучитьТокены(); + + ПараметрыПарсера = Новый Структура; + ПараметрыПарсера.Вставить("Спек", СтрокаИспользования); + ПараметрыПарсера.Вставить("Опции", Опции); + ПараметрыПарсера.Вставить("Аргументы", Аргументы); + ПараметрыПарсера.Вставить("ОпцииИндекс", ОпцииИндекс); + ПараметрыПарсера.Вставить("АргументыИндекс", АргументыИндекс); + + Парсер = Новый Парсер(ТокеныПарсера, ПараметрыПарсера); + НачальноеСостояние = парсер.Прочитать(); + + ВывестиПутьПарсераВОтладке(); + +КонецПроцедуры + +// Функция добавляет опцию команды и возвращает экземпляр данной опции +// +// Параметры: +// Имя - строка - имя опции, в строке допустимо задавать синоним через пробел, например "s some-opt" +// Значение - строка - значение опции по умолчанию +// Описание - объект - описание опции для справки. +// +// Возвращаемое значение: +// ПараметрКоманды - Созданный параметр команды +// +// Дополнительно смотри справку по классу ПараметрКоманды +Функция Опция(Имя, Значение = "", Описание = "") Экспорт + + НоваяОпция = Новый ПараметрКоманды("опция", Имя, Значение, Описание); + Опции.Вставить(НоваяОпция, НоваяОпция); + + Возврат НоваяОпция; + +КонецФункции + +// Функция добавляет аргумент команды и возвращает экземпляр данной аргумента +// +// Параметры: +// Имя - Строка - имя аргумента, в строке допустимо использование только из БОЛЬШИХ латинских букв, например "ARG" +// Значение - Строка - значение аргумента по умолчанию +// Описание - Объект - описание аргумента для справки. +// +// Возвращаемое значение: +// ПараметрКоманды - Созданный параметр команды +// +// Дополнительно смотри справку по классу ПараметрКоманды +Функция Аргумент(Имя, Значение = "", Описание = "") Экспорт + + НовыйАргумент = Новый ПараметрКоманды("аргумент", Имя, Значение, Описание); + Аргументы.Вставить(НовыйАргумент, НовыйАргумент); + + Возврат НовыйАргумент; + +КонецФункции + +// Функция возвращает значение опции по переданному имени/синониму опции +// +// Параметры: +// ИмяОпции - Строка - имя или синоним опции +// +// Возвращаемое значение: +// ПараметраКоманды, Неопределенно - класс опции, находящийся в индексе Опций команды +// Неопределенно, в случае отсутствия в индексе опций с запрошенным именем +Функция ОпцияИзИндекса(Знач ИмяОпции) Экспорт + + Если СтрНачинаетсяС(ИмяОпции, "-") + Или СтрНачинаетсяС(ИмяОпции, "--") Тогда + // Ничего не делаем переданы уже нормализированные опции + Иначе + Префикс = "-"; + Если СтрДлина(ИмяОпции) > 1 Тогда + Префикс = "--"; + КонецЕсли; + ИмяОпции = СтрШаблон("%1%2", Префикс, ИмяОпции); + КонецЕсли; + + ОпцииИндекса = ОпцииИндекс[ИмяОпции]; + + Возврат ОпцииИндекса; + +КонецФункции + +// Функция возвращает параметры команды для аргумента по переданному имени аргумента +// +// Параметры: +// ИмяАргумента - Строка - имя аргумента +// +// Возвращаемое значение: +// ПараметраКоманды, Неопределенно - класс аргумента, находящийся в индексе Аргументов команды +// Неопределенно, в случае отсутствия в индексе аргумента с запрошенным именем +Функция АргументИзИндекса(Знач ИмяАргумента) Экспорт + + АргументИндекса = АргументыИндекс[ВРег(ИмяАргумента)]; + + Возврат АргументИндекса; + +КонецФункции + +// Процедура устанавливает процедуру "ВыполнитьКоманду" выполнения для команды +// +// Параметры: +// ОбъектРеализации - Объект - класс, объект реализующий процедуру выполнения команды. +// ИмяПроцедуры - Строка - имя процедуры, отличное от стандартного "ВыполнитьКоманду" +// +Процедура УстановитьДействиеВыполнения(ОбъектРеализации, ИмяПроцедуры = "ВыполнитьКоманду") Экспорт + + РефлекторПроверки = ПолучитьРефлекторКласса(ОбъектРеализации); + ЕстьМетод = РефлекторПроверки.ЕстьПроцедура(ИмяПроцедуры, 1); + + Если Не ЕстьМетод Тогда + ВызватьИсключение НоваяИнформацияОбОшибке("Ошибка установки действия <ВыполнитьКоманду>. Объект <%1> не содержит требуемого метода <%2>", ОбъектРеализации, ИмяПроцедуры); + КонецЕсли; + + ДелегатДействия = Делегаты.Создать(ОбъектРеализации, ИмяПроцедуры); + ДобавитьВИндексДействиеКоманды("ВыполнитьКоманду", ДелегатДействия); + +КонецПроцедуры + +// Процедура устанавливает процедуру "ПередВыполнениемКоманды" выполнения для команды +// запускаемую перед выполнением "ВыполнитьКоманду" +// +// Параметры: +// ОбъектРеализации - Объект - класс, объект реализующий процедуру выполнения команды. +// ИмяПроцедуры - Строка - имя процедуры, отличное от стандартного "ПередВыполнениемКоманды" +// +Процедура УстановитьДействиеПередВыполнением(ОбъектРеализации, ИмяПроцедуры = "ПередВыполнениемКоманды") Экспорт + + Лог.Отладка("Установка метода: перед выполнением класс <%1> имя процедуры <%2>", ОбъектРеализации, ИмяПроцедуры); + + РефлекторПроверки = ПолучитьРефлекторКласса(ОбъектРеализации); + ЕстьМетод = РефлекторПроверки.ЕстьПроцедура(ИмяПроцедуры, 1); + + Если Не ЕстьМетод Тогда + ВызватьИсключение НоваяИнформацияОбОшибке("Ошибка установки действия <ПередВыполнениемКоманды>. Объект <%1> не содержит требуемого метода <%2>", ОбъектРеализации, ИмяПроцедуры); + КонецЕсли; + + Лог.Отладка(" >> метод %2 у класс <%1> найден", ОбъектРеализации, ИмяПроцедуры); + + ДелегатДействия = Делегаты.Создать(ОбъектРеализации, ИмяПроцедуры); + ДобавитьВИндексДействиеКоманды("ПередВыполнениемКоманды", ДелегатДействия); + +КонецПроцедуры + +// Процедура устанавливает процедуру "ПослеВыполненияКоманды" выполнения для команды +// запускаемую после выполнением "ВыполнитьКоманду" +// +// Параметры: +// ОбъектРеализации - Объект - класс, объект реализующий процедуру выполнения команды. +// ИмяПроцедуры - Строка - имя процедуры, отличное от стандартного "ПослеВыполненияКоманды" +// +Процедура УстановитьДействиеПослеВыполнения(ОбъектРеализации, ИмяПроцедуры = "ПослеВыполненияКоманды") Экспорт + + Лог.Отладка("Установка метода: после выполнением класс <%1> имя процедуры <%2>", ОбъектРеализации, ИмяПроцедуры); + + РефлекторПроверки = ПолучитьРефлекторКласса(ОбъектРеализации); + ЕстьМетод = РефлекторПроверки.ЕстьПроцедура(ИмяПроцедуры, 1); + + Если Не ЕстьМетод Тогда + ВызватьИсключение НоваяИнформацияОбОшибке("Ошибка установки действия <ПослеВыполненияКоманды>. Объект <%1> не содержит требуемого метода <%2>", ОбъектРеализации, ИмяПроцедуры); + КонецЕсли; + + Лог.Отладка(" >> метод %2 у класс <%1> найден", ОбъектРеализации, ИмяПроцедуры); + + ДелегатДействия = Делегаты.Создать(ОбъектРеализации, ИмяПроцедуры); + ДобавитьВИндексДействиеКоманды("ПослеВыполненияКоманды", ДелегатДействия); + +КонецПроцедуры + +// Процедура устанавливает процедуру "ВывестиСправку" для текущей команды +// +// Параметры: +// ОбъектРеализации - Объект - класс, объект реализующий процедуру вывода справки. +// ИмяПроцедуры - Строка - имя процедуры, отличное от стандартного "ВывестиСправку" +// +Процедура УстановитьДействиеВывестиСправку(ОбъектРеализации, ИмяПроцедуры = "ВывестиСправку") Экспорт + + Лог.Отладка("Установка метода: после выполнением класс <%1> имя процедуры <%2>", ОбъектРеализации, ИмяПроцедуры); + + РефлекторПроверки = ПолучитьРефлекторКласса(ОбъектРеализации); + ЕстьМетод = РефлекторПроверки.ЕстьПроцедура(ИмяПроцедуры, 1); + + Если Не ЕстьМетод Тогда + ВызватьИсключение НоваяИнформацияОбОшибке("Ошибка установки действия <ВывестиСправку>. Объект <%1> не содержит требуемого метода <%2>", ОбъектРеализации, ИмяПроцедуры); + КонецЕсли; + + Лог.Отладка(" >> метод %2 у класс <%1> найден", ОбъектРеализации, ИмяПроцедуры); + + ДелегатДействия = Делегаты.Создать(ОбъектРеализации, ИмяПроцедуры); + + ДобавитьВИндексДействиеКоманды("ВывестиСправку", ДелегатДействия); + +КонецПроцедуры + +// Возвращает таблицу опций команды +// +// Возвращаемое значение: +// ТаблицаЗначений - таблица с колонками: +// * Наименование - Строка - наименование +// * НаименованияПараметров - Массив - массив строк, с полными наименованиями опции (например, [-f, --force]) +// * Описание - Строка - краткое описание +// * ПодробноеОписание - Строка - подробное описание +// * ПеременнаяОкружения - Строка - переменная окружения, возможно несколько через пробел +// * СкрытьЗначение - Булево - признак скрытия значения по умолчанию +// * Значение - Произвольный - строковое представление значения по умолчанию +// +Функция ПолучитьТаблицуОпций() Экспорт + + Возврат ПолучитьТаблицуПараметров(Опции); + +КонецФункции + +// Возвращает таблицу аргуметов команды +// +// Возвращаемое значение: +// ТаблицаЗначений - таблица с колонками: +// * Наименование - Строка - наименование +// * НаименованияПараметров - Массив - массив строк, с полными наименованиями аргументов (например, [ARG, АРГУМЕНТ1]) +// * Описание - Строка - краткое описание +// * ПодробноеОписание - Строка - подробное описание +// * ПеременнаяОкружения - Строка - переменная окружения, возможно несколько через пробел +// * СкрытьЗначение - Булево - признак скрытия значения по умолчанию +// * Значение - Произвольный - строковое представление значения по умолчанию +// +Функция ПолучитьТаблицуАргументов() Экспорт + + Возврат ПолучитьТаблицуПараметров(Аргументы); + +КонецФункции + +#КонецОбласти + +#Область Работа_с_входящими_аргументами + +Процедура ОчиститьАргументы(АргументыCLI) + + НовыйМассивАргументов = Новый Массив; + + Для каждого арг Из АргументыCLI Цикл + + Если ПустаяСтрока(арг) Тогда + Продолжить; + КонецЕсли; + + НовыйМассивАргументов.Добавить(арг); + + КонецЦикла; + + АргументыCLI = Новый ФиксированныйМассив(НовыйМассивАргументов); + +КонецПроцедуры + +Функция ФлагУстановлен(Знач АргументыCLI, Знач Флаг) + + Если АргументыCLI.Количество() = 0 Тогда + Возврат Ложь; + КонецЕсли; + + Возврат АргументыCLI[0] = Флаг; + +КонецФункции + +Функция ПолучитьОпцииИАргументы(Знач АргументыCLI) + + ПоследнийИндекс = -1; + Лог.Отладка("Приверяю аргументы. Количество %1", АргументыCLI.Количество()); + + Для каждого ТекущийАргумент Из АргументыCLI Цикл + + Для каждого ВложеннаяКоманда Из ВложенныеКоманды Цикл + + Лог.Отладка("Ищу подчиненную команду %1", ВложеннаяКоманда.ПолучитьИмяКоманды()); + Если ВложеннаяКоманда.ЭтоСинонимКоманды(ТекущийАргумент) Тогда + Лог.Отладка("Подчиненная команда %1 найдена", ВложеннаяКоманда.ПолучитьИмяКоманды()); + Возврат ПоследнийИндекс; + КонецЕсли; + + КонецЦикла; + + ПоследнийИндекс = ПоследнийИндекс + 1; + + КонецЦикла; + + Возврат ПоследнийИндекс; + +КонецФункции + +#КонецОбласти + +#Область Работа_с_индексом_опций_и_аргументов + +Процедура ДобавитьОпцииВИндекс() + + Для каждого КлючЗначение Из Опции Цикл + + КлассОпции = КлючЗначение.Ключ; + КлассОпции.ИзПеременнойОкружения(); + + Для каждого ИмяПараметра Из КлассОпции.НаименованияПараметров Цикл + + ОпцииИндекс.Вставить(ИмяПараметра, КлассОпции); + + КонецЦикла; + + КонецЦикла; + +КонецПроцедуры + +Процедура ДобавитьАргументыВИндекс() + + Для каждого КлючЗначение Из Аргументы Цикл + + КлассАргумента = КлючЗначение.Ключ; + КлассАргумента.ИзПеременнойОкружения(); + + Для каждого ИмяПараметра Из КлассАргумента.НаименованияПараметров Цикл + + АргументыИндекс.Вставить(ИмяПараметра, КлассАргумента); + + КонецЦикла; + + КонецЦикла; + +КонецПроцедуры + +Функция ВыполнитьДействиеКоманды(ИмяДействия) + + ДелегатДействия = ИндексДействийКоманды[ИмяДействия]; + + Если ДелегатДействия = Неопределено Тогда + Возврат Ложь; + КонецЕсли; + + ДелегатДействия.Исполнить(ЭтотОбъект); + + Возврат Истина; + +КонецФункции + +#КонецОбласти + +#Область Работа_с_рефлектором_объектов + +Функция ПолучитьРефлекторКласса(КлассПроверки) + + Если Не КлассПроверки = КлассРеализации Тогда + + Возврат Новый РефлекторОбъекта(КлассПроверки); + + Иначе + + Возврат РасширенныйРефлектор; + + КонецЕсли; + +КонецФункции + +#КонецОбласти + +#Область Работа_со_справкой + +Функция НужноВывестиСправку(Знач АргументыCLI) + + Если АргументыCLI.Количество() = 0 Тогда + Возврат Ложь; + КонецЕсли; + + Лог.Отладка("Вывожу справку: %1", ФлагУстановлен(АргументыCLI, "--help")); + Возврат ФлагУстановлен(АргументыCLI, "--help"); + +КонецФункции + +Функция ПолучитьТаблицуДанныхДляСправки() + + Таблица = Новый ТаблицаЗначений; + Таблица.Колонки.Добавить("Наименование"); + Таблица.Колонки.Добавить("Описание"); + Таблица.Колонки.Добавить("ПодробноеОписание"); + Таблица.Колонки.Добавить("ПеременнаяОкружения"); + Таблица.Колонки.Добавить("СкрытьЗначение"); + Таблица.Колонки.Добавить("НаименованияПараметров"); + Таблица.Колонки.Добавить("Значение"); + + Возврат Таблица; + +КонецФункции + +Функция ТаблицаАргументовДляСправки() + + Если Аргументы.Количество() = 0 Тогда + Возврат ПолучитьТаблицуДанныхДляСправки(); + КонецЕсли; + + ТаблицаАргументов = ПолучитьТаблицуАргументов(); + + ОбработатьТаблицуПараметровДляСправки(ТаблицаАргументов); + + Возврат ТаблицаАргументов; +КонецФункции + +Функция ТаблицаОпцийДляСправки() + + Если Опции.Количество() = 0 Тогда + Возврат ПолучитьТаблицуДанныхДляСправки(); + КонецЕсли; + + ТаблицаОпций = ПолучитьТаблицуОпций(); + + ОбработатьТаблицуПараметровДляСправки(ТаблицаОпций); + + Возврат ТаблицаОпций; + +КонецФункции + +Процедура ВывестиТаблицуСправки(ТаблицаДанных) + + ДобавочнаяДлинаДополнения = 3; + + ШаблонНаименования = " %1"+ Символы.Таб + "%2"; + + Для каждого СтрокаТаблицы Из ТаблицаДанных Цикл + + Сообщить(СтрШаблон(ШаблонНаименования, СтрокаТаблицы.Наименование, СтрокаТаблицы.Описание)); + + Если Не ПустаяСтрока(СтрокаТаблицы.ПодробноеОписание) Тогда + + СтрокаНаименования = СтрШаблон(" %2%1", Символы.Таб, СтрокаТаблицы.Наименование); + + ДлинаДополнения = СтрДлина(СтрокаНаименования) + ДобавочнаяДлинаДополнения; + МассивСтрок = СтрРазделить(СтрокаТаблицы.ПодробноеОписание, Символы.ПС, Ложь); + + Для каждого СтрокаОписания Из МассивСтрок Цикл + ДопОписаниеСтроки = ДополнитьСтрокуПробеламиДо(СтрокаОписания, ДлинаДополнения); + Сообщить(ДопОписаниеСтроки); + КонецЦикла; + + КонецЕсли; + + КонецЦикла; + + Сообщить(""); + +КонецПроцедуры + +Процедура ОбработатьТаблицуПараметровДляСправки(ТаблицаПараметров) + + МаксимальнаяДлина = 9; + + Для каждого СтрокаТаблицы Из ТаблицаПараметров Цикл + + СтрокаТаблицы.Наименование = ФорматироватьНаименованиеПараметраДляСправки(СтрокаТаблицы.НаименованияПараметров); + СтрокаТаблицы.Описание = СформироватьОписаниеДляСправки(СтрокаТаблицы); + МаксимальнаяДлина = Макс(МаксимальнаяДлина, СтрДлина(СтрокаТаблицы.Наименование) + 1); + + КонецЦикла; + + Для каждого СтрокаТаблицы Из ТаблицаПараметров Цикл + + ТекущаяДлина = СтрДлина(СтрокаТаблицы.Наименование); + Если ТекущаяДлина = МаксимальнаяДлина Тогда + Продолжить; + КонецЕсли; + + СтрокаТаблицы.Наименование = ДополнитьСтрокуПробелами(СтрокаТаблицы.Наименование, МаксимальнаяДлина - ТекущаяДлина); + + КонецЦикла; + +КонецПроцедуры + +Функция СформироватьОписаниеДляСправки(СтрокаТаблицы) + + ПеременныеОкружения = ФорматироватьПеременнуюОкруженияОпцииДляСправки(СтрокаТаблицы.ПеременнаяОкружения); + ЗначениеОпции = ФорматироватьЗначениеОпцииДляСправки(СтрокаТаблицы.Значение, СтрокаТаблицы.СкрытьЗначение); + + МассивСоединения = Новый Массив; + МассивСоединения.Добавить(СтрокаТаблицы.Описание); + Если Не ПустаяСтрока(ПеременныеОкружения) Тогда + МассивСоединения.Добавить(ПеременныеОкружения); + КонецЕсли; + Если Не ПустаяСтрока(ЗначениеОпции) Тогда + МассивСоединения.Добавить(ЗначениеОпции); + КонецЕсли; + + ОписаниеДляСправки = СтрСоединить(МассивСоединения, " "); + + Возврат ОписаниеДляСправки + +КонецФункции + +Функция ДополнитьСтрокуПробелами(Знач НачальнаяСтрока, КоличествоПробелов) + + Для Счетчик = 1 По КоличествоПробелов Цикл + НачальнаяСтрока = НачальнаяСтрока + " "; + КонецЦикла; + + Возврат НачальнаяСтрока; + +КонецФункции + +Функция ДополнитьСтрокуПробеламиДо(Знач НачальнаяСтрока, Знач КоличествоПробелов) + + СтрокаПробелов = ""; + + Для Счетчик = 1 По КоличествоПробелов Цикл + СтрокаПробелов = СтрокаПробелов + " "; + КонецЦикла; + + Возврат СтрокаПробелов + НачальнаяСтрока; + +КонецФункции + +Функция ФорматироватьНаименованиеПараметраДляСправки(Знач НаименованияПараметров) + + ОграничениеДлины = 2; + + Если НаименованияПараметров.Количество() = 1 Тогда + + НаименованиеПараметра = НаименованияПараметров[0]; + + Если Не СтрНачинаетсяС(НаименованиеПараметра, "-") Тогда + Возврат НаименованиеПараметра; + КонецЕсли; + + Если СтрДлина(НаименованиеПараметра) = ОграничениеДлины Тогда + Возврат НаименованиеПараметра; + Иначе + Возврат СтрШаблон(" %1", НаименованиеПараметра); + КонецЕсли; + + КонецЕсли; + + ПроцессорКоллекций = Новый ПроцессорКоллекций; + ПроцессорКоллекций.УстановитьКоллекцию(НаименованияПараметров); + СортированныеНаименования = ПроцессорКоллекций + .Сортировать("(Первый, Второй) -> + | Возврат ПроцессорыКоллекций.СтандартнаяФункцияСравненияПрямойПорядок() + | .Выполнить(СтрДлина(Первый), СтрДлина(Второй))") + .Получить(Тип("Массив")); + + НаименованиеПараметра = СтрСоединить(СортированныеНаименования, ", "); + + Лог.Отладка("Наименование опции для справки <%1>", НаименованиеПараметра); + + Возврат НаименованиеПараметра; + +КонецФункции + +Функция ФорматироватьЗначениеОпцииДляСправки(Знач ЗначениеОпции, Знач СкрытьЗначение) + + Если СкрытьЗначение + ИЛИ ПустаяСтрока(ЗначениеОпции) Тогда + Возврат ""; + КонецЕсли; + + Возврат СтрШаблон("(по умолчанию %1)", ЗначениеОпции); + +КонецФункции + +Функция ФорматироватьПеременнуюОкруженияОпцииДляСправки(Знач ПеременнаяОкружения) + + Если ПустаяСтрока(СокрЛП(ПеременнаяОкружения)) Тогда + Возврат ""; + КонецЕсли; + + СтрокаПеременнойОкружения = ПеременнаяОкружения; + МассивПО = СтрРазделить(СтрокаПеременнойОкружения, " ", Ложь); + + Результат = "(env"; + + СтрокаРазделитель = " "; + + Для ИИ = 0 По МассивПО.ВГраница() Цикл + + Если ИИ > 0 Тогда + СтрокаРазделитель = ", "; + КонецЕсли; + + Результат = Результат + СтрШаблон("%1$%2", СтрокаРазделитель, МассивПО[ИИ]); + + КонецЦикла; + + Возврат Результат + ")"; + +КонецФункции + +#КонецОбласти + +#Область Вспомогательные_процедуры_и_функции + +Функция СформироватьСтандартнуюСтрокуИспользования() + + СтандартнаяСтрокаИспользования = ""; + + Лог.Отладка("Количество опций строки: %1", Опции.Количество()); + ЕстьОбязательнаяОпция = Ложь; + Для каждого Опция Из Опции Цикл + + ИмяОпции = Опция.Ключ.НаименованияПараметров[0]; + КлассОпции = Опция.Ключ; + + Если КлассОпции.ПолучитьОбязательностьВвода() Тогда + ЕстьОбязательнаяОпция = Истина; + КонецЕсли; + + ДополнитьИмяАргументаМассива(ИмяОпции, КлассОпции); + ДополнитьИмяАргументаНеобязательного(ИмяОпции, КлассОпции); + + СтандартнаяСтрокаИспользования = СтандартнаяСтрокаИспользования + ИмяОпции + " "; + + КонецЦикла; + + Если Не ЕстьОбязательнаяОпция И Опции.Количество() > 0 Тогда + СтандартнаяСтрокаИспользования = "[ОПЦИИ] "; + КонецЕсли; + + Если Аргументы.Количество() > 0 Тогда + СтандартнаяСтрокаИспользования = СтандартнаяСтрокаИспользования + "-- "; + КонецЕсли; + + Лог.Отладка("Количество аргументы строки: %1", Аргументы.Количество()); + Для каждого арг Из Аргументы Цикл + + ИмяАргумента = арг.Ключ.Имя; + КлассАргумента = арг.Ключ; + + ДополнитьИмяАргументаМассива(ИмяАргумента, КлассАргумента); + ДополнитьИмяАргументаНеобязательного(ИмяАргумента, КлассАргумента); + + Лог.Отладка("Добавляю аргумент <%1> в спек <%2>", ИмяАргумента, СтандартнаяСтрокаИспользования); + СтандартнаяСтрокаИспользования = СтандартнаяСтрокаИспользования + ИмяАргумента + " "; + + КонецЦикла; + + Возврат СтандартнаяСтрокаИспользования; + +КонецФункции + + +Процедура ВывестиПутьПарсераВОтладке() + + Если Лог.Уровень() = УровниЛога.Отладка Тогда + + ОбработчикВыборкиПути = Новый ВыборСовпадений(); + Лог.Отладка("Вывожу текущий путь парсинга: "); + Лог.Отладка(ОбработчикВыборкиПути.СгенеритьСтрокуПути(НачальноеСостояние)); + + КонецЕсли; + +КонецПроцедуры + +// Дополняет признаком "[]" необязательности для аргумента +// +// Параметры: +// ИмяАргумента - Строка - Имя аргумента +// КлассАргумента - Класс - класс аргумента +// +Процедура ДополнитьИмяАргументаНеобязательного(ИмяАргумента, КлассАргумента) + + Если НЕ КлассАргумента.ПолучитьОбязательностьВвода() Тогда + + ИмяАргумента = СтрШаблон("[%1]", ИмяАргумента); + + КонецЕсли; + +КонецПроцедуры + +// Дополняет признаком "..." для аргумента массива +// +// Параметры: +// ИмяАргумента - Строка - Имя аргумента +// КлассАргумента - Класс - класс аргумента +// +Процедура ДополнитьИмяАргументаМассива(ИмяАргумента, КлассАргумента) + + Если КлассАргумента.ЭтоМассив() Тогда + + ИмяАргумента = СтрШаблон("%1...", ИмяАргумента); + + КонецЕсли; + +КонецПроцедуры + +Процедура ДобавитьВИндексДействиеКоманды(ИмяДействия, ДелегатДействия) + + ИндексДействийКоманды.Вставить(ИмяДействия, ДелегатДействия); + +КонецПроцедуры + +Процедура УстановитьСтандартныеОбработчики(РеализованныеМетодыКоманды) + + Если РеализованныеМетодыКоманды.ОписаниеКоманды Тогда + КлассРеализации.ОписаниеКоманды(ЭтотОбъект); + КонецЕсли; + + Если РеализованныеМетодыКоманды.ПередВыполнениемКоманды Тогда + ДелегатДействия = Делегаты.Создать(КлассРеализации, "ПередВыполнениемКоманды"); + ДобавитьВИндексДействиеКоманды("ПередВыполнениемКоманды", ДелегатДействия); + КонецЕсли; + + Если РеализованныеМетодыКоманды.ВыполнитьКоманду Тогда + ДелегатДействия = Делегаты.Создать(КлассРеализации, "ВыполнитьКоманду"); + ДобавитьВИндексДействиеКоманды("ВыполнитьКоманду", ДелегатДействия); + КонецЕсли; + + Если РеализованныеМетодыКоманды.ПослеВыполненияКоманды Тогда + ДелегатДействия = Делегаты.Создать(КлассРеализации, "ПослеВыполненияКоманды"); + ДобавитьВИндексДействиеКоманды("ПослеВыполненияКоманды", ДелегатДействия); + КонецЕсли; + + Если РеализованныеМетодыКоманды.ВывестиСправку Тогда + ДелегатДействия = Делегаты.Создать(КлассРеализации, "ВывестиСправку"); + ДобавитьВИндексДействиеКоманды("ВывестиСправку", ДелегатДействия); + КонецЕсли; + +КонецПроцедуры + +Функция НоваяИнформацияОбОшибке(Знач ТекстСообщения, + Знач Параметр1 = Неопределено, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено, + Знач Параметр4 = Неопределено, Знач Параметр5 = Неопределено, Знач Параметр6 = Неопределено, + Знач Параметр7 = Неопределено, Знач Параметр8 = Неопределено, Знач Параметр9 = Неопределено) + + Если Параметр1 <> Неопределено Тогда + ТекстСообщения = СтрШаблон(ТекстСообщения, Параметр1, + Параметр2, Параметр3, Параметр4, Параметр5, Параметр6, Параметр7, Параметр8, Параметр9); + КонецЕсли; + + ИнфИсключение = Новый ИнформацияОбОшибке(ТекстСообщения, ЭтотОбъект); + + Возврат ИнфИсключение; + +КонецФункции + +Функция ПолучитьТаблицуПараметров(ИндексПараметров) + + ТаблицаДанных = ПолучитьТаблицуДанныхДляСправки(); + + Для каждого КлючЗначение Из ИндексПараметров Цикл + + ПараметрСправки = КлючЗначение.Ключ; + + НоваяЗапись = ТаблицаДанных.Добавить(); + + НоваяЗапись.Наименование = ПараметрСправки.Имя; + НоваяЗапись.Описание = ПараметрСправки.Описание; + НоваяЗапись.ПодробноеОписание = ПараметрСправки.ПолучитьПодробноеОписание(); + НоваяЗапись.ПеременнаяОкружения = ПараметрСправки.ПеременнаяОкружения; + НоваяЗапись.СкрытьЗначение = ПараметрСправки.СкрытьЗначение; + НоваяЗапись.НаименованияПараметров = ПараметрСправки.НаименованияПараметров; + + Если НЕ ПараметрСправки.УстановленаИзПеременнойОкружения Тогда + + НоваяЗапись.Значение = ПараметрСправки.ЗначениеВСтроку(); + + КонецЕсли; + + КонецЦикла; + + Возврат ТаблицаДанных; + +КонецФункции + +#КонецОбласти + +Процедура ПриСозданииОбъекта(ИмяКоманды, ОписаниеКоманды, КлассРеализацииКоманды, ПриложениеКоманды = Неопределено) + + Синонимы = СтрРазделить(ИмяКоманды, " ", Ложь); + Имя = Синонимы[0]; + Описание = ОписаниеКоманды; + КлассРеализации = КлассРеализацииКоманды; + + ВложенныеКоманды = Новый Массив; + КомандыРодители = Новый Массив; + Опции = Новый Соответствие; + Аргументы = Новый Соответствие; + + ОпцииИндекс = Новый Соответствие; + АргументыИндекс = Новый Соответствие; + + ИндексДействийКоманды = Новый Соответствие; + + Приложение = ПриложениеКоманды; + + Спек = ""; + ПодробноеОписание = ""; + + РасширенныйРефлектор = Новый РефлекторОбъекта(КлассРеализации); + + ИнтерфейсКоманды = Новый ИнтерфейсОбъекта(); + ИнтерфейсКоманды.П("ОписаниеКоманды", 1) + .П("ПередВыполнениемКоманды", 1) + .П("ВыполнитьКоманду", 1) + .П("ПослеВыполненияКоманды", 1) + .П("ВывестиСправку", 1) + ; + + РеализованныеМетодыКоманды = РасширенныйРефлектор.РеализованныеМетодыИнтерфейса(ИнтерфейсКоманды); + УстановитьСтандартныеОбработчики(РеализованныеМетодыКоманды); + +КонецПроцедуры + +Лог = Логирование.ПолучитьЛог("oscript.lib.cli_command"); diff --git a/lib/cli/src/core/Классы/КонсольноеПриложение.os b/lib/cli/src/core/Классы/КонсольноеПриложение.os new file mode 100644 index 0000000..02a639b --- /dev/null +++ b/lib/cli/src/core/Классы/КонсольноеПриложение.os @@ -0,0 +1,211 @@ +// Класс ПараметрКоманды, для доступа к установленному значению из вне +Перем ФлагВерсия Экспорт; +// Строковое представление версии приложения +Перем ВерсияПриложения Экспорт; + +Перем Команда; +Перем НаименованиеПриложения; +Перем ОписаниеПриложения; + +// Процедура добавляет версию приложения, +// при вызове данной опции, показывается установленная версия и +// завершается выполнение с кодом (0) +// +// Параметры: +// Наименование - строка - имя опции, в строке допустимо задавать синоним через пробел, например "v version" +// СтрокаВерсии - строка - версия, приложения +Процедура Версия(Наименование, СтрокаВерсии) Экспорт + + ВерсияПриложения = СтрокаВерсии; + ФлагВерсия = Команда.Опция(Наименование, Ложь, "показать версию и выйти"); + +КонецПроцедуры + +// Процедура позволяет переопределить стандартную строку использования приложения +// +// Параметры: +// СтрокаСпек - строка - переопределенная строка использования приложения +Процедура УстановитьСпек(Знач СтрокаСпек) Экспорт + + Команда.Спек = СтрокаСпек; + +КонецПроцедуры + +// Возвращает основную команду приложения +// +// Возвращаемое значение: +// Команда - класс КомандаПриложения +Функция ПолучитьКоманду() Экспорт + + Возврат Команда; + +КонецФункции + +// Основная процедура запуска приложения +// +// Параметры: +// АргументыКоманднойСтрокиВходящие - Массив - Элементы <Строка>, необзательный, +// Если, не передано считывает из АргументыКоманднойСтроки +Процедура Запустить(АргументыКоманднойСтрокиВходящие = Неопределено) Экспорт + + Аргументы = АргументыКоманднойСтроки; + + Если Не АргументыКоманднойСтрокиВходящие = Неопределено Тогда + Аргументы = АргументыКоманднойСтрокиВходящие; + КонецЕсли; + + Если Тип("ПараметрКоманды") = ТипЗнч(ФлагВерсия) + И ЗначениеЗаполнено(ВерсияПриложения) + И ФлагУстановлен(Аргументы, ФлагВерсия) Тогда + + ВывестиВерсию(); + ЗавершитьРаботу(0); + + КонецЕсли; + + Команда.НачалоЗапуска(); + Команда.Запуск(Аргументы); + +КонецПроцедуры + +// Функция добавляет команду приложение и возвращает экземпляр данной команды +// +// Параметры: +// ИмяКоманды - строка - в строке допустимо задавать синоним через пробел, например "exec e" +// ОписаниеКоманды - строка - описание команды для справки +// КлассРеализацииКоманды - объект - класс, объект реализующий функции выполнения команды. +// Так же используется, для автоматической настройки опций и параметров команды +// +// Возвращаемое значение: +// Команда - класс КомандаПриложения +Функция ДобавитьКоманду(ИмяКоманды, ОписаниеКоманды, КлассРеализацииКоманды) Экспорт + + Возврат Команда.ДобавитьПодкоманду(ИмяКоманды, ОписаниеКоманды, КлассРеализацииКоманды); + +КонецФункции + +// Процедура устанавливает процедуру "ВыполнитьКоманду" выполнения для приложения +// +// Параметры: +// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды. +// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ВыполнитьКоманду" +// +Процедура УстановитьОсновноеДействие(КлассРеализации, ИмяПроцедуры = "ВыполнитьКоманду") Экспорт + + Команда.УстановитьДействиеВыполнения(КлассРеализации, ИмяПроцедуры); + +КонецПроцедуры + +// Процедура устанавливает процедуру "ПередВыполнениемКоманды" выполнения для приложения +// запускаемую перед выполнением "ВыполнитьКоманду" +// +// Параметры: +// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды. +// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ПередВыполнениемКоманды" +// +Процедура УстановитьДействиеПередВыполнением(КлассРеализации, ИмяПроцедуры = "ПередВыполнениемКоманды") Экспорт + + Команда.УстановитьДействиеПередВыполнением(КлассРеализации, ИмяПроцедуры); + +КонецПроцедуры + +// Процедура устанавливает процедуру "ПослеВыполненияКоманды" выполнения для приложения +// запускаемую после выполнением "ВыполнитьКоманду" +// +// Параметры: +// КлассРеализации - объект - класс, объект реализующий процедуру выполнения команды. +// ИмяПроцедуры - строка - имя процедуры, отличное от стандартного "ПослеВыполненияКоманды" +// +Процедура УстановитьДействиеПослеВыполнения(КлассРеализации, ИмяПроцедуры = "ПослеВыполненияКоманды") Экспорт + + Команда.УстановитьДействиеПослеВыполнения(КлассРеализации, ИмяПроцедуры); + +КонецПроцедуры + +// Функция добавляет опцию приложения и возвращает экземпляр данной опции +// +// Параметры: +// Имя - строка - имя опции, в строке допустимо задавать синоним через пробел, например "s some-opt" +// Значение - строка - значение опции по умолчанию +// Описание - объект - описание опции для справки. +// +// Возвращаемое значение: +// Команда - класс ПараметрКоманды +// +// Дополнительно смотри справку по классу ПараметрКоманды +Функция Опция(Имя, Значение = "", Описание = "") Экспорт + + Возврат Команда.Опция(Имя, Значение, Описание); + +КонецФункции + +// Функция добавляет аргумент приложения и возвращает экземпляр данной аргумента +// +// Параметры: +// Имя - строка - имя аргумента, в строке допустимо использование только из БОЛЬШИХ латинских букв, например "ARG" +// Значение - строка - значение аргумента по умолчанию +// Описание - объект - описание аргумента для справки. +// +// Возвращаемое значение: +// Команда - класс ПараметрКоманды +// +// Дополнительно смотри справку по классу ПараметрКоманды +Функция Аргумент(Имя, Значение = "", Описание = "") Экспорт + + Возврат Команда.Аргумент(Имя, Значение, Описание); + +КонецФункции + +// Предопределенная процедура выполнения приложения, если не задана процедура в классе. +// Выводит справку, по работе с приложением и завершает работу с кодом "1" +// Переопределяется, процедурой "УстановитьОсновноеДействие" +// +// Параметры: +// Команда - класс КомандаПриложения - инстанс класс, для доступа к опция и аргументам выполняемой команды +// +Процедура ВыполнитьКоманду(Знач Команда) Экспорт + + Сообщить("Не корректное использование"+ Символы.ПС); + Команда.ВывестиСправку(); + ЗавершитьРаботу(1); + +КонецПроцедуры + +Процедура ВывестиВерсию() + + Сообщить(ВерсияПриложения); + +КонецПроцедуры + +Функция ФлагУстановлен(Знач АргументыCLI, Знач ОпцияФлаг) + + Если АргументыCLI.Количество() = 0 Тогда + Возврат Ложь; + КонецЕсли; + + МассивИменОпции = ОпцияФлаг.НаименованияПараметров; + + Для каждого ИмяФлага Из МассивИменОпции Цикл + + Если АргументыCLI[0] = ИмяФлага Тогда + Возврат Истина; + КонецЕсли; + + КонецЦикла; + + Возврат Ложь; + +КонецФункции + +Процедура ПриСозданииОбъекта(Знач Наименование, Знач Описание, Знач КлассРеализацииОсновныйКоманды = Неопределено) + + НаименованиеПриложения = Наименование; + ОписаниеПриложения = Описание; + + Если КлассРеализацииОсновныйКоманды = Неопределено Тогда + КлассРеализацииОсновныйКоманды = ЭтотОбъект; + КонецЕсли; + + Команда = Новый КомандаПриложения(Наименование, Описание, КлассРеализацииОсновныйКоманды, ЭтотОбъект); + +КонецПроцедуры \ No newline at end of file diff --git a/lib/cli/src/core/Классы/ПараметрКоманды.os b/lib/cli/src/core/Классы/ПараметрКоманды.os new file mode 100644 index 0000000..0764c0c --- /dev/null +++ b/lib/cli/src/core/Классы/ПараметрКоманды.os @@ -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"); diff --git a/lib/cli/tasks/coverage.os b/lib/cli/tasks/coverage.os new file mode 100644 index 0000000..41f8364 --- /dev/null +++ b/lib/cli/tasks/coverage.os @@ -0,0 +1,30 @@ +#Использовать coverage +#Использовать 1commands +#Использовать fs + +ФС.ОбеспечитьПустойКаталог("coverage"); +ПутьКСтат = "coverage/stat.json"; + +Команда = Новый Команда; +Команда.УстановитьКоманду("oscript"); +Команда.ДобавитьПараметр("-encoding=utf-8"); +Команда.ДобавитьПараметр(СтрШаблон("-codestat=%1", ПутьКСтат)); +Команда.ДобавитьПараметр("tasks/test.os"); +Команда.ПоказыватьВыводНемедленно(Истина); + +КодВозврата = Команда.Исполнить(); + +Файл_Стат = Новый Файл(ПутьКСтат); + +ИмяПакета = "cli"; + +ПроцессорГенерации = Новый ГенераторОтчетаПокрытия(); + +ПроцессорГенерации.ОтносительныеПути() + .ФайлСтатистики(Файл_Стат.ПолноеИмя) + .GenericCoverage() + .Cobertura() + .Clover(ИмяПакета) + .Сформировать(); + +ЗавершитьРаботу(КодВозврата); \ No newline at end of file diff --git a/lib/cli/tasks/test.os b/lib/cli/tasks/test.os new file mode 100644 index 0000000..36de811 --- /dev/null +++ b/lib/cli/tasks/test.os @@ -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> + |", ТестыПрошли)); +КонецЕсли; \ No newline at end of file diff --git a/lib/cli/tests/fixtures/КомандаСМассивами.os b/lib/cli/tests/fixtures/КомандаСМассивами.os new file mode 100644 index 0000000..edf304b --- /dev/null +++ b/lib/cli/tests/fixtures/КомандаСМассивами.os @@ -0,0 +1,16 @@ + + +Перем МассивДат Экспорт; + +Процедура ПриСозданииОбъекта() + +КонецПроцедуры + +Процедура ОписаниеКоманды(КомандаПриложения) Экспорт + ТекКоманда = КомандаПриложения.Опция("a datearray",,"Массив дат"); + ТекКоманда.ТМассивДат("yyyy-MM-dd", ";"); +КонецПроцедуры + +Процедура ВыполнитьКоманду(КомандаПриложения) Экспорт + МассивДат = КомандаПриложения.ЗначениеОпции("a") +КонецПроцедуры \ No newline at end of file diff --git a/lib/cli/tests/fixtures/ТестовоеПриложение.os b/lib/cli/tests/fixtures/ТестовоеПриложение.os new file mode 100644 index 0000000..2cc65f1 --- /dev/null +++ b/lib/cli/tests/fixtures/ТестовоеПриложение.os @@ -0,0 +1,32 @@ +#Использовать "../../src/core" + +Процедура ВыполнитьПриложение() + + Приложение = Новый КонсольноеПриложение( "my-tests", + "Мое описание"); + Приложение.Версия("v version", "0.1.0"); + + // Приложение.ДобавитьКоманду( + // "m make", "", + // Новый ); + + // Приложение.УстановитьОсновноеДействие(ЭтотОбъект); + Приложение.Запустить(АргументыКоманднойСтроки); + +КонецПроцедуры // ВыполнениеКоманды() + +// Процедура ВыполнитьКоманду(Знач КомандаПриложения) Экспорт +// КомандаПриложения.ВывестиСправку(); +// КонецПроцедуры + +Попытка + + ВыполнитьПриложение(); + ЗавершитьРаботу(0); + +Исключение + + Сообщить(ОписаниеОшибки()); + ЗавершитьРаботу(1); + +КонецПопытки; \ No newline at end of file diff --git a/lib/cli/tests/АргументыПарсера_test.os b/lib/cli/tests/АргументыПарсера_test.os new file mode 100644 index 0000000..d123d08 --- /dev/null +++ b/lib/cli/tests/АргументыПарсера_test.os @@ -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"); +//Лог.УстановитьУровень(УровниЛога.Отладка); \ No newline at end of file diff --git a/lib/cli/tests/ВсеОпцииПарсера_test.os b/lib/cli/tests/ВсеОпцииПарсера_test.os new file mode 100644 index 0000000..0b408fd --- /dev/null +++ b/lib/cli/tests/ВсеОпцииПарсера_test.os @@ -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"); +//Лог.УстановитьУровень(УровниЛога.Отладка); \ No newline at end of file diff --git a/lib/cli/tests/КомандаПриложения_test.os b/lib/cli/tests/КомандаПриложения_test.os new file mode 100644 index 0000000..6002abb --- /dev/null +++ b/lib/cli/tests/КомандаПриложения_test.os @@ -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, "Результат должны совпадать"); + +КонецПроцедуры + +Функция ПодготовитьТестовуюКоманду(Спек = "") + + Команда = Новый КомандаПриложения("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"); +//Лог.УстановитьУровень(УровниЛога.Отладка); \ No newline at end of file diff --git a/lib/cli/tests/КонсольноеПриложение_test.os b/lib/cli/tests/КонсольноеПриложение_test.os new file mode 100644 index 0000000..a9efdbc --- /dev/null +++ b/lib/cli/tests/КонсольноеПриложение_test.os @@ -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"); +//Лог.УстановитьУровень(УровниЛога.Отладка); \ No newline at end of file diff --git a/lib/cli/tests/Лексер_test.os b/lib/cli/tests/Лексер_test.os new file mode 100644 index 0000000..efd1654 --- /dev/null +++ b/lib/cli/tests/Лексер_test.os @@ -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), + ) + ); + + + ПроверочныеДанные.Вставить("=", ПравильныйОтвет( + Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=", 0), + ) + ); + + ПроверочныеДанные.Вставить("=", ПравильныйОтвет( + Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=", 0), + ) + ); + + ПроверочныеДанные.Вставить("=", ПравильныйОтвет( + Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=", 0), + ) + ); + + ПроверочныеДанные.Вставить("=", ПравильныйОтвет( + Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=", 0), + ) + ); + + ПроверочныеДанные.Вставить("-p=", ПравильныйОтвет( + Токены.НовыйТокен(Токены.ТипыТокенов().TTShortOpt, "-p", 0), + Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=", 2), + ) + ); + + ПроверочныеДанные.Вставить("--path=", ПравильныйОтвет( + Токены.НовыйТокен(Токены.ТипыТокенов().TTLongOpt, "--path", 0), + Токены.НовыйТокен(Токены.ТипыТокенов().TTOptValue, "=", 6), + ) + ); + + Возврат ПроверочныеДанные + +КонецФункции + +Лог = Логирование.ПолучитьЛог("oscript.lib.cli_lexer"); +//Лог.УстановитьУровень(УровниЛога.Отладка); \ No newline at end of file diff --git a/lib/cli/tests/МассивыПараметров.os b/lib/cli/tests/МассивыПараметров.os new file mode 100644 index 0000000..c9e481a --- /dev/null +++ b/lib/cli/tests/МассивыПараметров.os @@ -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")); + +КонецПроцедуры \ No newline at end of file diff --git a/lib/cli/tests/ОпцияПарсера_test.os b/lib/cli/tests/ОпцияПарсера_test.os new file mode 100644 index 0000000..ceb64c3 --- /dev/null +++ b/lib/cli/tests/ОпцияПарсера_test.os @@ -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"); +//Лог.УстановитьУровень(УровниЛога.Отладка); \ No newline at end of file diff --git a/lib/cli/tests/Парсер_test.os b/lib/cli/tests/Парсер_test.os new file mode 100644 index 0000000..484c3fd --- /dev/null +++ b/lib/cli/tests/Парсер_test.os @@ -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"); +//Лог.УстановитьУровень(УровниЛога.Отладка); \ No newline at end of file diff --git a/lib/cli/travis-ci.sh b/lib/cli/travis-ci.sh new file mode 100644 index 0000000..d2bda93 --- /dev/null +++ b/lib/cli/travis-ci.sh @@ -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 diff --git a/packagedef b/packagedef index 02ffdc5..381ea5e 100644 --- a/packagedef +++ b/packagedef @@ -10,7 +10,6 @@ .ВключитьФайл("lib.config") .ВключитьФайл("README.md") .ЗависитОт("tokenizer") - .ЗависитОт("cli") .ЗависитОт("logos") .ЗависитОт("winow", "0.8.3") .РазработкаЗависитОт("1testrunner") diff --git a/src/Классы/КонвертерКомандыCURL.os b/src/Классы/КонвертерКомандыCURL.os index 54b7cb6..708fa67 100644 --- a/src/Классы/КонвертерКомандыCURL.os +++ b/src/Классы/КонвертерКомандыCURL.os @@ -1,5 +1,5 @@ -#Использовать cli -#Использовать "../internal" +#Использовать "../internal" +#Использовать "../../lib/cli/src/core" Перем ОписаниеЗапроса; Перем КаталогСохраненияФайлов;