mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-25 15:40:28 +08:00
CommandValueArgumentParser
This commit is contained in:
parent
1e9b498ba9
commit
86c3b18bca
@ -150,8 +150,8 @@ public object BuiltInCommands {
|
||||
ConsoleCommandOwner, "permission", "权限", "perm",
|
||||
description = "管理权限",
|
||||
overrideContext = buildCommandArgumentContext {
|
||||
PermitteeId::class with PermitteeIdArgumentParser
|
||||
Permission::class with PermissionIdArgumentParser.map { id ->
|
||||
PermitteeId::class with PermitteeIdValueArgumentParser
|
||||
Permission::class with PermissionIdValueArgumentParser.map { id ->
|
||||
kotlin.runCatching {
|
||||
id.findCorrespondingPermissionOrFail()
|
||||
}.getOrElse { illegalArgument("指令不存在: $id", it) }
|
||||
|
@ -99,7 +99,7 @@ public abstract class CompositeCommand(
|
||||
public override val usage: String get() = super.usage
|
||||
|
||||
/**
|
||||
* [CommandArgumentParser] 的环境
|
||||
* [CommandValueArgumentParser] 的环境
|
||||
*/
|
||||
public final override val context: CommandArgumentContext = CommandArgumentContext.Builtins + overrideContext
|
||||
|
||||
|
@ -31,7 +31,7 @@ import net.mamoe.mirai.message.data.MessageChain
|
||||
* 简单的, 支持参数自动解析的指令.
|
||||
*
|
||||
* 要查看指令解析流程, 参考 [CommandManager.executeCommand]
|
||||
* 要查看参数解析方式, 参考 [CommandArgumentParser]
|
||||
* 要查看参数解析方式, 参考 [CommandValueArgumentParser]
|
||||
*
|
||||
* Kotlin 实现:
|
||||
* ```
|
||||
|
@ -29,7 +29,7 @@ import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
|
||||
/**
|
||||
* 指令参数环境, 即 [CommandArgumentParser] 的集合, 用于 [CompositeCommand] 和 [SimpleCommand].
|
||||
* 指令参数环境, 即 [CommandValueArgumentParser] 的集合, 用于 [CompositeCommand] 和 [SimpleCommand].
|
||||
*
|
||||
* 在指令解析时, 总是从 [CommandArgumentContextAware.context] 搜索相关解析器
|
||||
*
|
||||
@ -38,20 +38,20 @@ import kotlin.reflect.full.isSubclassOf
|
||||
* @see SimpleCommandArgumentContext 简单实现
|
||||
* @see EmptyCommandArgumentContext 空实现, 类似 [emptyList]
|
||||
*
|
||||
* @see CommandArgumentContext.Builtins 内建 [CommandArgumentParser]
|
||||
* @see CommandArgumentContext.Builtins 内建 [CommandValueArgumentParser]
|
||||
*
|
||||
* @see buildCommandArgumentContext DSL 构造
|
||||
*/
|
||||
public interface CommandArgumentContext {
|
||||
/**
|
||||
* [KClass] 到 [CommandArgumentParser] 的匹配
|
||||
* [KClass] 到 [CommandValueArgumentParser] 的匹配
|
||||
*/
|
||||
public data class ParserPair<T : Any>(
|
||||
val klass: KClass<T>,
|
||||
val parser: CommandArgumentParser<T>,
|
||||
val parser: CommandValueArgumentParser<T>,
|
||||
)
|
||||
|
||||
public operator fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>?
|
||||
public operator fun <T : Any> get(klass: KClass<out T>): CommandValueArgumentParser<T>?
|
||||
|
||||
public fun toList(): List<ParserPair<*>>
|
||||
|
||||
@ -66,32 +66,32 @@ public interface CommandArgumentContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* 内建的默认 [CommandArgumentParser]
|
||||
* 内建的默认 [CommandValueArgumentParser]
|
||||
*/
|
||||
public object Builtins : CommandArgumentContext by (buildCommandArgumentContext {
|
||||
Int::class with IntArgumentParser
|
||||
Byte::class with ByteArgumentParser
|
||||
Short::class with ShortArgumentParser
|
||||
Boolean::class with BooleanArgumentParser
|
||||
String::class with StringArgumentParser
|
||||
Long::class with LongArgumentParser
|
||||
Double::class with DoubleArgumentParser
|
||||
Float::class with FloatArgumentParser
|
||||
Int::class with IntValueArgumentParser
|
||||
Byte::class with ByteValueArgumentParser
|
||||
Short::class with ShortValueArgumentParser
|
||||
Boolean::class with BooleanValueArgumentParser
|
||||
String::class with StringValueArgumentParser
|
||||
Long::class with LongValueArgumentParser
|
||||
Double::class with DoubleValueArgumentParser
|
||||
Float::class with FloatValueArgumentParser
|
||||
|
||||
Image::class with ImageArgumentParser
|
||||
PlainText::class with PlainTextArgumentParser
|
||||
Image::class with ImageValueArgumentParser
|
||||
PlainText::class with PlainTextValueArgumentParser
|
||||
|
||||
Contact::class with ExistingContactArgumentParser
|
||||
User::class with ExistingUserArgumentParser
|
||||
Member::class with ExistingMemberArgumentParser
|
||||
Group::class with ExistingGroupArgumentParser
|
||||
Friend::class with ExistingFriendArgumentParser
|
||||
Bot::class with ExistingBotArgumentParser
|
||||
Contact::class with ExistingContactValueArgumentParser
|
||||
User::class with ExistingUserValueArgumentParser
|
||||
Member::class with ExistingMemberValueArgumentParser
|
||||
Group::class with ExistingGroupValueArgumentParser
|
||||
Friend::class with ExistingFriendValueArgumentParser
|
||||
Bot::class with ExistingBotValueArgumentParser
|
||||
|
||||
PermissionId::class with PermissionIdArgumentParser
|
||||
PermitteeId::class with PermitteeIdArgumentParser
|
||||
PermissionId::class with PermissionIdValueArgumentParser
|
||||
PermitteeId::class with PermitteeIdValueArgumentParser
|
||||
|
||||
MessageContent::class with RawContentArgumentParser
|
||||
MessageContent::class with RawContentValueArgumentParser
|
||||
})
|
||||
}
|
||||
|
||||
@ -103,7 +103,7 @@ public interface CommandArgumentContext {
|
||||
*/
|
||||
public interface CommandArgumentContextAware {
|
||||
/**
|
||||
* [CommandArgumentParser] 的集合
|
||||
* [CommandValueArgumentParser] 的集合
|
||||
*/
|
||||
public val context: CommandArgumentContext
|
||||
}
|
||||
@ -117,7 +117,7 @@ public operator fun CommandArgumentContext.plus(replacer: CommandArgumentContext
|
||||
if (replacer == EmptyCommandArgumentContext) return this
|
||||
if (this == EmptyCommandArgumentContext) return replacer
|
||||
return object : CommandArgumentContext {
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>? =
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandValueArgumentParser<T>? =
|
||||
replacer[klass] ?: this@plus[klass]
|
||||
|
||||
override fun toList(): List<ParserPair<*>> = replacer.toList() + this@plus.toList()
|
||||
@ -132,8 +132,8 @@ public operator fun CommandArgumentContext.plus(replacer: List<ParserPair<*>>):
|
||||
if (this == EmptyCommandArgumentContext) return SimpleCommandArgumentContext(replacer)
|
||||
return object : CommandArgumentContext {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>? =
|
||||
replacer.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandArgumentParser<T>?
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandValueArgumentParser<T>? =
|
||||
replacer.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandValueArgumentParser<T>?
|
||||
?: this@plus[klass]
|
||||
|
||||
override fun toList(): List<ParserPair<*>> = replacer.toList() + this@plus.toList()
|
||||
@ -149,9 +149,9 @@ public operator fun CommandArgumentContext.plus(replacer: List<ParserPair<*>>):
|
||||
public class SimpleCommandArgumentContext(
|
||||
public val list: List<ParserPair<*>>,
|
||||
) : CommandArgumentContext {
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>? =
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandValueArgumentParser<T>? =
|
||||
(this.list.firstOrNull { klass == it.klass }?.parser
|
||||
?: this.list.firstOrNull { klass.isSubclassOf(it.klass) }?.parser) as CommandArgumentParser<T>?
|
||||
?: this.list.firstOrNull { klass.isSubclassOf(it.klass) }?.parser) as CommandValueArgumentParser<T>?
|
||||
|
||||
override fun toList(): List<ParserPair<*>> = list
|
||||
}
|
||||
@ -203,14 +203,14 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
|
||||
* 添加一个指令解析器.
|
||||
*/
|
||||
@JvmName("add")
|
||||
public infix fun <T : Any> Class<T>.with(parser: CommandArgumentParser<T>): CommandArgumentContextBuilder =
|
||||
public infix fun <T : Any> Class<T>.with(parser: CommandValueArgumentParser<T>): CommandArgumentContextBuilder =
|
||||
this.kotlin with parser
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
*/
|
||||
@JvmName("add")
|
||||
public inline infix fun <T : Any> KClass<T>.with(parser: CommandArgumentParser<T>): CommandArgumentContextBuilder {
|
||||
public inline infix fun <T : Any> KClass<T>.with(parser: CommandValueArgumentParser<T>): CommandArgumentContextBuilder {
|
||||
add(ParserPair(this, parser))
|
||||
return this@CommandArgumentContextBuilder
|
||||
}
|
||||
@ -221,9 +221,9 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
|
||||
@JvmSynthetic
|
||||
@LowPriorityInOverloadResolution
|
||||
public inline infix fun <T : Any> KClass<T>.with(
|
||||
crossinline parser: CommandArgumentParser<T>.(s: String, sender: CommandSender) -> T,
|
||||
crossinline parser: CommandValueArgumentParser<T>.(s: String, sender: CommandSender) -> T,
|
||||
): CommandArgumentContextBuilder {
|
||||
add(ParserPair(this, object : CommandArgumentParser<T> {
|
||||
add(ParserPair(this, object : CommandValueArgumentParser<T> {
|
||||
override fun parse(raw: String, sender: CommandSender): T = parser(raw, sender)
|
||||
}))
|
||||
return this@CommandArgumentContextBuilder
|
||||
@ -234,16 +234,16 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
|
||||
*/
|
||||
@JvmSynthetic
|
||||
public inline infix fun <T : Any> KClass<T>.with(
|
||||
crossinline parser: CommandArgumentParser<T>.(s: String) -> T,
|
||||
crossinline parser: CommandValueArgumentParser<T>.(s: String) -> T,
|
||||
): CommandArgumentContextBuilder {
|
||||
add(ParserPair(this, object : CommandArgumentParser<T> {
|
||||
add(ParserPair(this, object : CommandValueArgumentParser<T> {
|
||||
override fun parse(raw: String, sender: CommandSender): T = parser(raw)
|
||||
}))
|
||||
return this@CommandArgumentContextBuilder
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
public inline fun <reified T : Any> add(parser: CommandArgumentParser<T>): CommandArgumentContextBuilder {
|
||||
public inline fun <reified T : Any> add(parser: CommandValueArgumentParser<T>): CommandArgumentContextBuilder {
|
||||
add(ParserPair(T::class, parser))
|
||||
return this@CommandArgumentContextBuilder
|
||||
}
|
||||
@ -254,8 +254,8 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
|
||||
@ConsoleExperimentalApi
|
||||
@JvmSynthetic
|
||||
public inline infix fun <reified T : Any> add(
|
||||
crossinline parser: CommandArgumentParser<*>.(s: String) -> T,
|
||||
): CommandArgumentContextBuilder = T::class with object : CommandArgumentParser<T> {
|
||||
crossinline parser: CommandValueArgumentParser<*>.(s: String) -> T,
|
||||
): CommandArgumentContextBuilder = T::class with object : CommandValueArgumentParser<T> {
|
||||
override fun parse(raw: String, sender: CommandSender): T = parser(raw)
|
||||
}
|
||||
|
||||
@ -266,8 +266,8 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
|
||||
@JvmSynthetic
|
||||
@LowPriorityInOverloadResolution
|
||||
public inline infix fun <reified T : Any> add(
|
||||
crossinline parser: CommandArgumentParser<*>.(s: String, sender: CommandSender) -> T,
|
||||
): CommandArgumentContextBuilder = T::class with object : CommandArgumentParser<T> {
|
||||
crossinline parser: CommandValueArgumentParser<*>.(s: String, sender: CommandSender) -> T,
|
||||
): CommandArgumentContextBuilder = T::class with object : CommandValueArgumentParser<T> {
|
||||
override fun parse(raw: String, sender: CommandSender): T = parser(raw, sender)
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ import net.mamoe.mirai.message.data.*
|
||||
/**
|
||||
* 使用 [String.toInt] 解析
|
||||
*/
|
||||
public object IntArgumentParser : InternalCommandArgumentParserExtensions<Int> {
|
||||
public object IntValueArgumentParser : InternalCommandValueArgumentParserExtensions<Int> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Int =
|
||||
raw.toIntOrNull() ?: illegalArgument("无法解析 $raw 为整数")
|
||||
}
|
||||
@ -33,7 +33,7 @@ public object IntArgumentParser : InternalCommandArgumentParserExtensions<Int> {
|
||||
/**
|
||||
* 使用 [String.toLong] 解析
|
||||
*/
|
||||
public object LongArgumentParser : InternalCommandArgumentParserExtensions<Long> {
|
||||
public object LongValueArgumentParser : InternalCommandValueArgumentParserExtensions<Long> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Long =
|
||||
raw.toLongOrNull() ?: illegalArgument("无法解析 $raw 为长整数")
|
||||
}
|
||||
@ -41,7 +41,7 @@ public object LongArgumentParser : InternalCommandArgumentParserExtensions<Long>
|
||||
/**
|
||||
* 使用 [String.toShort] 解析
|
||||
*/
|
||||
public object ShortArgumentParser : InternalCommandArgumentParserExtensions<Short> {
|
||||
public object ShortValueArgumentParser : InternalCommandValueArgumentParserExtensions<Short> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Short =
|
||||
raw.toShortOrNull() ?: illegalArgument("无法解析 $raw 为短整数")
|
||||
}
|
||||
@ -49,7 +49,7 @@ public object ShortArgumentParser : InternalCommandArgumentParserExtensions<Shor
|
||||
/**
|
||||
* 使用 [String.toByte] 解析
|
||||
*/
|
||||
public object ByteArgumentParser : InternalCommandArgumentParserExtensions<Byte> {
|
||||
public object ByteValueArgumentParser : InternalCommandValueArgumentParserExtensions<Byte> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Byte =
|
||||
raw.toByteOrNull() ?: illegalArgument("无法解析 $raw 为字节")
|
||||
}
|
||||
@ -57,7 +57,7 @@ public object ByteArgumentParser : InternalCommandArgumentParserExtensions<Byte>
|
||||
/**
|
||||
* 使用 [String.toDouble] 解析
|
||||
*/
|
||||
public object DoubleArgumentParser : InternalCommandArgumentParserExtensions<Double> {
|
||||
public object DoubleValueArgumentParser : InternalCommandValueArgumentParserExtensions<Double> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Double =
|
||||
raw.toDoubleOrNull() ?: illegalArgument("无法解析 $raw 为小数")
|
||||
}
|
||||
@ -65,7 +65,7 @@ public object DoubleArgumentParser : InternalCommandArgumentParserExtensions<Dou
|
||||
/**
|
||||
* 使用 [String.toFloat] 解析
|
||||
*/
|
||||
public object FloatArgumentParser : InternalCommandArgumentParserExtensions<Float> {
|
||||
public object FloatValueArgumentParser : InternalCommandValueArgumentParserExtensions<Float> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Float =
|
||||
raw.toFloatOrNull() ?: illegalArgument("无法解析 $raw 为小数")
|
||||
}
|
||||
@ -73,14 +73,14 @@ public object FloatArgumentParser : InternalCommandArgumentParserExtensions<Floa
|
||||
/**
|
||||
* 直接返回 [String], 或取用 [SingleMessage.contentToString]
|
||||
*/
|
||||
public object StringArgumentParser : InternalCommandArgumentParserExtensions<String> {
|
||||
public object StringValueArgumentParser : InternalCommandValueArgumentParserExtensions<String> {
|
||||
public override fun parse(raw: String, sender: CommandSender): String = raw
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 [String] 通过 [Image].
|
||||
*/
|
||||
public object ImageArgumentParser : InternalCommandArgumentParserExtensions<Image> {
|
||||
public object ImageValueArgumentParser : InternalCommandValueArgumentParserExtensions<Image> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Image {
|
||||
return kotlin.runCatching {
|
||||
Image(raw)
|
||||
@ -95,7 +95,7 @@ public object ImageArgumentParser : InternalCommandArgumentParserExtensions<Imag
|
||||
}
|
||||
}
|
||||
|
||||
public object PlainTextArgumentParser : InternalCommandArgumentParserExtensions<PlainText> {
|
||||
public object PlainTextValueArgumentParser : InternalCommandValueArgumentParserExtensions<PlainText> {
|
||||
public override fun parse(raw: String, sender: CommandSender): PlainText {
|
||||
return PlainText(raw)
|
||||
}
|
||||
@ -109,7 +109,7 @@ public object PlainTextArgumentParser : InternalCommandArgumentParserExtensions<
|
||||
/**
|
||||
* 当字符串内容为(不区分大小写) "true", "yes", "enabled"
|
||||
*/
|
||||
public object BooleanArgumentParser : InternalCommandArgumentParserExtensions<Boolean> {
|
||||
public object BooleanValueArgumentParser : InternalCommandValueArgumentParserExtensions<Boolean> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Boolean = raw.trim().let { str ->
|
||||
str.equals("true", ignoreCase = true)
|
||||
|| str.equals("yes", ignoreCase = true)
|
||||
@ -121,7 +121,7 @@ public object BooleanArgumentParser : InternalCommandArgumentParserExtensions<Bo
|
||||
/**
|
||||
* 根据 [Bot.id] 解析一个登录后的 [Bot]
|
||||
*/
|
||||
public object ExistingBotArgumentParser : InternalCommandArgumentParserExtensions<Bot> {
|
||||
public object ExistingBotValueArgumentParser : InternalCommandValueArgumentParserExtensions<Bot> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Bot =
|
||||
if (raw == "~") sender.inferBotOrFail()
|
||||
else raw.findBotOrFail()
|
||||
@ -136,7 +136,7 @@ public object ExistingBotArgumentParser : InternalCommandArgumentParserExtension
|
||||
/**
|
||||
* 解析任意一个存在的好友.
|
||||
*/
|
||||
public object ExistingFriendArgumentParser : InternalCommandArgumentParserExtensions<Friend> {
|
||||
public object ExistingFriendValueArgumentParser : InternalCommandValueArgumentParserExtensions<Friend> {
|
||||
private val syntax = """
|
||||
- `botId.friendId`
|
||||
- `botId.friendNick` (模糊搜索, 寻找最优匹配)
|
||||
@ -175,7 +175,7 @@ public object ExistingFriendArgumentParser : InternalCommandArgumentParserExtens
|
||||
/**
|
||||
* 解析任意一个存在的群.
|
||||
*/
|
||||
public object ExistingGroupArgumentParser : InternalCommandArgumentParserExtensions<Group> {
|
||||
public object ExistingGroupValueArgumentParser : InternalCommandValueArgumentParserExtensions<Group> {
|
||||
private val syntax = """
|
||||
- `botId.groupId`
|
||||
- `~` (指代指令调用人自己所在群. 仅群聊天环境下)
|
||||
@ -202,7 +202,7 @@ public object ExistingGroupArgumentParser : InternalCommandArgumentParserExtensi
|
||||
}
|
||||
}
|
||||
|
||||
public object ExistingUserArgumentParser : InternalCommandArgumentParserExtensions<User> {
|
||||
public object ExistingUserValueArgumentParser : InternalCommandValueArgumentParserExtensions<User> {
|
||||
private val syntax: String = """
|
||||
- `botId.groupId.memberId`
|
||||
- `botId.groupId.memberCard` (模糊搜索, 寻找最优匹配)
|
||||
@ -215,11 +215,11 @@ public object ExistingUserArgumentParser : InternalCommandArgumentParserExtensio
|
||||
""".trimIndent()
|
||||
|
||||
override fun parse(raw: String, sender: CommandSender): User {
|
||||
return parseImpl(sender, raw, ExistingMemberArgumentParser::parse, ExistingFriendArgumentParser::parse)
|
||||
return parseImpl(sender, raw, ExistingMemberValueArgumentParser::parse, ExistingFriendValueArgumentParser::parse)
|
||||
}
|
||||
|
||||
override fun parse(raw: MessageContent, sender: CommandSender): User {
|
||||
return parseImpl(sender, raw, ExistingMemberArgumentParser::parse, ExistingFriendArgumentParser::parse)
|
||||
return parseImpl(sender, raw, ExistingMemberValueArgumentParser::parse, ExistingFriendValueArgumentParser::parse)
|
||||
}
|
||||
|
||||
private fun <T> parseImpl(
|
||||
@ -246,7 +246,7 @@ public object ExistingUserArgumentParser : InternalCommandArgumentParserExtensio
|
||||
}
|
||||
|
||||
|
||||
public object ExistingContactArgumentParser : InternalCommandArgumentParserExtensions<Contact> {
|
||||
public object ExistingContactValueArgumentParser : InternalCommandValueArgumentParserExtensions<Contact> {
|
||||
private val syntax: String = """
|
||||
- `botId.groupId.memberId`
|
||||
- `botId.groupId.memberCard` (模糊搜索, 寻找最优匹配)
|
||||
@ -259,11 +259,11 @@ public object ExistingContactArgumentParser : InternalCommandArgumentParserExten
|
||||
""".trimIndent()
|
||||
|
||||
override fun parse(raw: String, sender: CommandSender): Contact {
|
||||
return parseImpl(sender, raw, ExistingUserArgumentParser::parse, ExistingGroupArgumentParser::parse)
|
||||
return parseImpl(sender, raw, ExistingUserValueArgumentParser::parse, ExistingGroupValueArgumentParser::parse)
|
||||
}
|
||||
|
||||
override fun parse(raw: MessageContent, sender: CommandSender): Contact {
|
||||
return parseImpl(sender, raw, ExistingUserArgumentParser::parse, ExistingGroupArgumentParser::parse)
|
||||
return parseImpl(sender, raw, ExistingUserValueArgumentParser::parse, ExistingGroupValueArgumentParser::parse)
|
||||
}
|
||||
|
||||
private fun <T> parseImpl(
|
||||
@ -286,7 +286,7 @@ public object ExistingContactArgumentParser : InternalCommandArgumentParserExten
|
||||
/**
|
||||
* 解析任意一个群成员.
|
||||
*/
|
||||
public object ExistingMemberArgumentParser : InternalCommandArgumentParserExtensions<Member> {
|
||||
public object ExistingMemberValueArgumentParser : InternalCommandValueArgumentParserExtensions<Member> {
|
||||
private val syntax: String = """
|
||||
- `botId.groupId.memberId`
|
||||
- `botId.groupId.memberCard` (模糊搜索, 寻找最优匹配)
|
||||
@ -333,7 +333,7 @@ public object ExistingMemberArgumentParser : InternalCommandArgumentParserExtens
|
||||
}
|
||||
}
|
||||
|
||||
public object PermissionIdArgumentParser : CommandArgumentParser<PermissionId> {
|
||||
public object PermissionIdValueArgumentParser : CommandValueArgumentParser<PermissionId> {
|
||||
override fun parse(raw: String, sender: CommandSender): PermissionId {
|
||||
return kotlin.runCatching { PermissionId.parseFromString(raw) }.getOrElse {
|
||||
illegalArgument("无法解析 $raw 为 PermissionId")
|
||||
@ -341,7 +341,7 @@ public object PermissionIdArgumentParser : CommandArgumentParser<PermissionId> {
|
||||
}
|
||||
}
|
||||
|
||||
public object PermitteeIdArgumentParser : CommandArgumentParser<PermitteeId> {
|
||||
public object PermitteeIdValueArgumentParser : CommandValueArgumentParser<PermitteeId> {
|
||||
override fun parse(raw: String, sender: CommandSender): PermitteeId {
|
||||
return if (raw == "~") sender.permitteeId
|
||||
else kotlin.runCatching { AbstractPermitteeId.parseFromString(raw) }.getOrElse {
|
||||
@ -351,19 +351,19 @@ public object PermitteeIdArgumentParser : CommandArgumentParser<PermitteeId> {
|
||||
|
||||
override fun parse(raw: MessageContent, sender: CommandSender): PermitteeId {
|
||||
if (raw is At) {
|
||||
return ExistingUserArgumentParser.parse(raw, sender).asCommandSender(false).permitteeId
|
||||
return ExistingUserValueArgumentParser.parse(raw, sender).asCommandSender(false).permitteeId
|
||||
}
|
||||
return super.parse(raw, sender)
|
||||
}
|
||||
}
|
||||
|
||||
/** 直接返回原始参数 [MessageContent] */
|
||||
public object RawContentArgumentParser : CommandArgumentParser<MessageContent> {
|
||||
public object RawContentValueArgumentParser : CommandValueArgumentParser<MessageContent> {
|
||||
override fun parse(raw: String, sender: CommandSender): MessageContent = PlainText(raw)
|
||||
override fun parse(raw: MessageContent, sender: CommandSender): MessageContent = raw
|
||||
}
|
||||
|
||||
internal interface InternalCommandArgumentParserExtensions<T : Any> : CommandArgumentParser<T> {
|
||||
internal interface InternalCommandValueArgumentParserExtensions<T : Any> : CommandValueArgumentParser<T> {
|
||||
fun String.parseToLongOrFail(): Long = toLongOrNull() ?: illegalArgument("无法解析 $this 为整数")
|
||||
|
||||
fun Long.findBotOrFail(): Bot = Bot.getInstanceOrNull(this) ?: illegalArgument("无法找到 Bot: $this")
|
||||
|
@ -16,8 +16,8 @@ package net.mamoe.mirai.console.command.descriptor
|
||||
*
|
||||
* [message] 将会发送给指令调用方.
|
||||
*
|
||||
* @see CommandArgumentParser
|
||||
* @see CommandArgumentParser.illegalArgument
|
||||
* @see CommandValueArgumentParser
|
||||
* @see CommandValueArgumentParser.illegalArgument
|
||||
*/
|
||||
public class CommandArgumentParserException : RuntimeException {
|
||||
public constructor() : super()
|
||||
|
@ -65,7 +65,7 @@ public sealed class CommandValueParameter<T> : ICommandParameter<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extended by [CommandArgumentParser]
|
||||
* Extended by [CommandValueArgumentParser]
|
||||
*/
|
||||
public abstract class Extended<T> : CommandValueParameter<T>()
|
||||
}
|
@ -32,27 +32,27 @@ import kotlin.contracts.contract
|
||||
* ```
|
||||
* suspend fun CommandSender.mute(target: Member, duration: Int)
|
||||
* ```
|
||||
* [CommandManager] 总是从 [SimpleCommand.context] 搜索一个 [T] 为 [Member] 的 [CommandArgumentParser], 并调用其 [CommandArgumentParser.parse]
|
||||
* [CommandManager] 总是从 [SimpleCommand.context] 搜索一个 [T] 为 [Member] 的 [CommandValueArgumentParser], 并调用其 [CommandValueArgumentParser.parse]
|
||||
*
|
||||
* ### 内建指令解析器
|
||||
* - 基础类型: [ByteArgumentParser], [ShortArgumentParser], [IntArgumentParser], [LongArgumentParser]
|
||||
* [FloatArgumentParser], [DoubleArgumentParser],
|
||||
* [BooleanArgumentParser], [StringArgumentParser]
|
||||
* - 基础类型: [ByteValueArgumentParser], [ShortValueArgumentParser], [IntValueArgumentParser], [LongValueArgumentParser]
|
||||
* [FloatValueArgumentParser], [DoubleValueArgumentParser],
|
||||
* [BooleanValueArgumentParser], [StringValueArgumentParser]
|
||||
*
|
||||
* - [Bot]: [ExistingBotArgumentParser]
|
||||
* - [Friend]: [ExistingFriendArgumentParser]
|
||||
* - [Group]: [ExistingGroupArgumentParser]
|
||||
* - [Member]: [ExistingMemberArgumentParser]
|
||||
* - [User]: [ExistingUserArgumentParser]
|
||||
* - [Contact]: [ExistingContactArgumentParser]
|
||||
* - [Bot]: [ExistingBotValueArgumentParser]
|
||||
* - [Friend]: [ExistingFriendValueArgumentParser]
|
||||
* - [Group]: [ExistingGroupValueArgumentParser]
|
||||
* - [Member]: [ExistingMemberValueArgumentParser]
|
||||
* - [User]: [ExistingUserValueArgumentParser]
|
||||
* - [Contact]: [ExistingContactValueArgumentParser]
|
||||
*
|
||||
*
|
||||
* @see SimpleCommand 简单指令
|
||||
* @see CompositeCommand 复合指令
|
||||
*
|
||||
* @see buildCommandArgumentContext 指令参数环境, 即 [CommandArgumentParser] 的集合
|
||||
* @see buildCommandArgumentContext 指令参数环境, 即 [CommandValueArgumentParser] 的集合
|
||||
*/
|
||||
public interface CommandArgumentParser<out T : Any> {
|
||||
public interface CommandValueArgumentParser<out T : Any> {
|
||||
/**
|
||||
* 解析一个字符串为 [T] 类型参数
|
||||
*
|
||||
@ -84,14 +84,14 @@ public interface CommandArgumentParser<out T : Any> {
|
||||
/**
|
||||
* 使用原 [this] 解析, 成功后使用 [mapper] 映射为另一个类型.
|
||||
*/
|
||||
public fun <T : Any, R : Any> CommandArgumentParser<T>.map(
|
||||
mapper: CommandArgumentParser<R>.(T) -> R
|
||||
): CommandArgumentParser<R> = MappingCommandArgumentParser(this, mapper)
|
||||
public fun <T : Any, R : Any> CommandValueArgumentParser<T>.map(
|
||||
mapper: CommandValueArgumentParser<R>.(T) -> R,
|
||||
): CommandValueArgumentParser<R> = MappingCommandValueArgumentParser(this, mapper)
|
||||
|
||||
private class MappingCommandArgumentParser<T : Any, R : Any>(
|
||||
private val original: CommandArgumentParser<T>,
|
||||
private val mapper: CommandArgumentParser<R>.(T) -> R
|
||||
) : CommandArgumentParser<R> {
|
||||
private class MappingCommandValueArgumentParser<T : Any, R : Any>(
|
||||
private val original: CommandValueArgumentParser<T>,
|
||||
private val mapper: CommandValueArgumentParser<R>.(T) -> R,
|
||||
) : CommandValueArgumentParser<R> {
|
||||
override fun parse(raw: String, sender: CommandSender): R = mapper(original.parse(raw, sender))
|
||||
override fun parse(raw: MessageContent, sender: CommandSender): R = mapper(original.parse(raw, sender))
|
||||
}
|
||||
@ -103,7 +103,7 @@ private class MappingCommandArgumentParser<T : Any, R : Any>(
|
||||
*/
|
||||
@JvmSynthetic
|
||||
@Throws(IllegalArgumentException::class)
|
||||
public fun <T : Any> CommandArgumentParser<T>.parse(raw: Any, sender: CommandSender): T {
|
||||
public fun <T : Any> CommandValueArgumentParser<T>.parse(raw: Any, sender: CommandSender): T {
|
||||
contract {
|
||||
returns() implies (raw is String || raw is SingleMessage)
|
||||
}
|
||||
@ -123,7 +123,7 @@ public fun <T : Any> CommandArgumentParser<T>.parse(raw: Any, sender: CommandSen
|
||||
@Suppress("unused")
|
||||
@JvmSynthetic
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
public inline fun CommandArgumentParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing {
|
||||
public inline fun CommandValueArgumentParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing {
|
||||
throw CommandArgumentParserException(message, cause)
|
||||
}
|
||||
|
||||
@ -134,9 +134,9 @@ public inline fun CommandArgumentParser<*>.illegalArgument(message: String, caus
|
||||
*/
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
@JvmSynthetic
|
||||
public inline fun CommandArgumentParser<*>.checkArgument(
|
||||
public inline fun CommandValueArgumentParser<*>.checkArgument(
|
||||
condition: Boolean,
|
||||
crossinline message: () -> String = { "Check failed." }
|
||||
crossinline message: () -> String = { "Check failed." },
|
||||
) {
|
||||
contract {
|
||||
returns() implies condition
|
@ -16,6 +16,9 @@ import kotlin.reflect.typeOf
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
public interface TypeVariant<out OutType> {
|
||||
/**
|
||||
* The reified type of [OutType]
|
||||
*/
|
||||
public val outType: KType
|
||||
|
||||
public fun mapValue(valueParameter: MessageContent): OutType
|
||||
@ -33,8 +36,8 @@ public interface TypeVariant<out OutType> {
|
||||
}
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
public object StringTypeVariant : TypeVariant<RawCommandArgument> {
|
||||
public object MessageContentTypeVariant : TypeVariant<MessageContent> {
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
override val outType: KType = typeOf<String>()
|
||||
override fun mapValue(valueParameter: RawCommandArgument): RawCommandArgument = valueParameter
|
||||
override fun mapValue(valueParameter: MessageContent): MessageContent = valueParameter
|
||||
}
|
||||
|
@ -10,8 +10,8 @@
|
||||
package net.mamoe.mirai.console.command.parse
|
||||
|
||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.command.descriptor.MessageContentTypeVariant
|
||||
import net.mamoe.mirai.console.command.descriptor.NoValueArgumentMappingException
|
||||
import net.mamoe.mirai.console.command.descriptor.StringTypeVariant
|
||||
import net.mamoe.mirai.console.command.descriptor.TypeVariant
|
||||
import net.mamoe.mirai.message.data.MessageContent
|
||||
import kotlin.reflect.full.isSubtypeOf
|
||||
@ -23,20 +23,29 @@ import kotlin.reflect.typeOf
|
||||
*/
|
||||
public typealias RawCommandArgument = MessageContent
|
||||
|
||||
/**
|
||||
* @see CommandValueArgument
|
||||
*/
|
||||
@ExperimentalCommandDescriptors
|
||||
public interface CommandArgument
|
||||
|
||||
/**
|
||||
* @see InvariantCommandValueArgument
|
||||
*/
|
||||
@ExperimentalCommandDescriptors
|
||||
public interface CommandValueArgument : CommandArgument {
|
||||
public val value: RawCommandArgument
|
||||
public val typeVariants: List<TypeVariant<*>>
|
||||
}
|
||||
|
||||
/**
|
||||
* The [CommandValueArgument] that doesn't vary in type (remaining [MessageContent]).
|
||||
*/
|
||||
@ExperimentalCommandDescriptors
|
||||
public data class InvariantCommandValueArgument(
|
||||
public override val value: RawCommandArgument,
|
||||
) : CommandValueArgument {
|
||||
override val typeVariants: List<TypeVariant<*>> = listOf(StringTypeVariant)
|
||||
override val typeVariants: List<TypeVariant<*>> = listOf(MessageContentTypeVariant)
|
||||
}
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
|
@ -12,7 +12,7 @@
|
||||
package net.mamoe.mirai.console.internal.command
|
||||
|
||||
import net.mamoe.mirai.console.command.CompositeCommand
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandArgumentParser
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandValueArgumentParser
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KParameter
|
||||
|
||||
@ -37,12 +37,12 @@ internal data class CommandParameter<T : Any>(
|
||||
*/
|
||||
val name: String,
|
||||
/**
|
||||
* 参数类型. 将从 [CompositeCommand.context] 中寻找 [CommandArgumentParser] 解析.
|
||||
* 参数类型. 将从 [CompositeCommand.context] 中寻找 [CommandValueArgumentParser] 解析.
|
||||
*/
|
||||
val type: KClass<T>, // exact type
|
||||
val parameter: KParameter, // source parameter
|
||||
) {
|
||||
constructor(name: String, type: KClass<T>, parameter: KParameter, parser: CommandArgumentParser<T>) : this(
|
||||
constructor(name: String, type: KClass<T>, parameter: KParameter, parser: CommandValueArgumentParser<T>) : this(
|
||||
name, type, parameter
|
||||
) {
|
||||
this._overrideParser = parser
|
||||
@ -50,14 +50,14 @@ internal data class CommandParameter<T : Any>(
|
||||
|
||||
@Suppress("PropertyName")
|
||||
@JvmField
|
||||
internal var _overrideParser: CommandArgumentParser<T>? = null
|
||||
internal var _overrideParser: CommandValueArgumentParser<T>? = null
|
||||
|
||||
|
||||
/**
|
||||
* 覆盖的 [CommandArgumentParser].
|
||||
* 覆盖的 [CommandValueArgumentParser].
|
||||
*
|
||||
* 如果非 `null`, 将不会从 [CommandArgumentContext] 寻找 [CommandArgumentParser]
|
||||
* 如果非 `null`, 将不会从 [CommandArgumentContext] 寻找 [CommandValueArgumentParser]
|
||||
*/
|
||||
val overrideParser: CommandArgumentParser<T>? get() = _overrideParser
|
||||
val overrideParser: CommandValueArgumentParser<T>? get() = _overrideParser
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.registeredCommands
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregister
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregisterAllCommands
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandArgumentParser
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandValueArgumentParser
|
||||
import net.mamoe.mirai.console.command.descriptor.buildCommandArgumentContext
|
||||
import net.mamoe.mirai.console.initTestEnvironment
|
||||
import net.mamoe.mirai.console.internal.command.CommandManagerImpl
|
||||
@ -191,7 +191,7 @@ internal class TestCommand {
|
||||
ConsoleCommandOwner,
|
||||
"test22",
|
||||
overrideContext = buildCommandArgumentContext {
|
||||
add(object : CommandArgumentParser<MyClass> {
|
||||
add(object : CommandValueArgumentParser<MyClass> {
|
||||
override fun parse(raw: String, sender: CommandSender): MyClass {
|
||||
return MyClass(raw.toInt())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user