예제 #1
0
// Searches for a QueryContextCallback and returns the result of the first callback being able to deal with this
// context, or Unknown if no such callback was found.
func (qe QueryContextEvent) Call(v *View, key string, operator util.Op, operand interface{}, match_all bool) QueryContextReturn {
	log.Fine("Query context: %s, %v, %v, %v", key, operator, operand, match_all)
	for i := range qe {
		r := qe[i](v, key, operator, operand, match_all)
		if r != Unknown {
			return r
		}
	}
	log.Fine("Unknown context: %s", key)
	return Unknown
}
예제 #2
0
파일: language.go 프로젝트: hanshenu/lime
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
}
예제 #3
0
파일: view.go 프로젝트: rokite/lime
// 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.buffer.Settings().Set("lime.last_save_change_count", v.buffer.ChangeCount())
	OnPostSave.Call(v)
	return nil
}
예제 #4
0
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
}
예제 #5
0
파일: watch.go 프로젝트: hanshenu/lime
func (w *Watcher) Watch(name string, cb interface{}) error {
	log.Finest("Watch(%s)", name)
	fi, err := os.Stat(name)
	isDir := err == nil && fi.IsDir()
	// If the file doesn't exist currently we will add watcher for file
	// directory and look for create event inside the directory
	if os.IsNotExist(err) {
		log.Fine("%s doesn't exist, Watching parent directory", name)
		if err := w.Watch(filepath.Dir(name), nil); err != nil {
			return err
		}
	}
	w.lock.Lock()
	defer w.lock.Unlock()
	if err := w.add(name, cb); err != nil {
		if !isDir {
			return err
		}
		if exist(w.dirs, name) {
			log.Debug("%s is watched already", name)
			return nil
		}
	}
	// If exists in watchers we are already watching the path
	// Or
	// If the file is under one of watched dirs
	//
	// no need to create watcher
	if exist(w.watchers, name) || (!isDir && exist(w.dirs, filepath.Dir(name))) {
		return nil
	}
	if err := w.watch(name); err != nil {
		return err
	}
	if isDir {
		w.flushDir(name)
	}
	return nil
}
예제 #6
0
func (c *ViewEventGlue) onEvent(v *backend.View) {
	l := py.NewLock()
	defer l.Unlock()
	pv, err := toPython(v)
	if err != nil {
		log.Error(err)
	}
	defer pv.Decref()
	log.Fine("onEvent: %v, %v, %v", c, c.inner, pv)
	// interrupt := true
	// defer func() { interrupt = false }()
	// go func() {
	// 	<-time.After(time.Second * 5)
	// 	if interrupt {
	// 		py.SetInterrupt()
	// 	}
	// }()

	if ret, err := c.inner.Base().CallFunctionObjArgs(pv); err != nil {
		log.Error(err)
	} else if ret != nil {
		ret.Decref()
	}
}
예제 #7
0
파일: view.go 프로젝트: rokite/lime
// 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)
	}
}
예제 #8
0
func (c *OnQueryContextGlue) onQueryContext(v *backend.View, key string, operator util.Op, operand interface{}, match_all bool) backend.QueryContextReturn {
	l := py.NewLock()
	defer l.Unlock()

	var (
		pv, pk, po, poa, pm, ret py.Object
		err                      error
	)
	if pv, err = toPython(v); err != nil {
		log.Error(err)
		return backend.Unknown
	}
	defer pv.Decref()

	if pk, err = toPython(key); err != nil {
		log.Error(err)
		return backend.Unknown
	}
	defer pk.Decref()

	if po, err = toPython(operator); err != nil {
		log.Error(err)
		return backend.Unknown
	}
	defer po.Decref()

	if poa, err = toPython(operand); err != nil {
		log.Error(err)
		return backend.Unknown
	}
	defer poa.Decref()

	if pm, err = toPython(match_all); err != nil {
		log.Error(err)
		return backend.Unknown
	}
	defer pm.Decref()
	// interrupt := true
	// defer func() { interrupt = false }()
	// go func() {
	// 	<-time.After(time.Second * 5)
	// 	if interrupt {
	// 		py.SetInterrupt()
	// 	}
	// }()

	if ret, err = c.inner.Base().CallFunctionObjArgs(pv, pk, po, poa, pm); err != nil {
		log.Error(err)
		return backend.Unknown
	}
	defer ret.Decref()

	if r2, ok := ret.(*py.Bool); ok {
		if r2.Bool() {
			return backend.True
		} else {
			return backend.False
		}
	} else {
		log.Fine("other: %v", ret)
	}
	return backend.Unknown
}