diff --git a/README.md b/README.md index 8d0a153..7c6fb9f 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,19 @@ The editor must: * look pretty; and finally * be easy to use +# reporting bugs/troubleshooting +Note the editor is still unstable. Please report any bugs you find so I can +squash them! It is appreciated if you skim the issue handler to make sure +you aren't reporting duplicate bugs. + +## before filing an issue +Just to make sure it's an issue with the editor currently and not due to a +broken change, please: + +* make sure the repository is up to date +* make sure all the dependencies are updated, especially "github.com/felixangell/strife" +* try removing the ~/.phi-config folder manually and letting the editor re-load it + # building You'll need Go with the GOPATH, GOBIN, etc. setup, as well as SDL2, SDL2\_image, and SDL2\_ttf. Here's an example for Ubuntu: diff --git a/cfg/config.go b/cfg/config.go index 027e0d3..610d24b 100644 --- a/cfg/config.go +++ b/cfg/config.go @@ -7,28 +7,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 { diff --git a/cfg/config_any.go b/cfg/config_any.go index fd8628d..ac122a0 100644 --- a/cfg/config_any.go +++ b/cfg/config_any.go @@ -26,69 +26,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 diff --git a/cfg/config_linux.go b/cfg/config_linux.go index a897ffe..20d0e88 100644 --- a/cfg/config_linux.go +++ b/cfg/config_linux.go @@ -26,69 +26,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 diff --git a/cfg/config_mac.go b/cfg/config_mac.go index db8aa6f..08cdb6b 100644 --- a/cfg/config_mac.go +++ b/cfg/config_mac.go @@ -26,69 +26,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 diff --git a/cfg/loader.go b/cfg/loader.go index c68cd28..3550f9a 100644 --- a/cfg/loader.go +++ b/cfg/loader.go @@ -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) { diff --git a/cfg/syntax.go b/cfg/syntax.go new file mode 100644 index 0000000..216ca92 --- /dev/null +++ b/cfg/syntax.go @@ -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 = [ + "=", ":", ";", "*", "&", "+", "-", "/", "%", + "^", "#", "!", "@", "<", ">", ".", "," +]`) +} diff --git a/gui/buffer.go b/gui/buffer.go index 1f882ec..81b0567 100644 --- a/gui/buffer.go +++ b/gui/buffer.go @@ -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++