simplified file handling for runtime files

This commit is contained in:
Florian Sundermann
2016-09-15 15:50:26 +02:00
parent 79621505f1
commit 796638d095
9 changed files with 161 additions and 230 deletions

View File

@@ -84,7 +84,8 @@ func CommandComplete(input string) (string, []string) {
func HelpComplete(input string) (string, []string) {
var suggestions []string
for topic, _ := range helpPages {
for _, file := range ListExtensionFiles(FILE_Help) {
topic := file.Name()
if strings.HasPrefix(topic, input) {
suggestions = append(suggestions, topic)
}

View File

@@ -2,7 +2,6 @@ package main
import (
"fmt"
"io/ioutil"
"regexp"
"strconv"
"strings"
@@ -16,66 +15,53 @@ type Colorscheme map[string]tcell.Style
// The current colorscheme
var colorscheme Colorscheme
var preInstalledColors = []string{"default", "simple", "solarized", "solarized-tc", "atom-dark-tc", "monokai", "gruvbox", "zenburn", "bubblegum"}
// ColorschemeExists checks if a given colorscheme exists
func ColorschemeExists(colorschemeName string) bool {
files, _ := ioutil.ReadDir(configDir + "/colorschemes")
for _, f := range files {
if f.Name() == colorschemeName+".micro" {
return true
}
}
for _, name := range preInstalledColors {
if name == colorschemeName {
return true
}
}
return false
return FindExtensionFile(FILE_ColorScheme, colorschemeName) != nil
}
// InitColorscheme picks and initializes the colorscheme when micro starts
func InitColorscheme() {
colorscheme = make(Colorscheme)
if screen != nil {
screen.SetStyle(tcell.StyleDefault.
Foreground(tcell.ColorDefault).
Background(tcell.ColorDefault))
}
LoadDefaultColorscheme()
}
// LoadDefaultColorscheme loads the default colorscheme from $(configDir)/colorschemes
func LoadDefaultColorscheme() {
LoadColorscheme(globalSettings["colorscheme"].(string), configDir+"/colorschemes")
LoadColorscheme(globalSettings["colorscheme"].(string))
}
// LoadColorscheme loads the given colorscheme from a directory
func LoadColorscheme(colorschemeName, dir string) {
files, _ := ioutil.ReadDir(dir)
found := false
for _, f := range files {
if f.Name() == colorschemeName+".micro" {
text, err := ioutil.ReadFile(dir + "/" + f.Name())
if err != nil {
fmt.Println("Error loading colorscheme:", err)
continue
}
colorscheme = ParseColorscheme(string(text))
found = true
}
}
for _, name := range preInstalledColors {
if name == colorschemeName {
data, err := Asset("runtime/colorschemes/" + name + ".micro")
if err != nil {
TermMessage("Unable to load pre-installed colorscheme " + name)
continue
}
colorscheme = ParseColorscheme(string(data))
found = true
}
}
if !found {
func LoadColorscheme(colorschemeName string) {
file := FindExtensionFile(FILE_ColorScheme, colorschemeName)
if file == nil {
TermMessage(colorschemeName, "is not a valid colorscheme")
} else {
if data, err := file.Data(); err != nil {
fmt.Println("Error loading colorscheme:", err)
} else {
colorscheme = ParseColorscheme(string(data))
// Default style
defStyle = tcell.StyleDefault.
Foreground(tcell.ColorDefault).
Background(tcell.ColorDefault)
// There may be another default style defined in the colorscheme
// In that case we should use that one
if style, ok := colorscheme["default"]; ok {
defStyle = style
}
if screen != nil {
screen.SetStyle(defStyle)
}
}
}
}

View File

@@ -94,7 +94,7 @@ func Help(args []string) {
CurView().openHelp("help")
} else {
helpPage := args[0]
if _, ok := helpPages[helpPage]; ok {
if FindExtensionFile(FILE_Help, helpPage) != nil {
CurView().openHelp(helpPage)
} else {
messenger.Error("Sorry, no help for ", helpPage)

115
cmd/micro/extfiles.go Normal file
View File

@@ -0,0 +1,115 @@
package main
import (
"io/ioutil"
"path"
"path/filepath"
)
const (
FILE_ColorScheme = "colorscheme"
FILE_Syntax = "syntax"
FILE_Help = "help"
)
// ExtensionFile allows the program to read runtime data like colorschemes or syntax files
type ExtensionFile interface {
// Name returns a name of the file without paths or extensions
Name() string
// Data returns the content of the file.
Data() ([]byte, error)
}
// allFiles contains all available files, mapped by filetype
var allFiles map[string][]ExtensionFile
// some file on filesystem
type realFile string
// some asset file
type assetFile string
// some file on filesystem but with a different name
type namedFile struct {
realFile
name string
}
func (rf realFile) Name() string {
fn := filepath.Base(string(rf))
return fn[:len(fn)-len(filepath.Ext(fn))]
}
func (rf realFile) Data() ([]byte, error) {
return ioutil.ReadFile(string(rf))
}
func (af assetFile) Name() string {
fn := path.Base(string(af))
return fn[:len(fn)-len(path.Ext(fn))]
}
func (af assetFile) Data() ([]byte, error) {
return Asset(string(af))
}
func (nf namedFile) Name() string {
return nf.name
}
func AddFile(fileType string, file ExtensionFile) {
if allFiles == nil {
allFiles = make(map[string][]ExtensionFile)
}
allFiles[fileType] = append(allFiles[fileType], file)
}
func AddFilesFromDirectory(fileType, directory, pattern string) {
files, _ := ioutil.ReadDir(directory)
for _, f := range files {
if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok {
fullPath := filepath.Join(directory, f.Name())
AddFile(fileType, realFile(fullPath))
}
}
}
func AddFilesFromAssets(fileType, directory, pattern string) {
files, err := AssetDir(directory)
if err != nil {
return
}
for _, f := range files {
if ok, _ := path.Match(pattern, f); ok {
AddFile(fileType, assetFile(path.Join(directory, f)))
}
}
}
func FindExtensionFile(fileType, name string) ExtensionFile {
for _, f := range ListExtensionFiles(fileType) {
if f.Name() == name {
return f
}
}
return nil
}
func ListExtensionFiles(fileType string) []ExtensionFile {
if files, ok := allFiles[fileType]; ok {
return files
} else {
return []ExtensionFile{}
}
}
func InitExtensionFiles() {
add := func(fileType, dir, pattern string) {
AddFilesFromDirectory(fileType, filepath.Join(configDir, dir), pattern)
AddFilesFromAssets(fileType, path.Join("runtime", dir), pattern)
}
add(FILE_ColorScheme, "colorschemes", "*.micro")
add(FILE_Syntax, "syntax", "*.micro")
add(FILE_Help, "help", "*.md")
}

View File

@@ -1,38 +0,0 @@
package main
import (
"io/ioutil"
)
type HelpPage interface {
HelpFile() ([]byte, error)
}
var helpPages map[string]HelpPage = map[string]HelpPage{
"help": assetHelpPage("help"),
"keybindings": assetHelpPage("keybindings"),
"plugins": assetHelpPage("plugins"),
"colors": assetHelpPage("colors"),
"options": assetHelpPage("options"),
"commands": assetHelpPage("commands"),
"tutorial": assetHelpPage("tutorial"),
}
type assetHelpPage string
func (file assetHelpPage) HelpFile() ([]byte, error) {
return Asset("runtime/help/" + string(file) + ".md")
}
type fileHelpPage string
func (file fileHelpPage) HelpFile() ([]byte, error) {
return ioutil.ReadFile(string(file))
}
func AddPluginHelp(name, file string) {
if _, exists := helpPages[name]; exists {
return
}
helpPages[name] = fileHelpPage(file)
}

View File

@@ -1,8 +1,6 @@
package main
import (
"io/ioutil"
"path/filepath"
"regexp"
"strings"
@@ -30,150 +28,16 @@ type SyntaxRule struct {
var syntaxFiles map[[2]*regexp.Regexp]FileTypeRules
// These syntax files are pre installed and embedded in the resulting binary by go-bindata
var preInstalledSynFiles = []string{
"Dockerfile",
"apacheconf",
"arduino",
"asciidoc",
"asm",
"awk",
"c",
"caddyfile",
"cmake",
"coffeescript",
"colortest",
"conf",
"conky",
"csharp",
"css",
"cython",
"d",
"dart",
"dot",
"erb",
"fish",
"fortran",
"gdscript",
"gentoo-ebuild",
"gentoo-etc-portage",
"git-commit",
"git-config",
"git-rebase-todo",
"glsl",
"go",
"golo",
"groff",
"haml",
"haskell",
"html",
"ini",
"inputrc",
"java",
"javascript",
"json",
"keymap",
"kickstart",
"ledger",
"lilypond",
"lisp",
"lua",
"makefile",
"man",
"markdown",
"mpdconf",
"micro",
"nanorc",
"nginx",
"ocaml",
"pascal",
"patch",
"peg",
"perl",
"perl6",
"php",
"pkg-config",
"po",
"pov",
"privoxy-action",
"privoxy-config",
"privoxy-filter",
"puppet",
"python",
"r",
"reST",
"rpmspec",
"ruby",
"rust",
"scala",
"sed",
"sh",
"sls",
"sql",
"swift",
"systemd",
"tcl",
"tex",
"vala",
"vi",
"xml",
"xresources",
"yaml",
"yum",
"zsh",
}
// LoadSyntaxFiles loads the syntax files from the default directory (configDir)
func LoadSyntaxFiles() {
// Load the user's custom syntax files, if there are any
LoadSyntaxFilesFromDir(configDir + "/syntax")
// Load the pre-installed syntax files from inside the binary
for _, filetype := range preInstalledSynFiles {
data, err := Asset("runtime/syntax/" + filetype + ".micro")
if err != nil {
TermMessage("Unable to load pre-installed syntax file " + filetype)
continue
}
LoadSyntaxFile(string(data), filetype+".micro")
}
}
// LoadSyntaxFilesFromDir loads the syntax files from a specified directory
// To load the syntax files, we must fill the `syntaxFiles` map
// This involves finding the regex for syntax and if it exists, the regex
// for the header. Then we must get the text for the file and the filetype.
func LoadSyntaxFilesFromDir(dir string) {
colorscheme = make(Colorscheme)
InitColorscheme()
// Default style
defStyle = tcell.StyleDefault.
Foreground(tcell.ColorDefault).
Background(tcell.ColorDefault)
// There may be another default style defined in the colorscheme
// In that case we should use that one
if style, ok := colorscheme["default"]; ok {
defStyle = style
}
if screen != nil {
screen.SetStyle(defStyle)
}
syntaxFiles = make(map[[2]*regexp.Regexp]FileTypeRules)
files, _ := ioutil.ReadDir(dir)
for _, f := range files {
if filepath.Ext(f.Name()) == ".micro" {
filename := dir + "/" + f.Name()
text, err := ioutil.ReadFile(filename)
if err != nil {
TermMessage("Error loading syntax file " + filename + ": " + err.Error())
return
}
LoadSyntaxFile(string(text), filename)
for _, f := range ListExtensionFiles(FILE_Syntax) {
data, err := f.Data()
if err != nil {
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
} else {
LoadSyntaxFile(string(data), f.Name())
}
}
}

View File

@@ -233,6 +233,9 @@ func main() {
// Find the user's configuration directory (probably $XDG_CONFIG_HOME/micro)
InitConfigDir()
// Build a list of available Extensions (Syntax, Colorscheme etc.)
InitExtensionFiles()
// Load the user's settings
InitGlobalSettings()

View File

@@ -138,7 +138,7 @@ func LoadPlugins() {
}
loadedPlugins = append(loadedPlugins, pluginName)
} else if f.Name() == "help.md" {
AddPluginHelp(pluginName, fullPath)
AddFile(FILE_Help, namedFile{realFile(fullPath), pluginName})
}
}
}

View File

@@ -529,7 +529,7 @@ func (v *View) ClearAllGutterMessages() {
// Opens the given help page in a new horizontal split
func (v *View) openHelp(helpPage string) {
if data, err := helpPages[helpPage].HelpFile(); err != nil {
if data, err := FindExtensionFile(FILE_Help, helpPage).Data(); err != nil {
TermMessage("Unable to load help text", helpPage, "\n", err)
} else {
helpBuffer := NewBuffer(data, helpPage+".md")