Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ buildNumber.properties
## Gradle
##############################
bin/
build/
.gradle
*build/
*gradle
*gradlew*
*.gradle
.gradletasknamecache
gradle-app.setting
!gradle-wrapper.jar
Expand Down
26 changes: 26 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# CLI

Данный проект - это интерпретатор командной строки, поддерживающий следующие команды:
- `cat [FILE]` - вывести на экран содержимое файла;
- `echo` - вывести на экран свой аргумент (или аргументы);
- `wc [FILE]` - вывести количество строк, слов и байт в файле;
- `pwd` - распечатать текущую директорию;
- `exit` - выйти из интерпретатора.

Интерпретатор распознает строку при помощи парсера, который разделяет текст на
лексемы ([`Lexemes`](https://github.com/PaGr0m/ifmo-software-design/blob/master/shell/src/main/java/parser/LexemType.java)),
которые поддерживают одинарные и двойные кавычки, а также оператор подстановки переменных окружения (`$`).

Все остальные команды, которые не перечислены в задании ("внешние команды") вызываются из Shell системы.

У `CLI` имеется свое окружение ([`Environment`](https://github.com/PaGr0m/ifmo-software-design/blob/master/shell/src/main/java/service/Environment.java)),
которое хранит в себе все переменные окружения, а также доступные команды.
Окружение является единственным для всего проекта.
Было принято решение избавиться от шаблона одиночки ([`Singleton`](https://refactoring.guru/ru/design-patterns/singleton))
для него, а использовать внедрение зависимостей ([`Dependency Injection`](https://en.wikipedia.org/wiki/Dependency_injection#:~:text=In%20software%20engineering%2C%20dependency%20injection,object%20is%20called%20a%20service.)).

Для имплементации команд CLI было решено использовать паттерн "Команда" ([`Command`](https://refactoring.guru/ru/design-patterns/command)),
так как очень удобно задать единый интерфейс для функционала команды и реализовать метод для каждой команды.
Для создания команд отказался от использования шаблона "Фабрика" ([`Factory Method`](https://refactoring.guru/ru/design-patterns/factory-method)),
так как в данном случае посчитал это излишнем, поскольку обращение в `HashMap` будет намного быстрее и
по названию команды можно выдавать объект (в данном случае масштабируемость шаблона "Фабрика" никак не использовалась бы).
29 changes: 29 additions & 0 deletions shell/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
plugins {
id 'java'
}

group 'org.jetbrains'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
mavenCentral()
jcenter()
}

dependencies {
implementation 'org.jetbrains:annotations:15.0'

compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.0'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.13.0'

compileOnly 'org.projectlombok:lombok:1.18.12'
annotationProcessor 'org.projectlombok:lombok:1.18.12'

testCompileOnly 'org.projectlombok:lombok:1.18.12'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile "org.mockito:mockito-core:2.+"
testCompile "org.assertj:assertj-core:3.11.1"
testAnnotationProcessor 'org.projectlombok:lombok:1.18.12'
}
11 changes: 0 additions & 11 deletions shell/docs/Plan.txt

This file was deleted.

Binary file added shell/docs/UML-Class-Diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
172 changes: 172 additions & 0 deletions shell/gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

84 changes: 84 additions & 0 deletions shell/gradlew.bat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions shell/local.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Mon Mar 02 23:59:06 MSK 2020
sdk.dir=/home/pagrom/Android/Sdk
2 changes: 2 additions & 0 deletions shell/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
rootProject.name = 'shell'

2 changes: 2 additions & 0 deletions shell/shell.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4" />
6 changes: 4 additions & 2 deletions shell/src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import service.Shell;

/**
* Shell application
*/
public class Application {

public static void main(String[] args) {
new Shell().run();
Shell.run();
}
}
19 changes: 15 additions & 4 deletions shell/src/main/java/commands/Command.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
package commands;

public interface Command {
String name();
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.stream.Collectors;

String run(String arguments, String options);
/**
* Интерфейс для команды
*/
public interface Command {
String run(List<String> arguments);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В целом, выделение команд в отдельную иерархию/использование паттерна команда (надеюсь, осознанное) здесь весьма разумно.

Но стоит подумать о том, действительно ли мы хотим из команд возвращать String, потому что это накладывает сильное ограничение: нельзя вернуть из команды частичный результат. Как следствие мы не можем одновременно выполнять команды в пайпе, всем последующим командам необходимо ждать, пока предыдущая полностью завершит работу.

Мб, сейчас это не самая большая проблема, но, конечно, на файлах >1гб проблема становится более очевидной.

@PaGr0m PaGr0m Jun 1, 2020

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Все-таки pipes немного иначе реализовал, а в команду передаю только аргументы


void setName(String name);
default String joinArguments(@NotNull List<String> arguments) {
return arguments.stream()
.filter(str -> !str.equals(""))
.map(String::trim)
.collect(Collectors.joining(" "));
}
}
Loading