Feature: ExtraKey in NeoLang
This commit is contained in:
parent
867736afe5
commit
68adad5238
@ -1,10 +1,14 @@
|
|||||||
extra-key: {
|
extra-key: {
|
||||||
|
version: 10
|
||||||
|
with-default: true
|
||||||
|
|
||||||
program: [ "vim", "vi" ]
|
program: [ "vim", "vi" ]
|
||||||
|
|
||||||
key: [
|
key: [
|
||||||
"hello",
|
|
||||||
{
|
{
|
||||||
display: "Ctrl"
|
display: "Ctrl"
|
||||||
code: "<CTRL>"
|
code: "<CTRL>"
|
||||||
|
with-enter: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
display: "Esc"
|
display: "Esc"
|
||||||
|
@ -77,7 +77,6 @@ open class NeoColorScheme {
|
|||||||
|
|
||||||
fun loadConfigure(file: File): Boolean {
|
fun loadConfigure(file: File): Boolean {
|
||||||
val loaderService = ServiceManager.getService<ConfigureService>()
|
val loaderService = ServiceManager.getService<ConfigureService>()
|
||||||
|
|
||||||
val configure = loaderService.newLoader(file).loadConfigure()
|
val configure = loaderService.newLoader(file).loadConfigure()
|
||||||
|
|
||||||
if (configure == null) {
|
if (configure == null) {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package io.neoterm.customize.config.loader
|
package io.neoterm.customize.config.loader
|
||||||
|
|
||||||
import io.neoterm.customize.eks.ExtraKeyConfigParser
|
import io.neolang.runtime.type.NeoLangValue
|
||||||
import io.neoterm.customize.eks.NeoExtraKey
|
|
||||||
import io.neolang.visitor.ConfigVisitor
|
import io.neolang.visitor.ConfigVisitor
|
||||||
|
import io.neoterm.customize.eks.NeoExtraKey
|
||||||
import io.neoterm.frontend.config.NeoConfigureFile
|
import io.neoterm.frontend.config.NeoConfigureFile
|
||||||
import io.neoterm.view.eks.button.TextButton
|
import io.neoterm.view.eks.button.TextButton
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileReader
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
@ -15,7 +16,46 @@ class OldExtraKeysConfigureFile(configureFile: File) : NeoConfigureFile(configur
|
|||||||
override var configVisitor: ConfigVisitor? = null
|
override var configVisitor: ConfigVisitor? = null
|
||||||
|
|
||||||
override fun parseConfigure(): Boolean {
|
override fun parseConfigure(): Boolean {
|
||||||
return super.parseConfigure()
|
try {
|
||||||
|
val config = parseOldConfig(BufferedReader(FileReader(configureFile)))
|
||||||
|
return generateVisitor(config)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateVisitor(config: NeoExtraKey): Boolean {
|
||||||
|
configVisitor = ConfigVisitor()
|
||||||
|
val visitor = configVisitor!!
|
||||||
|
visitor.onStart()
|
||||||
|
visitor.onEnterContext(NeoExtraKey.EKS_META_CONTEXT_NAME)
|
||||||
|
visitor.getCurrentContext()
|
||||||
|
.defineAttribute(NeoExtraKey.EKS_META_VERSION, NeoLangValue(config.version))
|
||||||
|
.defineAttribute(NeoExtraKey.EKS_META_WITH_DEFAULT, NeoLangValue(config.withDefaultKeys))
|
||||||
|
|
||||||
|
// program
|
||||||
|
visitor.onEnterContext(NeoExtraKey.EKS_META_PROGRAM)
|
||||||
|
config.programNames.forEachIndexed { index, program ->
|
||||||
|
visitor.getCurrentContext().defineAttribute(index.toString(), NeoLangValue(program))
|
||||||
|
}
|
||||||
|
visitor.onExitContext()
|
||||||
|
|
||||||
|
// key
|
||||||
|
visitor.onEnterContext(NeoExtraKey.EKS_META_KEY)
|
||||||
|
config.shortcutKeys.forEachIndexed { index, button ->
|
||||||
|
if (button is TextButton) {
|
||||||
|
visitor.onEnterContext(index.toString())
|
||||||
|
visitor.getCurrentContext()
|
||||||
|
.defineAttribute(NeoExtraKey.EKS_META_WITH_ENTER, NeoLangValue(button.withEnter))
|
||||||
|
.defineAttribute(NeoExtraKey.EKS_META_DISPLAY, NeoLangValue(button.buttonText!!))
|
||||||
|
.defineAttribute(NeoExtraKey.EKS_META_CODE, NeoLangValue(button.buttonText!!))
|
||||||
|
visitor.onExitContext()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visitor.onExitContext()
|
||||||
|
|
||||||
|
visitor.onFinish()
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseOldConfig(source: BufferedReader): NeoExtraKey {
|
private fun parseOldConfig(source: BufferedReader): NeoExtraKey {
|
||||||
@ -29,13 +69,13 @@ class OldExtraKeysConfigureFile(configureFile: File) : NeoConfigureFile(configur
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.startsWith("version")) {
|
if (line.startsWith(NeoExtraKey.EKS_META_VERSION)) {
|
||||||
parseHeader(line, config)
|
parseHeader(line, config)
|
||||||
} else if (line.startsWith("program")) {
|
} else if (line.startsWith(NeoExtraKey.EKS_META_PROGRAM)) {
|
||||||
parseProgram(line, config)
|
parseProgram(line, config)
|
||||||
} else if (line.startsWith("define")) {
|
} else if (line.startsWith("define")) {
|
||||||
parseKeyDefine(line, config)
|
parseKeyDefine(line, config)
|
||||||
} else if (line.startsWith("with-default")) {
|
} else if (line.startsWith(NeoExtraKey.EKS_META_WITH_DEFAULT)) {
|
||||||
parseWithDefault(line, config)
|
parseWithDefault(line, config)
|
||||||
}
|
}
|
||||||
line = source.readLine()
|
line = source.readLine()
|
||||||
@ -51,7 +91,7 @@ class OldExtraKeysConfigureFile(configureFile: File) : NeoConfigureFile(configur
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun parseWithDefault(line: String, config: NeoExtraKey) {
|
private fun parseWithDefault(line: String, config: NeoExtraKey) {
|
||||||
val value = line.substring("with-default".length).trim().trimEnd()
|
val value = line.substring(NeoExtraKey.EKS_META_WITH_DEFAULT.length).trim().trimEnd()
|
||||||
config.withDefaultKeys = value == "true"
|
config.withDefaultKeys = value == "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +109,7 @@ class OldExtraKeysConfigureFile(configureFile: File) : NeoConfigureFile(configur
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun parseProgram(line: String, config: NeoExtraKey) {
|
private fun parseProgram(line: String, config: NeoExtraKey) {
|
||||||
val programNames = line.substring("program".length).trim().trimEnd()
|
val programNames = line.substring(NeoExtraKey.EKS_META_PROGRAM.length).trim().trimEnd()
|
||||||
if (programNames.isEmpty()) {
|
if (programNames.isEmpty()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -81,17 +121,13 @@ class OldExtraKeysConfigureFile(configureFile: File) : NeoConfigureFile(configur
|
|||||||
|
|
||||||
private fun parseHeader(line: String, config: NeoExtraKey) {
|
private fun parseHeader(line: String, config: NeoExtraKey) {
|
||||||
val version: Int
|
val version: Int
|
||||||
val versionString = line.substring("version".length).trim().trimEnd()
|
val versionString = line.substring(NeoExtraKey.EKS_META_VERSION.length).trim().trimEnd()
|
||||||
try {
|
try {
|
||||||
version = Integer.parseInt(versionString)
|
version = Integer.parseInt(versionString)
|
||||||
} catch (e: NumberFormatException) {
|
} catch (e: NumberFormatException) {
|
||||||
throw RuntimeException("Bad version '$versionString'")
|
throw RuntimeException("Bad version '$versionString'")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version > ExtraKeyConfigParser.PARSER_VERSION) {
|
|
||||||
throw RuntimeException("Required version: $version, please upgrade your app")
|
|
||||||
}
|
|
||||||
|
|
||||||
config.version = version
|
config.version = version
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,51 +0,0 @@
|
|||||||
package io.neoterm.customize.eks
|
|
||||||
|
|
||||||
import io.neoterm.frontend.logging.NLog
|
|
||||||
import io.neoterm.frontend.preference.NeoTermPath
|
|
||||||
import io.neoterm.view.eks.ExtraKeysView
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
object ExtraKeyConfigLoader {
|
|
||||||
class ConfiguredExtraKey(val config: NeoExtraKey) : IExtraKey {
|
|
||||||
override fun applyShortcutKeys(extraKeysView: ExtraKeysView) {
|
|
||||||
if (config.withDefaultKeys) {
|
|
||||||
extraKeysView.loadDefaultUserKeys()
|
|
||||||
}
|
|
||||||
for (button in config.shortcutKeys) {
|
|
||||||
extraKeysView.addUserKey(button)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadDefinedConfigs(extraKeysManager: ExtraKeysService) {
|
|
||||||
val configDir = File(NeoTermPath.EKS_PATH)
|
|
||||||
configDir.mkdirs()
|
|
||||||
|
|
||||||
val parser = ExtraKeyConfigParser()
|
|
||||||
for (file in configDir.listFiles()) {
|
|
||||||
try {
|
|
||||||
parser.setInput(file)
|
|
||||||
val config = parser.parse()
|
|
||||||
|
|
||||||
// "default" is a reserved program used for default extra keys
|
|
||||||
// see ExtraKeysView.loadDefaultUserKeys()
|
|
||||||
if (config.programNames.contains("default")) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
registerConfig(extraKeysManager, config)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
NLog.e("NeoTerm-EKS", "Load $file failed: " + e.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun registerConfig(extraKeysManager: ExtraKeysService, config: NeoExtraKey) {
|
|
||||||
val shortcutKey = ConfiguredExtraKey(config)
|
|
||||||
for (programName in config.programNames) {
|
|
||||||
extraKeysManager.registerShortcutKeys(programName, shortcutKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
package io.neoterm.customize.eks
|
|
||||||
|
|
||||||
import io.neoterm.view.eks.button.TextButton
|
|
||||||
import java.io.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
class ExtraKeyConfigParser {
|
|
||||||
companion object {
|
|
||||||
const val PARSER_VERSION = 5
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var source: BufferedReader
|
|
||||||
|
|
||||||
fun setInput(file: File) {
|
|
||||||
source = BufferedReader(FileReader(file))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setInput(bufferedReader: BufferedReader) {
|
|
||||||
source = bufferedReader
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setInput(inputStream: BufferedInputStream) {
|
|
||||||
source = BufferedReader(InputStreamReader(inputStream))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parse(): NeoExtraKey {
|
|
||||||
val config = NeoExtraKey()
|
|
||||||
var line: String? = source.readLine()
|
|
||||||
|
|
||||||
while (line != null) {
|
|
||||||
line = line.trim().trimEnd()
|
|
||||||
if (line.isEmpty() || line.startsWith("#")) {
|
|
||||||
line = source.readLine()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.startsWith("version")) {
|
|
||||||
parseHeader(line, config)
|
|
||||||
} else if (line.startsWith("program")) {
|
|
||||||
parseProgram(line, config)
|
|
||||||
} else if (line.startsWith("define")) {
|
|
||||||
parseKeyDefine(line, config)
|
|
||||||
} else if (line.startsWith("with-default")) {
|
|
||||||
parseWithDefault(line, config)
|
|
||||||
}
|
|
||||||
line = source.readLine()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.version < 0) {
|
|
||||||
throw RuntimeException("Not a valid shortcut config file")
|
|
||||||
}
|
|
||||||
if (config.programNames.size == 0) {
|
|
||||||
throw RuntimeException("At least one program name should be given")
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseWithDefault(line: String, config: NeoExtraKey) {
|
|
||||||
val value = line.substring("with-default".length).trim().trimEnd()
|
|
||||||
config.withDefaultKeys = value == "true"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseKeyDefine(line: String, config: NeoExtraKey) {
|
|
||||||
val keyDefine = line.substring("define".length).trim().trimEnd()
|
|
||||||
val keyValues = keyDefine.split(" ")
|
|
||||||
if (keyValues.size < 2) {
|
|
||||||
throw RuntimeException("Bad define")
|
|
||||||
}
|
|
||||||
|
|
||||||
val buttonText = keyValues[0]
|
|
||||||
val withEnter = keyValues[1] == "true"
|
|
||||||
|
|
||||||
config.shortcutKeys.add(TextButton(buttonText, withEnter))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseProgram(line: String, config: NeoExtraKey) {
|
|
||||||
val programNames = line.substring("program".length).trim().trimEnd()
|
|
||||||
if (programNames.isEmpty()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (name in programNames.split(" ")) {
|
|
||||||
config.programNames.add(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseHeader(line: String, config: NeoExtraKey) {
|
|
||||||
val version: Int
|
|
||||||
val versionString = line.substring("version".length).trim().trimEnd()
|
|
||||||
try {
|
|
||||||
version = Integer.parseInt(versionString)
|
|
||||||
} catch (e: NumberFormatException) {
|
|
||||||
throw RuntimeException("Bad version '$versionString'")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (version > ExtraKeyConfigParser.PARSER_VERSION) {
|
|
||||||
throw RuntimeException("Required version: $version, please upgrade your app")
|
|
||||||
}
|
|
||||||
|
|
||||||
config.version = version
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,9 @@
|
|||||||
package io.neoterm.customize.eks
|
package io.neoterm.customize.eks
|
||||||
|
|
||||||
import io.neoterm.customize.eks.builtin.BuiltinExtraKeys
|
import io.neoterm.frontend.preference.NeoTermPath
|
||||||
import io.neoterm.frontend.service.NeoService
|
import io.neoterm.frontend.service.NeoService
|
||||||
import io.neoterm.view.eks.ExtraKeysView
|
import io.neoterm.view.eks.ExtraKeysView
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
@ -47,7 +48,13 @@ class ExtraKeysService : NeoService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkForFiles() {
|
private fun checkForFiles() {
|
||||||
BuiltinExtraKeys.registerAll()
|
// TODO: Builtin keys
|
||||||
ExtraKeyConfigLoader.loadDefinedConfigs(this)
|
loadConfigure()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadConfigure() {
|
||||||
|
val configDir = File(NeoTermPath.EKS_PATH)
|
||||||
|
configDir.mkdirs()
|
||||||
|
// TODO: Load configure.
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,90 @@
|
|||||||
package io.neoterm.customize.eks
|
package io.neoterm.customize.eks
|
||||||
|
|
||||||
|
import io.neolang.visitor.ConfigVisitor
|
||||||
|
import io.neoterm.customize.config.ConfigureService
|
||||||
|
import io.neoterm.frontend.logging.NLog
|
||||||
|
import io.neoterm.frontend.service.ServiceManager
|
||||||
import io.neoterm.view.eks.button.IExtraButton
|
import io.neoterm.view.eks.button.IExtraButton
|
||||||
|
import io.neoterm.view.eks.button.TextButton
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
*/
|
*/
|
||||||
class NeoExtraKey {
|
class NeoExtraKey {
|
||||||
var version: Int = -1
|
companion object {
|
||||||
|
const val EKS_META_CONTEXT_NAME = "extra-key"
|
||||||
|
|
||||||
|
const val EKS_META_PROGRAM = "program"
|
||||||
|
const val EKS_META_KEY = "key"
|
||||||
|
const val EKS_META_WITH_DEFAULT = "with-default"
|
||||||
|
const val EKS_META_WITH_ENTER = "with-enter"
|
||||||
|
const val EKS_META_DISPLAY = "display"
|
||||||
|
const val EKS_META_CODE = "code"
|
||||||
|
const val EKS_META_VERSION = "version"
|
||||||
|
|
||||||
|
val EKS_META_CONTEXT_PATH = arrayOf(EKS_META_CONTEXT_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
var version: Int = 0
|
||||||
val programNames: MutableList<String> = mutableListOf()
|
val programNames: MutableList<String> = mutableListOf()
|
||||||
val shortcutKeys: MutableList<IExtraButton> = mutableListOf()
|
val shortcutKeys: MutableList<IExtraButton> = mutableListOf()
|
||||||
var withDefaultKeys: Boolean = true
|
var withDefaultKeys: Boolean = true
|
||||||
|
|
||||||
|
fun loadConfigure(file: File): Boolean {
|
||||||
|
val loaderService = ServiceManager.getService<ConfigureService>()
|
||||||
|
val configure = loaderService.newLoader(file).loadConfigure()
|
||||||
|
|
||||||
|
if (configure == null) {
|
||||||
|
NLog.e("ExtraKey", "Failed to load extra key config: ${file.absolutePath}")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val visitor = configure.getVisitor()
|
||||||
|
|
||||||
|
// program
|
||||||
|
val programArray = visitor.getArray(EKS_META_CONTEXT_PATH, EKS_META_PROGRAM)
|
||||||
|
if (programArray.isEmpty()) {
|
||||||
|
NLog.e("ExtraKey", "Failed to load extra key config: ${file.absolutePath}: Extra Key must have programs attribute")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
programArray.forEach {
|
||||||
|
if (!it.isBlock()) {
|
||||||
|
programNames.add(it.eval().asString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// key
|
||||||
|
val keyArray = visitor.getArray(EKS_META_CONTEXT_PATH, EKS_META_KEY)
|
||||||
|
keyArray.takeWhile { it.isBlock() }
|
||||||
|
.forEach {
|
||||||
|
val display = it.eval(EKS_META_DISPLAY)
|
||||||
|
val code = it.eval(EKS_META_CODE)
|
||||||
|
if (!code.isValid()) {
|
||||||
|
NLog.e("ExtraKey", "Failed to load extra key config: ${file.absolutePath}: Key must have a code")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val codeText = code.asString()
|
||||||
|
val displayText = if (display.isValid()) display.asString() else codeText
|
||||||
|
val withEnter = it.eval(EKS_META_WITH_ENTER)
|
||||||
|
val withEnterBoolean = withEnter.asString() == "true"
|
||||||
|
|
||||||
|
val button = TextButton(codeText, withEnterBoolean)
|
||||||
|
button.displayText = displayText
|
||||||
|
shortcutKeys.add(button)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must cal toDouble() before toInt()
|
||||||
|
// Because in NeoLang, numbers are default convert into Double
|
||||||
|
version = getMetaByVisitor(visitor, EKS_META_VERSION)?.toDouble()?.toInt() ?: 0
|
||||||
|
withDefaultKeys = "true" == getMetaByVisitor(visitor, EKS_META_WITH_DEFAULT)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMetaByVisitor(visitor: ConfigVisitor, metaName: String): String? {
|
||||||
|
val value = visitor.getAttribute(EKS_META_CONTEXT_PATH, metaName)
|
||||||
|
return if (value.isValid()) value.asString() else null
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,38 +0,0 @@
|
|||||||
package io.neoterm.customize.eks.builtin
|
|
||||||
|
|
||||||
import io.neoterm.frontend.preference.NeoTermPath
|
|
||||||
import io.neoterm.customize.eks.ExtraKeyConfigParser
|
|
||||||
import io.neoterm.utils.FileUtils
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
object BuiltinExtraKeys {
|
|
||||||
private const val vimKeys = "version ${ExtraKeyConfigParser.PARSER_VERSION}\n" +
|
|
||||||
"program vim neovim vi\n" +
|
|
||||||
"define dd true\n" +
|
|
||||||
"define :x true\n" +
|
|
||||||
"define :w true\n" +
|
|
||||||
"define :q true\n"
|
|
||||||
|
|
||||||
private const val moreKeys = "version ${ExtraKeyConfigParser.PARSER_VERSION}\n" +
|
|
||||||
"program more less\n" +
|
|
||||||
"define R false\n" +
|
|
||||||
"define Q false\n"
|
|
||||||
|
|
||||||
fun registerAll() {
|
|
||||||
val configDir = File(NeoTermPath.EKS_PATH)
|
|
||||||
configDir.mkdirs()
|
|
||||||
|
|
||||||
val vimFile = File(configDir, "vim.eks")
|
|
||||||
if (!vimFile.exists()) {
|
|
||||||
FileUtils.writeFile(vimFile, vimKeys.toByteArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
val moreFile = File(configDir, "more-less.eks")
|
|
||||||
if (!moreFile.exists()) {
|
|
||||||
FileUtils.writeFile(moreFile, moreKeys.toByteArray())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package io.neoterm.view.eks
|
|
||||||
|
|
||||||
import io.neoterm.customize.eks.ExtraKeyConfigParser
|
|
||||||
import io.neoterm.frontend.preference.NeoTermPath
|
|
||||||
import io.neoterm.utils.FileUtils
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
object ExtraKeysUtils {
|
|
||||||
fun generateDefaultFile(defaultFile: File) {
|
|
||||||
val DEFAULT_FILE_CONTENT = "version " + ExtraKeyConfigParser.PARSER_VERSION + "\n" +
|
|
||||||
"program default\n" +
|
|
||||||
"define - false\n" +
|
|
||||||
"define / false\n" +
|
|
||||||
"define \\ false\n" +
|
|
||||||
"define | false\n" +
|
|
||||||
"define $ false\n" +
|
|
||||||
"define < false\n" +
|
|
||||||
"define > false\n"
|
|
||||||
FileUtils.writeFile(defaultFile, DEFAULT_FILE_CONTENT.toByteArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getDefaultFile(): File {
|
|
||||||
val defaultFile = File(NeoTermPath.EKS_DEFAULT_FILE)
|
|
||||||
if (!defaultFile.exists()) {
|
|
||||||
generateDefaultFile(defaultFile)
|
|
||||||
}
|
|
||||||
return defaultFile
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,7 +7,6 @@ import android.view.*
|
|||||||
import android.widget.GridLayout
|
import android.widget.GridLayout
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.customize.eks.ExtraKeyConfigParser
|
|
||||||
import io.neoterm.frontend.preference.NeoPreference
|
import io.neoterm.frontend.preference.NeoPreference
|
||||||
import io.neoterm.ui.term.event.ToggleImeEvent
|
import io.neoterm.ui.term.event.ToggleImeEvent
|
||||||
import io.neoterm.view.eks.button.ControlButton
|
import io.neoterm.view.eks.button.ControlButton
|
||||||
@ -113,17 +112,18 @@ class ExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(contex
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadDefaultUserKeys() {
|
fun loadDefaultUserKeys() {
|
||||||
val defaultFile = ExtraKeysUtils.getDefaultFile()
|
// val defaultFile = ExtraKeysUtils.getDefaultFile()
|
||||||
clearUserKeys()
|
clearUserKeys()
|
||||||
|
|
||||||
try {
|
// TODO: loadDefaultUserKeys
|
||||||
val parser = ExtraKeyConfigParser()
|
// try {
|
||||||
parser.setInput(defaultFile)
|
// val parser = ExtraKeyConfigParser()
|
||||||
val config = parser.parse()
|
// parser.setInput(defaultFile)
|
||||||
userKeys.addAll(config.shortcutKeys)
|
// val config = parser.parse()
|
||||||
} catch (e: Exception) {
|
// userKeys.addAll(config.shortcutKeys)
|
||||||
e.printStackTrace()
|
// } catch (e: Exception) {
|
||||||
}
|
// e.printStackTrace()
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateButtons() {
|
fun updateButtons() {
|
||||||
@ -205,7 +205,7 @@ class ExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(contex
|
|||||||
outerButton.layoutParams = param
|
outerButton.layoutParams = param
|
||||||
outerButton.maxLines = 1
|
outerButton.maxLines = 1
|
||||||
outerButton.typeface = typeface
|
outerButton.typeface = typeface
|
||||||
outerButton.text = extraButton.buttonText
|
outerButton.text = extraButton.displayText
|
||||||
outerButton.setPadding(0, 0, 0, 0)
|
outerButton.setPadding(0, 0, 0, 0)
|
||||||
outerButton.setTextColor(IExtraButton.NORMAL_TEXT_COLOR)
|
outerButton.setTextColor(IExtraButton.NORMAL_TEXT_COLOR)
|
||||||
outerButton.setAllCaps(false)
|
outerButton.setAllCaps(false)
|
||||||
|
@ -1,210 +0,0 @@
|
|||||||
package io.neoterm.view.eks
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.HapticFeedbackConstants
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.Button
|
|
||||||
import android.widget.HorizontalScrollView
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.ToggleButton
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
import io.neoterm.customize.eks.ExtraKeyConfigParser
|
|
||||||
import io.neoterm.frontend.preference.NeoTermPath
|
|
||||||
import io.neoterm.utils.FileUtils
|
|
||||||
import io.neoterm.view.eks.button.ControlButton
|
|
||||||
import io.neoterm.view.eks.button.IExtraButton
|
|
||||||
import io.neoterm.view.eks.button.StatedControlButton
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A view showing extra keys (such as Escape, Ctrl, Alt) not normally available on an Android soft
|
|
||||||
* keyboard.
|
|
||||||
*/
|
|
||||||
class ScrollExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
|
|
||||||
|
|
||||||
private var builtinExtraKeys: MutableList<IExtraButton>? = null
|
|
||||||
private var userDefinedExtraKeys: MutableList<IExtraButton>? = null
|
|
||||||
|
|
||||||
private val lineOne: LinearLayout
|
|
||||||
private val lineTwo: LinearLayout
|
|
||||||
private var typeface: Typeface? = null
|
|
||||||
|
|
||||||
init {
|
|
||||||
gravity = Gravity.TOP
|
|
||||||
orientation = LinearLayout.VERTICAL
|
|
||||||
|
|
||||||
val scrollOne = HorizontalScrollView(context)
|
|
||||||
val scrollTwo = HorizontalScrollView(context)
|
|
||||||
lineOne = initLine(scrollOne)
|
|
||||||
lineTwo = initLine(scrollTwo)
|
|
||||||
addView(scrollOne)
|
|
||||||
addView(scrollTwo)
|
|
||||||
|
|
||||||
loadBuiltinKeys()
|
|
||||||
loadUserKeys()
|
|
||||||
updateButtons()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initLine(scroll: HorizontalScrollView): LinearLayout {
|
|
||||||
val line = LinearLayout(context)
|
|
||||||
line.gravity = Gravity.START
|
|
||||||
line.orientation = LinearLayout.HORIZONTAL
|
|
||||||
|
|
||||||
scroll.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f)
|
|
||||||
scroll.isFillViewport = true
|
|
||||||
scroll.isHorizontalScrollBarEnabled = false
|
|
||||||
scroll.addView(line)
|
|
||||||
return line
|
|
||||||
}
|
|
||||||
|
|
||||||
fun readControlButton(): Boolean {
|
|
||||||
return CTRL.readState()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun readAltButton(): Boolean {
|
|
||||||
return ALT.readState()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addUserKey(button: IExtraButton) {
|
|
||||||
addKeyButton(userDefinedExtraKeys, button)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addBuiltinKey(button: IExtraButton) {
|
|
||||||
addKeyButton(builtinExtraKeys, button)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clearUserKeys() {
|
|
||||||
userDefinedExtraKeys!!.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadUserKeys() {
|
|
||||||
userDefinedExtraKeys = ArrayList<IExtraButton>(8)
|
|
||||||
val defaultFile = File(NeoTermPath.EKS_DEFAULT_FILE)
|
|
||||||
if (!defaultFile.exists()) {
|
|
||||||
generateDefaultFile(defaultFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
clearUserKeys()
|
|
||||||
try {
|
|
||||||
val parser = ExtraKeyConfigParser()
|
|
||||||
parser.setInput(defaultFile)
|
|
||||||
val config = parser.parse()
|
|
||||||
userDefinedExtraKeys!!.addAll(config.shortcutKeys)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadBuiltinKeys() {
|
|
||||||
builtinExtraKeys = ArrayList<IExtraButton>(7)
|
|
||||||
builtinExtraKeys!!.clear()
|
|
||||||
builtinExtraKeys!!.add(ESC)
|
|
||||||
builtinExtraKeys!!.add(CTRL)
|
|
||||||
builtinExtraKeys!!.add(ALT)
|
|
||||||
builtinExtraKeys!!.add(TAB)
|
|
||||||
builtinExtraKeys!!.add(ARROW_UP)
|
|
||||||
builtinExtraKeys!!.add(ARROW_DOWN)
|
|
||||||
builtinExtraKeys!!.add(ARROW_LEFT)
|
|
||||||
builtinExtraKeys!!.add(ARROW_RIGHT)
|
|
||||||
builtinExtraKeys!!.add(PAGE_UP)
|
|
||||||
builtinExtraKeys!!.add(PAGE_DOWN)
|
|
||||||
builtinExtraKeys!!.add(HOME)
|
|
||||||
builtinExtraKeys!!.add(END)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateButtons() {
|
|
||||||
lineOne.removeAllViews()
|
|
||||||
lineTwo.removeAllViews()
|
|
||||||
for (extraButton in userDefinedExtraKeys!!) {
|
|
||||||
addKeyButton(lineOne, extraButton)
|
|
||||||
}
|
|
||||||
for (extraButton in builtinExtraKeys!!) {
|
|
||||||
addKeyButton(lineTwo, extraButton)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setTextColor(textColor: Int) {
|
|
||||||
NORMAL_TEXT_COLOR = textColor
|
|
||||||
updateButtons()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setTypeface(typeface: Typeface?) {
|
|
||||||
this.typeface = typeface
|
|
||||||
updateButtons()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addKeyButton(buttons: MutableList<IExtraButton>?, button: IExtraButton) {
|
|
||||||
if (buttons != null && !buttons.contains(button)) {
|
|
||||||
buttons.add(button)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addKeyButton(contentView: LinearLayout, extraButton: IExtraButton) {
|
|
||||||
val button: Button
|
|
||||||
if (extraButton is StatedControlButton) {
|
|
||||||
val btn = extraButton
|
|
||||||
val toggleButton = ToggleButton(context, null, android.R.attr.buttonBarButtonStyle)
|
|
||||||
btn.toggleButton = toggleButton
|
|
||||||
button = toggleButton
|
|
||||||
|
|
||||||
button.setClickable(true)
|
|
||||||
if (btn.initState) {
|
|
||||||
btn.toggleButton!!.isChecked = true
|
|
||||||
btn.toggleButton!!.setTextColor(SELECTED_TEXT_COLOR)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
button = Button(context, null, android.R.attr.buttonBarButtonStyle)
|
|
||||||
}
|
|
||||||
|
|
||||||
button.typeface = typeface
|
|
||||||
button.text = extraButton.buttonText
|
|
||||||
button.setTextColor(NORMAL_TEXT_COLOR)
|
|
||||||
button.setAllCaps(false)
|
|
||||||
|
|
||||||
button.setOnClickListener {
|
|
||||||
button.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
|
||||||
val root = rootView
|
|
||||||
extraButton.onClick(root)
|
|
||||||
}
|
|
||||||
contentView.addView(button)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
|
||||||
val CTRL = StatedControlButton(IExtraButton.KEY_CTRL)
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
|
||||||
val ALT = StatedControlButton(IExtraButton.KEY_ALT)
|
|
||||||
val ESC = ControlButton(IExtraButton.KEY_ESC)
|
|
||||||
val TAB = ControlButton(IExtraButton.KEY_TAB)
|
|
||||||
val PAGE_UP = ControlButton(IExtraButton.KEY_PAGE_UP)
|
|
||||||
val PAGE_DOWN = ControlButton(IExtraButton.KEY_PAGE_DOWN)
|
|
||||||
val HOME = ControlButton(IExtraButton.KEY_HOME)
|
|
||||||
val END = ControlButton(IExtraButton.KEY_END)
|
|
||||||
val ARROW_UP = ControlButton(IExtraButton.KEY_ARROW_UP)
|
|
||||||
val ARROW_DOWN = ControlButton(IExtraButton.KEY_ARROW_DOWN)
|
|
||||||
val ARROW_LEFT = ControlButton(IExtraButton.KEY_ARROW_LEFT)
|
|
||||||
val ARROW_RIGHT = ControlButton(IExtraButton.KEY_ARROW_RIGHT)
|
|
||||||
|
|
||||||
val DEFAULT_FILE_CONTENT = "version " + ExtraKeyConfigParser.PARSER_VERSION + "\n" +
|
|
||||||
"program default\n" +
|
|
||||||
"define - false\n" +
|
|
||||||
"define / false\n" +
|
|
||||||
"define | false\n" +
|
|
||||||
"define $ false\n" +
|
|
||||||
"define < false\n" +
|
|
||||||
"define > false\n"
|
|
||||||
|
|
||||||
var NORMAL_TEXT_COLOR = 0xFFFFFFFF.toInt()
|
|
||||||
var SELECTED_TEXT_COLOR = 0xFF80DEEA.toInt()
|
|
||||||
|
|
||||||
private fun generateDefaultFile(defaultFile: File) {
|
|
||||||
FileUtils.writeFile(defaultFile, DEFAULT_FILE_CONTENT.toByteArray())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,8 +4,4 @@ package io.neoterm.view.eks.button
|
|||||||
* @author kiva
|
* @author kiva
|
||||||
*/
|
*/
|
||||||
|
|
||||||
open class ControlButton(text: String) : TextButton(text, false) {
|
open class ControlButton(text: String) : TextButton(text, false)
|
||||||
init {
|
|
||||||
buttonText = text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -16,6 +16,7 @@ import io.neoterm.view.TerminalView
|
|||||||
abstract class IExtraButton : View.OnClickListener {
|
abstract class IExtraButton : View.OnClickListener {
|
||||||
|
|
||||||
var buttonText: String? = null
|
var buttonText: String? = null
|
||||||
|
var displayText: String? = null
|
||||||
|
|
||||||
abstract override fun onClick(view: View)
|
abstract override fun onClick(view: View)
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ abstract class IExtraButton : View.OnClickListener {
|
|||||||
val KEY_ESC = "Esc"
|
val KEY_ESC = "Esc"
|
||||||
val KEY_TAB = "Tab"
|
val KEY_TAB = "Tab"
|
||||||
val KEY_CTRL = "Ctrl"
|
val KEY_CTRL = "Ctrl"
|
||||||
val KEY_ALT = "Alt"
|
val KEY_ALT = "Alt"
|
||||||
val KEY_PAGE_UP = "PgUp"
|
val KEY_PAGE_UP = "PgUp"
|
||||||
val KEY_PAGE_DOWN = "PgDn"
|
val KEY_PAGE_DOWN = "PgDn"
|
||||||
val KEY_HOME = "Home"
|
val KEY_HOME = "Home"
|
||||||
|
@ -10,10 +10,11 @@ import android.widget.Button
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
open class TextButton @JvmOverloads constructor(text: String, withEnter: Boolean = false) : IExtraButton() {
|
open class TextButton @JvmOverloads constructor(text: String, withEnter: Boolean = false) : IExtraButton() {
|
||||||
private var withEnter = false
|
var withEnter = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.buttonText = text
|
this.buttonText = text
|
||||||
|
this.displayText = text
|
||||||
this.withEnter = withEnter
|
this.withEnter = withEnter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package io.neoterm
|
package io.neoterm
|
||||||
|
|
||||||
|
import io.neolang.visitor.ConfigVisitor
|
||||||
import io.neoterm.customize.color.NeoColorScheme
|
import io.neoterm.customize.color.NeoColorScheme
|
||||||
import io.neoterm.customize.config.ConfigureService
|
import io.neoterm.customize.config.ConfigureService
|
||||||
import io.neolang.visitor.ConfigVisitor
|
import io.neoterm.customize.eks.NeoExtraKey
|
||||||
import io.neoterm.frontend.config.NeoConfigureFile
|
import io.neoterm.frontend.config.NeoConfigureFile
|
||||||
import io.neoterm.frontend.service.ServiceManager
|
import io.neoterm.frontend.service.ServiceManager
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -41,21 +42,14 @@ class ConfigureFileTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun extraKeyConfigureTest() {
|
fun extraKeyConfigureTest() {
|
||||||
val visitor = parseConfigure("NeoLang/example/extra-key.nl")
|
try {
|
||||||
if (visitor != null) {
|
ServiceManager.registerService(ConfigureService::class.java)
|
||||||
val programs = visitor.getArray(arrayOf("extra-key"), "program")
|
} catch (ignore: Throwable) {
|
||||||
programs.forEachIndexed { index, element ->
|
}
|
||||||
println("program[$index]: ${element.eval().asString()}")
|
|
||||||
}
|
|
||||||
|
|
||||||
val keys = visitor.getArray(arrayOf("extra-key"), "key")
|
val extraKey = NeoExtraKey()
|
||||||
keys.forEachIndexed { index, element ->
|
if (extraKey.loadConfigure(File("NeoLang/example/extra-key.nl"))) {
|
||||||
if (element.isBlock()) {
|
println(extraKey)
|
||||||
println("key[$index]: " +
|
|
||||||
"display: ${element.eval("display").asString()}, " +
|
|
||||||
"code: ${element.eval("code").asString()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user