comparison src/main/kotlin/name/blackcap/passman/ListSubcommand.kt @ 21:ea65ab890f66

More work to support interactive feature.
author David Barts <n5jrn@me.com>
date Tue, 02 Jul 2024 11:27:39 -0700
parents 72619175004e
children 07406c4af4a5
comparison
equal deleted inserted replaced
20:4391afcf6bd0 21:ea65ab890f66
1 package name.blackcap.passman 1 package name.blackcap.passman
2 2
3 import org.apache.commons.cli.* 3 import org.apache.commons.cli.*
4 import java.util.regex.PatternSyntaxException 4 import java.util.regex.PatternSyntaxException
5 import kotlin.system.exitProcess
6 5
7 class ListSubcommand(): Subcommand() { 6 class ListSubcommand(): Subcommand() {
8 private companion object { 7 private companion object {
9 const val CASE = "case" 8 const val CASE = "case"
10 const val FIXED = "fixed" 9 const val FIXED = "fixed"
55 } 54 }
56 } 55 }
57 try { 56 try {
58 commandLine = DefaultParser().parse(options, args) 57 commandLine = DefaultParser().parse(options, args)
59 } catch (e: ParseException) { 58 } catch (e: ParseException) {
60 die(e.message ?: "syntax error", 2) 59 throw SubcommandException(message = e.message ?: "syntax error", cause = e, status = 2)
61 } 60 }
62 if (commandLine.hasOption(HELP)) { 61 if (commandLine.hasOption(HELP)) {
63 HelpFormatter().printHelp("$SHORTNAME list [options]", options) 62 HelpFormatter().printHelp("$SHORTNAME list [options]", options)
64 exitProcess(0) 63 return
65 } 64 }
66 if (commandLine.args.isNotEmpty()) { 65 if (commandLine.args.isNotEmpty()) {
67 die("unexpected trailing arguments", 2) 66 throw SubcommandException(message = "unexpected trailing arguments", status = 2)
68 } 67 }
69 68
70 STRING_OPTIONS.forEach { 69 STRING_OPTIONS.forEach {
71 commandLine.getOptionValues(it.name)?.forEach { value -> 70 commandLine.getOptionValues(it.name)?.forEach { value ->
72 val regexOptions = mutableSetOf<RegexOption>() 71 val regexOptions = mutableSetOf<RegexOption>()
80 if (it.name !in matchers) { 79 if (it.name !in matchers) {
81 matchers[it.name] = mutableListOf<(Any?) -> Boolean>() 80 matchers[it.name] = mutableListOf<(Any?) -> Boolean>()
82 } 81 }
83 matchers[it.name]!! += { x -> x is String && x.contains(Regex(value, regexOptions)) } 82 matchers[it.name]!! += { x -> x is String && x.contains(Regex(value, regexOptions)) }
84 } catch (e: PatternSyntaxException) { 83 } catch (e: PatternSyntaxException) {
85 die("${see(value)} - invalid regular expression") 84 throw SubcommandException(message = "${see(value)} - invalid regular expression", cause = e, status = 2)
86 } 85 }
87 } 86 }
88 } 87 }
89 88
90 TIME_OPTIONS.forEach { 89 TIME_OPTIONS.forEach {
91 commandLine.getOptionValues(it.name)?.forEach { rawValue -> 90 commandLine.getOptionValues(it.name)?.forEach { rawValue ->
92 if (rawValue.isEmpty()) { 91 if (rawValue.isEmpty()) {
93 die("empty string is not a valid time expression") 92 throw SubcommandException(message = "empty string is not a valid time expression")
94 } 93 }
95 val (op, exp) = when(rawValue.first()) { 94 val (op, exp) = when(rawValue.first()) {
96 '+', '>' -> Pair<Char, String>('>', rawValue.substring(1)) 95 '+', '>' -> Pair<Char, String>('>', rawValue.substring(1))
97 '=' -> Pair<Char, String>('=', rawValue.substring(1)) 96 '=' -> Pair<Char, String>('=', rawValue.substring(1))
98 '-', '<' -> Pair<Char, String>('<', rawValue.substring(1)) 97 '-', '<' -> Pair<Char, String>('<', rawValue.substring(1))
99 else -> Pair<Char, String>('=', rawValue) 98 else -> Pair<Char, String>('=', rawValue)
100 } 99 }
101 val value = parseDateTime(exp) 100 val value = parseDateTime(exp)
102 if (value == null) { 101 if (value == null) {
103 die("${see(rawValue)} - invalid time expression") 102 throw SubcommandException(message = "${see(rawValue)} - invalid time expression")
104 throw RuntimeException("will never happen")
105 } 103 }
106 if (it.name !in matchers) { 104 if (it.name !in matchers) {
107 matchers[it.name] = mutableListOf<(Any?) -> Boolean>() 105 matchers[it.name] = mutableListOf<(Any?) -> Boolean>()
108 } 106 }
109 when(op) { 107 when(op) {
115 } 113 }
116 } 114 }
117 } 115 }
118 116
119 private fun runQuery(): Unit { 117 private fun runQuery(): Unit {
120 val db = Database.open() 118 val db = Database.default
121 119
122 db.connection.prepareStatement("select $NAME, $USERNAME, $NOTES, $CREATED, $MODIFIED, $ACCESSED from passwords").use { 120 db.connection.prepareStatement("select $NAME, $USERNAME, $NOTES, $CREATED, $MODIFIED, $ACCESSED from passwords").use {
123 val results = it.executeQuery() 121 val results = it.executeQuery()
124 val printer = if (commandLine.hasOption(LONG)) Entry::printLong else Entry::print 122 val printer = if (commandLine.hasOption(LONG)) Entry::printLong else Entry::print
125 var count = 0; 123 var count = 0;