diff --git a/src/nativeMain/kotlin/hu.tothlp.sshanyi/Add.kt b/src/nativeMain/kotlin/hu.tothlp.sshanyi/Add.kt new file mode 100644 index 0000000..d725ae1 --- /dev/null +++ b/src/nativeMain/kotlin/hu.tothlp.sshanyi/Add.kt @@ -0,0 +1,38 @@ +package hu.tothlp.sshanyi + +import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.parameters.groups.provideDelegate +import com.github.ajalt.clikt.parameters.options.convert +import com.github.ajalt.clikt.parameters.options.option +import com.github.ajalt.clikt.parameters.options.prompt +import com.github.ajalt.clikt.parameters.types.int +import okio.FileSystem +import okio.buffer +import okio.use + +class Add : CliktCommand(help = "Add entries to configuration") { + + private val config by ConfigOptions() + private val entryOptions by EntryOptions() + + override fun run() { + echo("New config entry:") + echo("\tHost: ${entryOptions.host}") + echo("\tHostName: ${entryOptions.hostName}") + entryOptions.user?.let { echo("\tUser: $it") } + entryOptions.port?.let { echo("\tPort: $it") } + confirm("A new entry will be added to your ${config.config} file. Continue?", abort = true) + appendConfig() + echo("Entry added. Now you can access your server with: ssh ${entryOptions.host}") + } + + private fun appendConfig() { + FileSystem.SYSTEM.appendingSink(config.config).buffer().use { + it.writeUtf8("\n") + it.writeUtf8("Host ${entryOptions.host}\n") + it.writeUtf8("HostName ${entryOptions.hostName}\n") + if(entryOptions.user != null) it.writeUtf8("User ${entryOptions.user}\n") + if(entryOptions.port != null) it.writeUtf8("Port ${entryOptions.port}\n") + } + } +} \ No newline at end of file diff --git a/src/nativeMain/kotlin/hu.tothlp.sshanyi/ConfigOptions.kt b/src/nativeMain/kotlin/hu.tothlp.sshanyi/ConfigOptions.kt new file mode 100644 index 0000000..f9a2ef1 --- /dev/null +++ b/src/nativeMain/kotlin/hu.tothlp.sshanyi/ConfigOptions.kt @@ -0,0 +1,29 @@ +package hu.tothlp.sshanyi + +import com.github.ajalt.clikt.core.context +import com.github.ajalt.clikt.output.CliktHelpFormatter +import com.github.ajalt.clikt.parameters.groups.OptionGroup +import com.github.ajalt.clikt.parameters.options.convert +import com.github.ajalt.clikt.parameters.options.default +import com.github.ajalt.clikt.parameters.options.option +import com.github.ajalt.clikt.parameters.options.validate +import kotlinx.cinterop.toKString +import okio.FileSystem +import okio.Path +import okio.Path.Companion.toPath +import platform.posix.getenv + +class ConfigOptions : OptionGroup("Config file options") { + val config: Path by option(help = "Path for the configuration file.") + .convert("FILE") { + it.toPath().takeIf { FileSystem.SYSTEM.exists(it) } ?: fail("An existing file is required.") + } + .default(getDefaultConfig().toPath()).validate { + if (!FileSystem.SYSTEM.exists(it)) fail("The default config file ($it) does not exist. Create it, or enter a different file. For more info, see --help") + } + + private fun getDefaultConfig(): String = when (Platform.osFamily) { + OsFamily.WINDOWS -> getenv("USERPROFILE")?.toKString()?.plus("\\.ssh\\config") + else -> getenv("HOME")?.toKString()?.plus("/.ssh/config") + }.orEmpty() +} diff --git a/src/nativeMain/kotlin/hu.tothlp.sshanyi/EntryOptions.kt b/src/nativeMain/kotlin/hu.tothlp.sshanyi/EntryOptions.kt new file mode 100644 index 0000000..9f8c104 --- /dev/null +++ b/src/nativeMain/kotlin/hu.tothlp.sshanyi/EntryOptions.kt @@ -0,0 +1,14 @@ +package hu.tothlp.sshanyi + +import com.github.ajalt.clikt.parameters.groups.OptionGroup +import com.github.ajalt.clikt.parameters.options.convert +import com.github.ajalt.clikt.parameters.options.option +import com.github.ajalt.clikt.parameters.options.prompt +import com.github.ajalt.clikt.parameters.types.int + +class EntryOptions : OptionGroup("Server entry options") { + val host: String by option(help = "Custom name for the Host").prompt("Host") + val hostName: String by option(help = "Hostname (can be domain or IP address)").prompt("HostName") + val user: String? by option(help = "User for SSH connection. Defaults to current user.") + val port: Int? by option(help = "Port for SSH connection. Defaults to 22.").int().convert("NUMBER") { it } +} diff --git a/src/nativeMain/kotlin/hu.tothlp.sshanyi/List.kt b/src/nativeMain/kotlin/hu.tothlp.sshanyi/List.kt index 2d1acec..beff373 100644 --- a/src/nativeMain/kotlin/hu.tothlp.sshanyi/List.kt +++ b/src/nativeMain/kotlin/hu.tothlp.sshanyi/List.kt @@ -3,40 +3,26 @@ package hu.tothlp.sshanyi import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.context import com.github.ajalt.clikt.output.CliktHelpFormatter -import com.github.ajalt.clikt.parameters.options.* +import com.github.ajalt.clikt.parameters.groups.provideDelegate import okio.FileSystem import okio.Path -import okio.Path.Companion.toPath import okio.buffer import okio.use -import platform.posix.* import kotlin.collections.List import kotlin.math.ceil -import kotlinx.cinterop.* class List : CliktCommand(help = "List configuration entries") { private val defaultPadding = 10 - private val config: Path by option(help = "Path for the configuration file.") - .convert("FILE") { - it.toPath().takeIf { FileSystem.SYSTEM.exists(it) } ?: fail("An existing file is required.") - } - .default(getDefaultConfig().toPath()).validate { - if (!FileSystem.SYSTEM.exists(it)) fail("The default config file ($it) does not exist. Create it, or enter a different file. For more info, see --help") - } + private val configOptions by ConfigOptions() init { context { helpFormatter = CliktHelpFormatter(showDefaultValues = true, width = 120) } } override fun run() { - readLines(config) + readLines(configOptions.config) } - private fun getDefaultConfig(): String = when (Platform.osFamily) { - OsFamily.WINDOWS -> getenv("USERPROFILE")?.toKString()?.plus("\\.ssh\\config") - else -> getenv("HOME")?.toKString()?.plus("/.ssh/config") - }.orEmpty() - private fun readLines(path: Path) { var configEntries = mutableListOf() var currentConfig: SSHConfig? = null @@ -74,7 +60,7 @@ class List : CliktCommand(help = "List configuration entries") { } private fun calculateCellWidthData(entries: List): Map { - val data = mapOf( + return mapOf( ConfigName.HOST to entries.mapNotNull { it.host }.plus(ConfigName.HOST.value).map { it.length } .maxBy { it }, ConfigName.HOSTNAME to entries.mapNotNull { it.hostName }.plus(ConfigName.HOSTNAME.value).map { it.length } @@ -84,7 +70,6 @@ class List : CliktCommand(help = "List configuration entries") { ConfigName.PORT to entries.mapNotNull { it.port.toStringOrEmpty() }.plus(ConfigName.PORT.value) .map { it.length }.maxBy { it }, ) - return data } private fun printHeaders(cellWidthData: Map) { @@ -100,7 +85,7 @@ class List : CliktCommand(help = "List configuration entries") { val hostPadSize = cellWidthData[ConfigName.HOST] val hostNamePadSize = cellWidthData[ConfigName.HOSTNAME] val userPadSize = cellWidthData[ConfigName.USER] - val portPadSize = cellWidthData[ConfigName.USER] + val portPadSize = cellWidthData[ConfigName.PORT] val formattedEntries = entries.map { "|${it.host.leftText(hostPadSize)}|${it.hostName.leftText(hostNamePadSize)}|${it.user.leftText(userPadSize)}|${ it.port.toStringOrEmpty().rightText(portPadSize) diff --git a/src/nativeMain/kotlin/hu.tothlp.sshanyi/Main.kt b/src/nativeMain/kotlin/hu.tothlp.sshanyi/Main.kt index 6fd8f76..8865700 100644 --- a/src/nativeMain/kotlin/hu.tothlp.sshanyi/Main.kt +++ b/src/nativeMain/kotlin/hu.tothlp.sshanyi/Main.kt @@ -1,29 +1,25 @@ package hu.tothlp.sshanyi import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.context import com.github.ajalt.clikt.core.subcommands +import com.github.ajalt.clikt.output.CliktHelpFormatter import com.github.ajalt.clikt.parameters.options.versionOption class SSHanyi : CliktCommand(name = "SSHanyi") { - init { - versionOption("1.0") - } - override fun run() { - echo(""" - _____ _____ _ _ _ -/ ___/ ___| | | | (_) -\ `--.\ `--.| |_| | __ _ _ __ _ _ _ - `--. \`--. \ _ |/ _` | '_ \| | | | | -/\__/ /\__/ / | | | (_| | | | | |_| | | -\____/\____/\_| |_/\__,_|_| |_|\__, |_| - __/ | - |___/ - """.trimIndent()) - SSHanyi().commandHelp - } + init { + versionOption("1.0", names = setOf("-v", "--version")) + context { + helpFormatter = CliktHelpFormatter(showDefaultValues = true, width = 120) + } + } + + override fun run() {} } fun main(args: Array) = SSHanyi().subcommands( - List() + Add(), + List(), + Useless() ).main(args) \ No newline at end of file diff --git a/src/nativeMain/kotlin/hu.tothlp.sshanyi/Useless.kt b/src/nativeMain/kotlin/hu.tothlp.sshanyi/Useless.kt new file mode 100644 index 0000000..3322966 --- /dev/null +++ b/src/nativeMain/kotlin/hu.tothlp.sshanyi/Useless.kt @@ -0,0 +1,38 @@ +package hu.tothlp.sshanyi + +import com.github.ajalt.clikt.core.CliktCommand + +class Useless : CliktCommand(hidden = true, name = "easteregg") { + + override fun run() { + val easter = """ + .-. .-. + / \ / \ + | _ \ / _ | + ; | \ \ / / | ; + \ \ \ \_.._/ / / / + '. '.;' ';,' .' + './ _ _ \.' + .' a __ a '. + '--./ _, \/ ,_ \.--' + ----| \ /\ / |---- + .--'\ '-' '-' /'--. + _>.__ -- _.- `; + .' _ __/ _/ + / '.,:".-\ /:, + | \.' `""`'.\\ + '-,.__/ _ .-. ;|_ + /` `|| _/ `\/_ \_|| `\ + | ||/ \-./` \ / || | + \ ||__/__|___|__|| / + \_ |_ _| / + .' \ = _= _ = _= /`\ + / `-;----=--;--' \ + \ _.-' '. / + `""` `""` + + """.trimIndent() + echo(easter) + echo("Well done!!") + } +} \ No newline at end of file