Приложение todo в Котлин


Я учусь Котлин и я сделал программу Тодо (в командной строке) с Котлин и Maven как инструмент построения.

Полный проект.

Описание

Идея моя программа для чтения файла (путь, определенный в конфигурационном файле), которая содержит список заданий.

Так как это проект цель практики, содержание файл довольно прост и выглядит так:

foo;true
bar;false
foobar;true

2 колонки:

  • Описание задачи
  • Статус задачи

Единственные действия, которые я создал следующие:

  • список задач (на стандартный вывод)
  • добавить новую задачу (написать новую строку на файл)
  • закончить задачу (путем установки статуса задачи true)

Есть и другие варианты:

  • помогите: отображение списка параметров в стандартный вывод
  • конфиг: использовать другой конфигурационный файл
  • многословный: отображение отладочного журналов
  • версия: отображает версию программы

Код

Я использую общин ЦПИ библиотеки , чтобы помочь мне разбирать параметры командной строки передаваемые в аргументах.

Я представлял задачу следующим:

class Task(var name: String, var isDone: Boolean = false) {
    // Override toString to display the task in "human"
    override fun toString(): String {
        var done = ""
        if (isDone) {
            done = "X"
        }
        return "$name \t$done"
    }
    // function to transform the task in a line to be written in the file
    fun toLine(): String {
        return "$name$SEPARATOR$isDone"
    }
}

Для того, чтобы преобразовать строку из моих задач-файл в Task например, это довольно просто:

fun parse(line: String): Task {
    val array = line.split(SEPARATOR)
    if (array.size < 2) {
        return Task("", false)
    }
    return Task(sanitize(array[0]), sanitize(array[1]).toBoolean())
}

fun sanitize(s: String): String {
    return s.replace("\n", "")
}

Я создал интерфейс Cmd что представляет собой команду:

interface Cmd {
    fun getOption(): Option
    fun isEnabled(line: CommandLine): Boolean
    fun getOptionValue(line: CommandLine): String?
}

Я также создал ActionCmd что представляет собой действие команды, такие как добавление, отделка, или список задач. Это ActionCmd реализует Cmd интерфейс:

interface ActionCmd: Cmd {
    fun execute(p: Path, arg: String)
}

Для того, чтобы избежать дублирования кода для всех моих команд, я создал абстрактный класс AbstractCmd что использует общин-Кинк-классы:

abstract class AbstractCmd: Cmd {
    override fun isEnabled(line: CommandLine): Boolean {
        return line.hasOption(getOption().longOpt)
    }

    override fun getOptionValue(line: CommandLine): String? {
        return line.getOptionValue(getOption().longOpt)
    }
}

Наконец, команды, действия следующие:

class ListCmd : AbstractCmd(), ActionCmd {
    private val option = Option("l", "list", false, "print the list of tasks")
    override fun getOption(): Option {
        return option
    }

    override fun execute(p: Path, arg: String) {
        val tasks = ArrayList<Task>()
        val stream = Files.newBufferedReader(p)
        stream.buffered().lines().forEach { line -> tasks.add(parse(line)) }
        tasks.forEach { println(it) }
    }
}

class AddCmd: AbstractCmd(), ActionCmd {
    private val option = Option("a", "add", true, "add a task")
    override fun getOption(): Option {
        return option
    }

    override fun execute(p: Path, arg: String) {
        // I have to add the empty string, otherwise, it's not going to add a new line
        p.toFile().appendText("" + Task(arg).toLine())
    }
}

class FinishCmd : AbstractCmd(), ActionCmd {
    private val option = Option("f", "finish", true, "finish a task")
    override fun getOption(): Option {
        return option
    }

    override fun execute(p: Path, arg: String) {
        val task = Task(arg)

        val tasks = ArrayList<Task>()
        val readerStream = Files.newBufferedReader(p)
        readerStream.buffered().lines().forEach { line ->
            val t = parse(line)
            if (t.name == task.name) {
                t.isDone = true
                debug("Finishing task: $t")
            }
            tasks.add(t)
        }
        File(p.toString()).printWriter().use { out ->
            tasks.forEach { out.println(it.toLine()) }
        }
    }
}

Мой код следовать оптимальной общей практики или я иду по неправильному пути?



252
6
задан 25 февраля 2018 в 05:02 Источник Поделиться
Комментарии