return true
}
-// SelectUp selects down one line
+// SelectDown selects down one line
func (v *View) SelectDown() bool {
loc := v.cursor.Loc()
if !v.cursor.HasSelection() {
ws := GetLeadingWhitespace(v.buf.lines[v.cursor.y])
v.cursor.Right()
- if settings.AutoIndent {
+ if settings["autoindent"].(bool) {
v.eh.Insert(v.cursor.Loc(), ws)
for i := 0; i < len(ws); i++ {
v.cursor.Right()
// whitespace at the start of the line, we should delete as if its a
// tab (tabSize number of spaces)
lineStart := v.buf.lines[v.cursor.y][:v.cursor.x]
- if settings.TabsToSpaces && IsSpaces(lineStart) && len(lineStart) != 0 && len(lineStart)%settings.TabSize == 0 {
+ tabSize := int(settings["tabsize"].(float64))
+ if settings["tabsToSpaces"].(bool) && IsSpaces(lineStart) && len(lineStart) != 0 && len(lineStart)%tabSize == 0 {
loc := v.cursor.Loc()
- v.cursor.SetLoc(loc - settings.TabSize)
+ v.cursor.SetLoc(loc - tabSize)
cx, cy := v.cursor.x, v.cursor.y
v.cursor.SetLoc(loc)
- v.eh.Remove(loc-settings.TabSize, loc)
+ v.eh.Remove(loc-tabSize, loc)
v.cursor.x, v.cursor.y = cx, cy
} else {
v.cursor.Left()
v.cursor.DeleteSelection()
v.cursor.ResetSelection()
}
- if settings.TabsToSpaces {
- v.eh.Insert(v.cursor.Loc(), Spaces(settings.TabSize))
- for i := 0; i < settings.TabSize; i++ {
+ if settings["tabsToSpaces"].(bool) {
+ tabSize := int(settings["tabsize"].(float64))
+ v.eh.Insert(v.cursor.Loc(), Spaces(tabSize))
+ for i := 0; i < tabSize; i++ {
v.cursor.Right()
}
} else {
// GoSave saves the current file (must be a go file) and runs goimports or gofmt
// depending on the user's configuration
func (v *View) GoSave() {
- if settings.GoImports == true {
+ if settings["goimports"] == true {
messenger.Message("Running goimports...")
err := goimports(v.buf.path)
if err != nil {
messenger.Message("Saved " + v.buf.path)
}
v.reOpen()
- } else if settings.GoFmt == true {
+ } else if settings["gofmt"] == true {
messenger.Message("Running gofmt...")
err := gofmt(v.buf.path)
if err != nil {
// ToggleRuler turns line numbers off and on
func (v *View) ToggleRuler() bool {
- if settings.Ruler == false {
- settings.Ruler = true
+ if settings["ruler"] == false {
+ settings["ruler"] = true
} else {
- settings.Ruler = false
+ settings["ruler"] = false
}
return false
}
// LoadDefaultColorscheme loads the default colorscheme from $(configDir)/colorschemes
func LoadDefaultColorscheme() {
- LoadColorscheme(settings.Colorscheme, configDir+"/colorschemes")
+ LoadColorscheme(settings["colorscheme"].(string), configDir+"/colorschemes")
}
// LoadColorscheme loads the given colorscheme from a directory
// GetCharPosInLine gets the char position of a visual x y coordinate (this is necessary because tabs are 1 char but 4 visual spaces)
func (c *Cursor) GetCharPosInLine(lineNum, visualPos int) int {
// Get the tab size
- tabSize := settings.TabSize
+ tabSize := int(settings["tabsize"].(float64))
// This is the visual line -- every \t replaced with the correct number of spaces
visualLine := strings.Replace(c.v.buf.lines[lineNum], "\t", "\t"+Spaces(tabSize-1), -1)
if visualPos > Count(visualLine) {
// GetVisualX returns the x value of the cursor in visual spaces
func (c *Cursor) GetVisualX() int {
runes := []rune(c.v.buf.lines[c.y])
- tabSize := settings.TabSize
+ tabSize := int(settings["tabsize"].(float64))
return c.x + NumOccurences(string(runes[:c.x]), '\t')*(tabSize-1)
}
)
// The options that the user can set
-var settings Settings
-
-// All the possible settings
-// This map maps the name of the setting in the Settings struct
-// to the name that the user will actually use (the one in the json file)
-var possibleSettings = map[string]string{
- "colorscheme": "Colorscheme",
- "tabsize": "TabSize",
- "autoindent": "AutoIndent",
- "syntax": "Syntax",
- "tabsToSpaces": "TabsToSpaces",
- "ruler": "Ruler",
- "gofmt": "GoFmt",
- "goimports": "GoImports",
-}
-
-// The Settings struct contains the settings for micro
-type Settings struct {
- Colorscheme string `json:"colorscheme"`
- TabSize int `json:"tabsize"`
- AutoIndent bool `json:"autoindent"`
- Syntax bool `json:"syntax"`
- TabsToSpaces bool `json:"tabsToSpaces"`
- Ruler bool `json:"ruler"`
- GoFmt bool `json:"gofmt"`
- GoImports bool `json:"goimports"`
-}
+var settings map[string]interface{}
// InitSettings initializes the options map and sets all options to their default values
func InitSettings() {
+ settings = make(map[string]interface{})
filename := configDir + "/settings.json"
if _, e := os.Stat(filename); e == nil {
input, err := ioutil.ReadFile(filename)
}
// DefaultSettings returns the default settings for micro
-func DefaultSettings() Settings {
- return Settings{
- Colorscheme: "default",
- TabSize: 4,
- AutoIndent: true,
- Syntax: true,
- TabsToSpaces: false,
- Ruler: true,
- GoFmt: false,
- GoImports: false,
+func DefaultSettings() map[string]interface{} {
+ return map[string]interface{}{
+ "colorscheme": "default",
+ "tabsize": 4,
+ "autoindent": true,
+ "syntax": true,
+ "tabsToSpaces": false,
+ "ruler": true,
+ "gofmt": false,
+ "goimports": false,
}
}
option := strings.TrimSpace(args[0])
value := strings.TrimSpace(args[1])
- mutable := reflect.ValueOf(&settings).Elem()
- field := mutable.FieldByName(possibleSettings[option])
- if !field.IsValid() {
+ if _, ok := settings[option]; !ok {
messenger.Error(option + " is not a valid option")
return
}
- kind := field.Type().Kind()
+
+ kind := reflect.TypeOf(settings[option]).Kind()
if kind == reflect.Bool {
b, err := ParseBool(value)
if err != nil {
messenger.Error("Invalid value for " + option)
return
}
- field.SetBool(b)
+ settings[option] = b
} else if kind == reflect.String {
- field.SetString(value)
- } else if kind == reflect.Int {
+ settings[option] = value
+ } else if kind == reflect.Float64 {
i, err := strconv.Atoi(value)
if err != nil {
messenger.Error("Invalid value for " + option)
return
}
- field.SetInt(int64(i))
+ settings[option] = float64(i)
}
if option == "colorscheme" {
if relocate {
v.Relocate()
}
- if settings.Syntax {
+ if settings["syntax"].(bool) {
v.matches = Match(v)
}
}
// We are going to have to offset by that amount
maxLineLength := len(strconv.Itoa(len(v.buf.lines)))
// + 1 for the little space after the line number
- if settings.Ruler == true {
+ if settings["ruler"] == true {
v.lineNumOffset = maxLineLength + 1
} else {
v.lineNumOffset = 0
}
// Write the spaces before the line number if necessary
var lineNum string
- if settings.Ruler == true {
+ if settings["ruler"] == true {
lineNum = strconv.Itoa(lineN + v.topline + 1)
for i := 0; i < maxLineLength-len(lineNum); i++ {
screen.SetContent(x, lineN, ' ', nil, lineNumStyle)
x++
}
- if settings.Ruler == true {
+ if settings["ruler"] == true {
// Write the extra space
screen.SetContent(x, lineN, ' ', nil, lineNumStyle)
x++
for colN, ch := range line {
var lineStyle tcell.Style
- if settings.Syntax {
+ if settings["syntax"].(bool) {
// Syntax highlighting is enabled
highlightStyle = v.matches[lineN][colN]
}
if ch == '\t' {
screen.SetContent(x+tabchars, lineN, ' ', nil, lineStyle)
- tabSize := settings.TabSize
+ tabSize := int(settings["tabsize"].(float64))
for i := 0; i < tabSize-1; i++ {
tabchars++
if x-v.leftCol+tabchars >= v.lineNumOffset {