diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/kotlin/ru/tretikoff/CommandFactory.kt b/src/main/kotlin/ru/tretikoff/CommandFactory.kt index c2a22f3..26dd637 100644 --- a/src/main/kotlin/ru/tretikoff/CommandFactory.kt +++ b/src/main/kotlin/ru/tretikoff/CommandFactory.kt @@ -1,11 +1,13 @@ package ru.tretikoff import ru.tretikoff.commands.CatCommand +import ru.tretikoff.commands.CdCommand import ru.tretikoff.commands.Command import ru.tretikoff.commands.EchoCommand import ru.tretikoff.commands.ExitCommand import ru.tretikoff.commands.ExternalCommand import ru.tretikoff.commands.GrepCommand +import ru.tretikoff.commands.LsCommand import ru.tretikoff.commands.PwdCommand import ru.tretikoff.commands.WcCommand import ru.tretikoff.streams.Stream @@ -33,6 +35,8 @@ class CommandFactory private constructor() { "pwd" -> PwdCommand(ins, outs, errs, args) "wc" -> WcCommand(ins, outs, errs, args) "grep" -> GrepCommand(ins, outs, errs, args) + "ls" -> LsCommand(ins, outs, errs, args) + "cd" -> CdCommand(ins, outs, errs, args) else -> ExternalCommand(ins, outs, errs, tokens.toMutableList(), tokens.first()) } checkKeys(command, words) diff --git a/src/main/kotlin/ru/tretikoff/commands/CdCommand.kt b/src/main/kotlin/ru/tretikoff/commands/CdCommand.kt new file mode 100644 index 0000000..e6ab131 --- /dev/null +++ b/src/main/kotlin/ru/tretikoff/commands/CdCommand.kt @@ -0,0 +1,40 @@ +package ru.tretikoff.commands + +import ru.tretikoff.streams.Stream +import java.io.File +import java.util.logging.Logger + +class CdCommand( + ins: Stream, + out: Stream, + err: Stream, + args: MutableList, +) : + Command(ins, out, err, args) { + private val logger = Logger.getLogger(CatCommand::class.java.name) + override fun execute(): Int { + logger.finest("Running cd with arguments $args") + if (args.isEmpty()) { + val path = System.getProperty("user.home") + return cdPath(path) + } else if (args.count() == 1) { + return cdPath(args.get(0)) + } else { + outputStream.writeLine("usage: cd [path]") + return 1 + } + } + + private fun cdPath(path: String): Int { + val file = File(path).getAbsoluteFile() + if (!file.exists()) { + errorStream.writeLine("no such directory: \"$path\"") + return 2 + } else if (!file.isDirectory()) { + errorStream.writeLine("not a directory: \"$path\"") + return 3 + } + System.setProperty("user.dir", file.getAbsolutePath()) + return 0 + } +} diff --git a/src/main/kotlin/ru/tretikoff/commands/ExternalCommand.kt b/src/main/kotlin/ru/tretikoff/commands/ExternalCommand.kt index f2d26ae..b25eaa6 100644 --- a/src/main/kotlin/ru/tretikoff/commands/ExternalCommand.kt +++ b/src/main/kotlin/ru/tretikoff/commands/ExternalCommand.kt @@ -3,6 +3,7 @@ package ru.tretikoff.commands import ru.tretikoff.CommandNotFoundException import ru.tretikoff.streams.Stream import java.io.BufferedReader +import java.io.File import java.io.IOException import java.io.InputStreamReader import java.util.logging.Logger @@ -23,7 +24,7 @@ class ExternalCommand( override fun execute(): Int { try { - val p = Runtime.getRuntime().exec(args[0]) + val p = Runtime.getRuntime().exec(args[0], null, File(System.getProperty("user.dir"))) p.waitFor() val stdInput = BufferedReader(InputStreamReader(p.inputStream)) val stdError = BufferedReader(InputStreamReader(p.errorStream)) diff --git a/src/main/kotlin/ru/tretikoff/commands/LsCommand.kt b/src/main/kotlin/ru/tretikoff/commands/LsCommand.kt new file mode 100644 index 0000000..bad6464 --- /dev/null +++ b/src/main/kotlin/ru/tretikoff/commands/LsCommand.kt @@ -0,0 +1,50 @@ +package ru.tretikoff.commands + +import ru.tretikoff.streams.Stream +import java.io.File +import java.util.logging.Logger + +class LsCommand( + ins: Stream, + out: Stream, + err: Stream, + args: MutableList, +) : + Command(ins, out, err, args) { + private val logger = Logger.getLogger(CatCommand::class.java.name) + override fun execute(): Int { + logger.finest("Running ls with arguments $args") + if (args.isEmpty()) { + val path = System.getProperty("user.dir") + return lsPath(path) + } else if (args.count() == 1) { + return lsPath(args.get(0)) + } else { + outputStream.writeLine("usage: ls [path]") + return 1 + } + } + + private fun lsPath(path: String): Int { + var parent = "" + if (!path.startsWith("/")) { + parent = System.getProperty("user.dir") + } + val file = File(parent, path).getAbsoluteFile() + val files = file.list() + if (!file.exists()) { + errorStream.writeLine("no such file or directory: \"$path\"") + return 2 + } + if (files == null) { + outputStream.writeLine(path) + } else { + files.forEach { + if (!it.startsWith(".")) { + outputStream.writeLine(it) + } + } + } + return 0 + } +} diff --git a/src/main/kotlin/ru/tretikoff/streams/FileStream.kt b/src/main/kotlin/ru/tretikoff/streams/FileStream.kt index 490d338..94c2455 100644 --- a/src/main/kotlin/ru/tretikoff/streams/FileStream.kt +++ b/src/main/kotlin/ru/tretikoff/streams/FileStream.kt @@ -20,7 +20,11 @@ open class FileStream(filename: String) : Stream() { init { try { - file = File(filename) + var parent = "" + if (!filename.startsWith("/")) { + parent = System.getProperty("user.dir") + } + file = File(parent, filename).getAbsoluteFile() outputStream = FileOutputStream(file, true) br = file.inputStream().bufferedReader() } catch (e: FileNotFoundException) { diff --git a/src/test/kotlin/ru/tretikoff/CdTest.kt b/src/test/kotlin/ru/tretikoff/CdTest.kt new file mode 100644 index 0000000..197e9ae --- /dev/null +++ b/src/test/kotlin/ru/tretikoff/CdTest.kt @@ -0,0 +1,30 @@ +package ru.tretikoff + +import kotlin.test.Test +import kotlin.test.assertEquals + +class CdTest : BashTest() { + @Test + fun cdHome() { + stdin.writeLine("cd") + stdin.writeLine("pwd") + shell.run() + assertEquals(System.getProperty("user.home"), stdout.read()) + } + + @Test + fun cdDir() { + stdin.writeLine("cd src") + stdin.writeLine("ls") + shell.run() + assertEquals("main", stdout.read()) + assertEquals("test", stdout.read()) + } + + @Test + fun cdErr() { + stdin.writeLine("cd abaaa") + shell.run() + assertEquals("no such directory: \"abaaa\"", stderr.read()) + } +} diff --git a/src/test/kotlin/ru/tretikoff/LsTest.kt b/src/test/kotlin/ru/tretikoff/LsTest.kt new file mode 100644 index 0000000..412df05 --- /dev/null +++ b/src/test/kotlin/ru/tretikoff/LsTest.kt @@ -0,0 +1,28 @@ +package ru.tretikoff + +import kotlin.test.Test +import kotlin.test.assertEquals + +class LsTest : BashTest() { + @Test + fun lsDir() { + stdin.writeLine("ls src") + shell.run() + assertEquals("main", stdout.read()) + assertEquals("test", stdout.read()) + } + + @Test + fun lsFile() { + stdin.writeLine("ls gradlew.bat") + shell.run() + assertEquals("gradlew.bat", stdout.read()) + } + + @Test + fun lsErr() { + stdin.writeLine("ls abaaa") + shell.run() + assertEquals("no such file or directory: \"abaaa\"", stderr.read()) + } +}