func (p *Pattern) Cache(data string, pos int) (pat *Pattern, ret MatchObject) { if p.cachedData == data { if p.cachedMatch == nil { return nil, nil } if p.cachedMatch[0] >= pos && p.cachedPat.cachedMatch != nil { p.hits++ return p.cachedPat, p.cachedMatch } } else { p.cachedPatterns = nil } if p.cachedPatterns == nil { p.cachedPatterns = make([]*Pattern, len(p.Patterns)) for i := range p.cachedPatterns { p.cachedPatterns[i] = &p.Patterns[i] } } p.misses++ if p.Match.re != nil { pat, ret = p, p.Match.Find(data, pos) } else if p.Begin.re != nil { pat, ret = p, p.Begin.Find(data, pos) } else if p.Include != "" { if z := p.Include[0]; z == '#' { key := p.Include[1:] if p2, ok := p.owner.Repository[key]; ok { pat, ret = p2.Cache(data, pos) } else { log.Fine("Not found in repository: %s", p.Include) } } else if z == '$' { // TODO(q): Implement tmLanguage $ include directives log.Warn("Unhandled include directive: %s", p.Include) } else if l, err := Provider.GetLanguage(p.Include); err != nil { if !failed[p.Include] { log.Warn("Include directive %s failed: %s", p.Include, err) } failed[p.Include] = true } else { return l.RootPattern.Cache(data, pos) } } else { pat, ret = p.FirstMatch(data, pos) } p.cachedData = data p.cachedMatch = ret p.cachedPat = pat return }
// Saves the file to the specified filename func (v *View) SaveAs(name string) (err error) { log.Fine("SaveAs(%s)", name) v.Settings().Set("lime.saving", true) defer v.Settings().Erase("lime.saving") var atomic bool OnPreSave.Call(v) if atomic, _ = v.Settings().Get("atomic_save", true).(bool); v.buffer.FileName() == "" || !atomic { if err := v.nonAtomicSave(name); err != nil { return err } } else { n, err := ioutil.TempDir(path.Dir(v.buffer.FileName()), "lime") if err != nil { return err } tmpf := path.Join(n, "tmp") if err := v.nonAtomicSave(tmpf); err != nil { return err } if err := os.Rename(tmpf, name); err != nil { // When we want to save as a file in another directory // we can't go with os.Rename so we need to force // not atomic saving sometimes as 4th test in TestSaveAsOpenFile if err := v.nonAtomicSave(name); err != nil { return err } } if err := os.RemoveAll(n); err != nil { return err } } ed := GetEditor() if fn := v.buffer.FileName(); fn != name { v.buffer.SetFileName(name) if fn != "" { ed.UnWatch(fn, v) } ed.Watch(name, v) } v.Settings().Set("lime.last_save_change_count", v.buffer.ChangeCount()) OnPostSave.Call(v) return nil }
func (ch *commandHandler) RunApplicationCommand(name string, args Args) error { p := Prof.Enter("ac") defer p.Exit() if ch.log { log.Info("Running application command: %s %v", name, args) } else { log.Fine("Running application command: %s %v", name, args) } if c, ok := ch.ApplicationCommands[name].(ApplicationCommand); c != nil && ok { if err := ch.init(c, args); err != nil && ch.verbose { log.Debug("Command initialization failed: %s", err) return err } else if err := c.Run(); err != nil && ch.verbose { log.Debug("Command execution failed: %s", err) return err } } return nil }
// Ends the given Edit object. func (v *View) EndEdit(edit *Edit) { if edit.invalid { // This happens when nesting Edits and the child Edit ends after the parent edit. log.Fine("This edit has already been invalidated: %v, %v", edit, v.editstack) return } // Find the position of this Edit object in this View's Edit stack. // If plugins, commands, etc are well-behaved the ended edit should be // last in the stack, but shit happens and we cannot count on this being the case. i := len(v.editstack) - 1 for i := len(v.editstack) - 1; i >= 0; i-- { if v.editstack[i] == edit { break } } if i == -1 { // TODO(.): Under what instances does this happen again? log.Errorf("This edit isn't even in the stack... where did it come from? %v, %v", edit, v.editstack) return } var selection_modified bool if l := len(v.editstack) - 1; i != l { // TODO(.): See TODO in BeginEdit log.Errorf("This edit wasn't last in the stack... %d != %d: %v, %v", i, l, edit, v.editstack) } // Invalidate all Edits "below" and including this Edit. for j := len(v.editstack) - 1; j >= i; j-- { current_edit := v.editstack[j] current_edit.invalid = true sel_same := reflect.DeepEqual(*v.Sel(), current_edit.savedSel) buf_same := v.buffer.ChangeCount() == current_edit.savedCount eq := (sel_same && buf_same && current_edit.composite.Len() == 0) if !eq && !sel_same { selection_modified = true } if v.IsScratch() || current_edit.bypassUndo || eq { continue } switch { case i == 0: // Well-behaved, no nested edits! fallthrough case j != i: // BOO! Someone began another Edit without finishing the first one. // In this instance, the parent Edit ended before the child. // TODO(.): What would be the correct way to handle this? v.undoStack.Add(edit) default: // BOO! Also poorly-behaved. This Edit object began after the parent began, // but was finished before the parent finished. // // Add it as a child of the parent Edit so that undoing the parent // will undo this edit as well. v.editstack[i-1].composite.Add(current_edit) } } // Pop this Edit and all the children off the Edit stack. v.editstack = v.editstack[:i] if selection_modified { OnSelectionModified.Call(v) } }