languages are now written to and loaded from "PHI_CONFIG_DIR/syntax/language_name.toml"

This commit is contained in:
Felix Angell 2018-04-17 14:20:22 +01:00
parent 8ece431fc4
commit c085e4e66e
7 changed files with 162 additions and 234 deletions

View File

@ -9,28 +9,24 @@ import (
)
type TomlConfig struct {
Editor EditorConfig `toml:"editor"`
Cursor CursorConfig `toml:"cursor"`
Render RenderConfig `toml:"render"`
Theme ThemeConfig `toml:"theme"`
Associations map[string]FileAssociations `toml:"file_associations"`
Commands map[string]Command `toml:"commands"`
Syntax map[string]map[string]SyntaxCriteria `toml:"syntax"`
Editor EditorConfig `toml:"editor"`
Cursor CursorConfig `toml:"cursor"`
Render RenderConfig `toml:"render"`
Theme ThemeConfig `toml:"theme"`
Associations map[string]FileAssociations `toml:"file_associations"`
Commands map[string]Command `toml:"commands"`
// this maps ext => language
// when we have file associations from
// the Associations field we take
// each extension and put them here
// pointing it to the language.
// basically the reverse/opposite
associations map[string]string
associations map[string]*LanguageSyntaxConfig
}
func (t *TomlConfig) GetLanguageFromExt(ext string) (string, error) {
// GetSyntaxConfig returns a pointer to the parsed
// syntax language file for the given file extension
// e.g. what syntax def we need for a .cpp file or a .h file
func (t *TomlConfig) GetSyntaxConfig(ext string) (*LanguageSyntaxConfig, error) {
if val, ok := t.associations[ext]; ok {
return val, nil
}
return "", errors.New("no language for extension '" + ext + "'")
return nil, errors.New("no language for extension '" + ext + "'")
}
type FileAssociations struct {

View File

@ -24,69 +24,6 @@ extensions = [".c", ".h", ".cc"]
[file_associations.go]
extensions = [".go"]
[syntax.go]
[syntax.go.keyword]
colouring = 0xf0a400
match = [
"type", "import", "package", "func", "struct",
"append", "delete", "make", "for", "if", "while",
"switch", "select", "chan", "else", "var", "const",
"iota", "case"
]
[syntax.go.type]
colouring = 0xf8f273
match = [
"int", "string", "uint",
"int8", "int16", "int32", "int64",
"uint8", "uint16", "uint32", "uint64",
"rune", "byte", "float32", "float64"
]
[syntax.go.string_literal]
colouring = 0x4b79fc
pattern = "\"([^\\\"]|\\.)*\""
[syntax.go.comment]
colouring = 0x4b79fc
pattern = '//.*'
[syntax.go.symbol]
colouring = 0xf0a400
match = [
"=", ":", ";", "*", "&", "+", "-", "/", "%",
"^", "#", "!", "@", "<", ">", ".", ","
]
[syntax.c]
[syntax.c.type]
colouring = 0xf8f273
match = [
"int", "char", "bool", "float", "double", "void",
"uint8_t", "uint16_t", "uint32_t", "uint64_t",
"int8_t", "int16_t", "int32_t", "int64_t"
]
[syntax.c.keyword]
colouring = 0xf0a400
match = [
"for", "break", "if", "else", "continue", "return",
"goto", "static", "extern", "const", "typedef",
]
[syntax.c.string_literal]
colouring = 0x4b79fc
pattern = "\"([^\\\"]|\\.)*\""
[syntax.c.directive]
colouring = 0xf0a400
pattern = "^\\s*#\\s*include\\s+(?:<[^>]*>|\"[^\"]*\")\\s*"
[syntax.c.comment]
colouring = 0x4b79fc
pattern = '//.*'
[theme]
background = 0x002649
foreground = 0xf2f4f6

View File

@ -23,8 +23,14 @@ const (
CONFIG_TOML_FILE = "config.toml"
)
// this is the absolute path to the
// config.toml file. todo rename/refactor
var CONFIG_FULL_PATH string = ""
// the absolute path to the config directory
// rename/refactor due here too!
var configDirAbsPath string = ""
// TODO we only had double key combos
// e.g. cmd+s. we want to handle things
// like cmd+alt+s
@ -38,6 +44,23 @@ var Shortcuts = &shortcutRegister{
Controls: map[string]string{},
}
func loadSyntaxDef(lang string) *LanguageSyntaxConfig {
languagePath := filepath.Join(configDirAbsPath, "syntax", lang+".toml")
syntaxTomlData, err := ioutil.ReadFile(languagePath)
if err != nil {
log.Println("Failed to load highlighting for language '"+lang+"' from path: ", languagePath)
return nil
}
var conf = &LanguageSyntaxConfig{}
if _, err := toml.Decode(string(syntaxTomlData), conf); err != nil {
panic(err)
}
log.Println("Loaded syntax definition for language", lang)
return conf
}
func configureAndValidate(conf *TomlConfig) {
// config & validate the keyboard shortcuts
log.Println("Configuring keyboard shortcuts")
@ -60,21 +83,15 @@ func configureAndValidate(conf *TomlConfig) {
log.Println("Syntax Highlighting")
{
conf.associations = map[string]string{}
conf.associations = map[string]*LanguageSyntaxConfig{}
for lang, extSet := range conf.Associations {
log.Println(lang, "=>", extSet.Extensions)
languageConfig := loadSyntaxDef(lang)
for _, ext := range extSet.Extensions {
log.Println("registering", ext, "as", lang)
conf.associations[ext] = lang
}
}
for name, conf := range conf.Syntax {
log.Println(name + ":")
for name, val := range conf {
log.Println(name, val)
conf.associations[ext] = languageConfig
}
}
}
@ -87,8 +104,15 @@ func Setup() TomlConfig {
if runtime.GOOS == "windows" {
home = os.Getenv("USERPROFILE")
}
CONFIG_DIR := filepath.Join(home, CONFIG_DIR_PATH)
configDirAbsPath = CONFIG_DIR
CONFIG_PATH := filepath.Join(CONFIG_DIR, CONFIG_TOML_FILE)
// this folder is where we store all of the language syntax
SYNTAX_CONFIG_DIR := filepath.Join(CONFIG_DIR, "syntax")
CONFIG_FULL_PATH = CONFIG_PATH
// if the user doesn't have a /.phi-editor
@ -99,6 +123,30 @@ func Setup() TomlConfig {
}
}
// try make the syntax config folder.
if _, err := os.Stat(SYNTAX_CONFIG_DIR); os.IsNotExist(err) {
if err := os.Mkdir(SYNTAX_CONFIG_DIR, 0775); err != nil {
panic(err)
}
// load all of the default language syntax
for name, syntaxDef := range DefaultSyntaxSet {
languagePath := filepath.Join(SYNTAX_CONFIG_DIR, name+".toml")
if _, err := os.Stat(languagePath); os.IsNotExist(err) {
file, err := os.Create(languagePath)
if err != nil {
panic(err)
}
defer file.Close()
if _, err := file.Write([]byte(syntaxDef)); err != nil {
panic(err)
}
log.Println("Wrote syntax for language '" + name + "'")
}
}
}
// make sure a config.toml file exists in the
// phi-editor directory.
if _, err := os.Stat(CONFIG_PATH); os.IsNotExist(err) {

View File

@ -24,69 +24,6 @@ extensions = [".c", ".h", ".cc"]
[file_associations.go]
extensions = [".go"]
[syntax.go]
[syntax.go.keyword]
colouring = 0xf0a400
match = [
"type", "import", "package", "func", "struct",
"append", "delete", "make", "for", "if", "while",
"switch", "select", "chan", "else", "var", "const",
"iota", "case"
]
[syntax.go.type]
colouring = 0xf8f273
match = [
"int", "string", "uint",
"int8", "int16", "int32", "int64",
"uint8", "uint16", "uint32", "uint64",
"rune", "byte", "float32", "float64"
]
[syntax.go.comment]
colouring = 0x4b79fc
pattern = '//.*'
[syntax.go.string_literal]
colouring = 0x4b79fc
pattern = "\"([^\\\"]|\\.)*\""
[syntax.go.symbol]
colouring = 0xf0a400
match = [
"=", ":", ";", "*", "&", "+", "-", "/", "%",
"^", "#", "!", "@", "<", ">", ".", ","
]
[syntax.c]
[syntax.c.type]
colouring = 0xf8f273
match = [
"int", "char", "bool", "float", "double", "void",
"uint8_t", "uint16_t", "uint32_t", "uint64_t",
"int8_t", "int16_t", "int32_t", "int64_t"
]
[syntax.c.keyword]
colouring = 0xf0a400
match = [
"for", "break", "if", "else", "continue", "return",
"goto", "static", "extern", "const", "typedef",
]
[syntax.c.string_literal]
colouring = 0x4b79fc
pattern = "\"([^\\\"]|\\.)*\""
[syntax.c.directive]
colouring = 0xf0a400
pattern = "^\\s*#\\s*include\\s+(?:<[^>]*>|\"[^\"]*\")\\s*"
[syntax.c.comment]
colouring = 0x4b79fc
pattern = '//.*'
[theme]
background = 0x002649
foreground = 0xf2f4f6

77
cfg/syntax.go Normal file
View File

@ -0,0 +1,77 @@
package cfg
type LanguageSyntaxConfig struct {
Syntax map[string]SyntaxCriteria `toml:"syntax"`
}
type DefaultSyntax map[string]string
var DefaultSyntaxSet = DefaultSyntax{}
func RegisterSyntax(name string, s string) {
DefaultSyntaxSet[name] = s
}
func init() {
RegisterSyntax("c", `[syntax.c]
[syntax.type]
colouring = 0xf8f273
match = [
"int", "char", "bool", "float", "double", "void",
"uint8_t", "uint16_t", "uint32_t", "uint64_t",
"int8_t", "int16_t", "int32_t", "int64_t"
]
[syntax.keyword]
colouring = 0xf0a400
match = [
"for", "break", "if", "else", "continue", "return",
"goto", "static", "extern", "const", "typedef",
]
[syntax.string_literal]
colouring = 0x4b79fc
pattern = "\"([^\\\"]|\\.)*\""
[syntax.directive]
colouring = 0xf0a400
pattern = "^\\s*#\\s*include\\s+(?:<[^>]*>|\"[^\"]*\")\\s*"
[syntax.comment]
colouring = 0x4b79fc
pattern = '//.*'`)
RegisterSyntax("go", `[syntax.go]
[syntax.go.keyword]
colouring = 0xf0a400
match = [
"type", "import", "package", "func", "struct",
"append", "delete", "make", "for", "if", "while",
"switch", "select", "chan", "else", "var", "const",
"iota", "case"
]
[syntax.go.type]
colouring = 0xf8f273
match = [
"int", "string", "uint",
"int8", "int16", "int32", "int64",
"uint8", "uint16", "uint32", "uint64",
"rune", "byte", "float32", "float64"
]
[syntax.go.comment]
colouring = 0x4b79fc
pattern = '//.*'
[syntax.go.string_literal]
colouring = 0x4b79fc
pattern = "\"([^\\\"]|\\.)*\""
[syntax.go.symbol]
colouring = 0xf0a400
match = [
"=", ":", ";", "*", "&", "+", "-", "/", "%",
"^", "#", "!", "@", "<", ">", ".", ","
]`)
}

View File

@ -24,69 +24,6 @@ extensions = [".c", ".h", ".cc"]
[file_associations.go]
extensions = [".go"]
[syntax.go]
[syntax.go.keyword]
colouring = 0xf0a400
match = [
"type", "import", "package", "func", "struct",
"append", "delete", "make", "for", "if", "while",
"switch", "select", "chan", "else", "var", "const",
"iota", "case"
]
[syntax.go.type]
colouring = 0xf8f273
match = [
"int", "string", "uint",
"int8", "int16", "int32", "int64",
"uint8", "uint16", "uint32", "uint64",
"rune", "byte", "float32", "float64"
]
[syntax.go.string_literal]
colouring = 0x4b79fc
pattern = "\"([^\\\"]|\\.)*\""
[syntax.go.comment]
colouring = 0x4b79fc
pattern = '//.*'
[syntax.go.symbol]
colouring = 0xf0a400
match = [
"=", ":", ";", "*", "&", "+", "-", "/", "%",
"^", "#", "!", "@", "<", ">", ".", ","
]
[syntax.c]
[syntax.c.type]
colouring = 0xf8f273
match = [
"int", "char", "bool", "float", "double", "void",
"uint8_t", "uint16_t", "uint32_t", "uint64_t",
"int8_t", "int16_t", "int32_t", "int64_t"
]
[syntax.c.keyword]
colouring = 0xf0a400
match = [
"for", "break", "if", "else", "continue", "return",
"goto", "static", "extern", "const", "typedef",
]
[syntax.c.string_literal]
colouring = 0x4b79fc
pattern = "\"([^\\\"]|\\.)*\""
[syntax.c.directive]
colouring = 0xf0a400
pattern = "^\\s*#\\s*include\\s+(?:<[^>]*>|\"[^\"]*\")\\s*"
[syntax.c.comment]
colouring = 0x4b79fc
pattern = '//.*'
[theme]
background = 0x002649
foreground = 0xf2f4f6

View File

@ -34,17 +34,16 @@ type camera struct {
type Buffer struct {
BaseComponent
HasFocus bool
index int
parent *View
font *strife.Font
contents []*rope.Rope
curs *Cursor
cfg *cfg.TomlConfig
cam *camera
filePath string
languageInfo string
HasFocus bool
index int
parent *View
font *strife.Font
contents []*rope.Rope
curs *Cursor
cfg *cfg.TomlConfig
cam *camera
filePath string
languageInfo *cfg.LanguageSyntaxConfig
}
func NewBuffer(conf *cfg.TomlConfig, parent *View, index int) *Buffer {
@ -73,12 +72,11 @@ func (b *Buffer) OpenFile(filePath string) {
log.Println("Opening file ", filePath)
ext := path.Ext(filePath)
lang, err := b.cfg.GetLanguageFromExt(ext)
var err error
b.languageInfo, err = b.cfg.GetSyntaxConfig(ext)
if err != nil {
log.Println(err.Error())
} else {
log.Println("- this file is a ", lang, " language program")
b.languageInfo = lang
}
// if the file doesn't exist, try to create it before reading it
@ -807,13 +805,11 @@ func (b *Buffer) renderAt(ctx *strife.Renderer, rx int, ry int) {
// char index => colour
matches := map[int]syntaxRuneInfo{}
stuff := b.cfg.Syntax[b.languageInfo]
subjects := make([]cfg.SyntaxCriteria, len(stuff))
colours := make([]int, len(stuff))
subjects := make([]cfg.SyntaxCriteria, len(b.languageInfo.Syntax))
colours := make([]int, len(b.languageInfo.Syntax))
idx := 0
for _, criteria := range stuff {
for _, criteria := range b.languageInfo.Syntax {
colours[idx] = criteria.Colour
subjects[idx] = criteria
idx++