func onInit() {
	l := py.NewLock()
	defer l.Unlock()
	m, err := py.Import("sublime_plugin")
	if err != nil {
		panic(err)
	}
	sys, err := py.Import("sys")
	if err != nil {
		log.Debug(err)
	} else {
		defer sys.Decref()
	}

	if watcher, err = watch.NewWatcher(); err != nil {
		log.Error("Couldn't create watcher: %s", err)
	}

	// TODO: add all plugins after supporting all commands
	// plugins := packages.ScanPlugins(backend.LIME_PACKAGES_PATH, ".py")
	// for _, p := range plugins {
	// 	newPlugin(p, m)
	// }
	newPlugin(packages.NewPlugin(path.Join(backend.LIME_PACKAGES_PATH, "Vintageous"), ".py"), m)

	go watcher.Observe()
}
func (p *plugin) loadPlugin() {
	fi := p.Get().([]os.FileInfo)
	for _, f := range fi {
		fn := f.Name()
		s, err := py.NewUnicode(path.Base(p.Name()) + "." + fn[:len(fn)-3])
		if err != nil {
			log.Error(err)
			return
		}
		if r, err := p.m.Base().CallMethodObjArgs("reload_plugin", s); err != nil {
			log.Error(err)
		} else if r != nil {
			r.Decref()
		}
	}
}
Beispiel #3
0
func main() {
	flag.Parse()

	log.AddFilter("file", log.FINEST, log.NewFileLogWriter("debug.log", *rotateLog))
	defer func() {
		py.NewLock()
		py.Finalize()
	}()

	if err := termbox.Init(); err != nil {
		log.Error(err)
		log.Close()
		return
	}

	defer func() {
		termbox.Close()
		log.Debug(util.Prof)
		if err := recover(); err != nil {
			log.Critical(err)
			panic(err)
		}
	}()

	t := createFrontend()
	go t.renderthread()
	go t.editor.Init()
	t.loop()
}
Beispiel #4
0
func (t *tbfe) renderthread() {
	pc := 0
	dorender := func() {
		defer func() {
			if r := recover(); r != nil {
				log.Error("Panic in renderthread: %v\n%s", r, string(debug.Stack()))
				if pc > 1 {
					panic(r)
				}
				pc++
			}
		}()
		termbox.Clear(defaultFg, defaultBg)

		t.lock.Lock()
		vs := make([]*backend.View, 0, len(t.layout))
		ls := make([]layout, 0, len(t.layout))
		for v, l := range t.layout {
			vs = append(vs, v)
			ls = append(ls, l)
		}
		t.lock.Unlock()

		for i, v := range vs {
			t.renderView(v, ls[i])
		}

		termbox.Flush()
	}

	for range t.dorender {
		dorender()
	}
}
Beispiel #5
0
func (w *Window) OpenFile(filename string, flags int) *View {
	v := w.NewFile()

	v.SetScratch(true)
	e := v.BeginEdit()
	if fn, err := filepath.Abs(filename); err != nil {
		v.Buffer().SetFileName(filename)
	} else {
		v.Buffer().SetFileName(fn)
	}
	if d, err := ioutil.ReadFile(filename); err != nil {
		log.Error("Couldn't load file %s: %s", filename, err)
	} else {
		v.Insert(e, 0, string(d))
	}
	v.EndEdit(e)
	v.selection.Clear()
	v.selection.Add(text.Region{A: 0, B: 0})
	v.Settings().Set("lime.last_save_change_count", v.buffer.ChangeCount())
	v.SetScratch(false)

	OnLoad.Call(v)
	w.SetActiveView(v)

	return v
}
Beispiel #6
0
// Will load view settings respect to current syntax
// e.g if current syntax is Python settings order will be:
// Packages/Python/Python.sublime-settings
// Packages/User/Python.sublime-settings
// <Buffer Specific Settings>
func (v *View) loadSettings() {
	syntax := v.Settings().Get("syntax", "").(string)

	if syntax == "" {
		v.Settings().SetParent(v.window)
		return
	}

	defSettings, usrSettings := &HasSettings{}, &HasSettings{}

	defSettings.Settings().SetParent(v.window)
	usrSettings.Settings().SetParent(defSettings)
	v.Settings().SetParent(usrSettings)

	ed := GetEditor()
	if r, err := rubex.Compile(`([A-Za-z]+?)\.(?:[^.]+)$`); err != nil {
		log.Error(err)
		return
	} else if s := r.FindStringSubmatch(syntax); s != nil {
		p := path.Join(LIME_PACKAGES_PATH, s[1], s[1]+".sublime-settings")
		ed.load(packages.NewPacket(p, defSettings.Settings()))

		p = path.Join(LIME_USER_PACKAGES_PATH, s[1]+".sublime-settings")
		ed.load(packages.NewPacket(p, usrSettings.Settings()))
	}
}
Beispiel #7
0
func (fv *frontendView) Line(index int) *lineStruct {
	if index < 0 || index >= len(fv.FormattedLine) {
		log.Error("Error? Line index out of bounds: %v %v\n", index, len(fv.FormattedLine))
		return nil
	}
	return fv.FormattedLine[index]
}
Beispiel #8
0
func GetEditor() *Editor {
	edl.Lock()
	defer edl.Unlock()
	if ed == nil {
		ed = &Editor{
			cmdHandler: commandHandler{
				ApplicationCommands: make(appcmd),
				TextCommands:        make(textcmd),
				WindowCommands:      make(wndcmd),
				verbose:             true,
			},
			frontend: &DummyFrontend{},
			console: &View{
				buffer:  NewBuffer(),
				scratch: true,
			},
			keyInput: make(chan keys.KeyPress, 32),
		}
		var err error
		if ed.Watcher, err = watch.NewWatcher(); err != nil {
			log.Error("Couldn't create watcher: %s", err)
		}
		ed.console.Settings().Set("is_widget", true)
		ed.defaultSettings = new(HasSettings)
		ed.platformSettings = new(HasSettings)
		ed.Settings() // Just to initialize it
		ed.defaultBindings = new(keys.HasKeyBindings)
		ed.platformBindings = new(keys.HasKeyBindings)
		ed.userBindings = new(keys.HasKeyBindings)
		log.AddFilter("console", log.DEBUG, log.NewLogWriter(ed.handleLog))
		go ed.inputthread()
		go ed.Observe()
	}
	return ed
}
Beispiel #9
0
func register(cmds []backend.Command) {
	ch := backend.GetEditor().CommandHandler()
	for _, cmd := range cmds {
		if err := ch.RegisterWithDefault(cmd); err != nil {
			log.Error("Failed to register command: %s", err)
		}
	}
}
Beispiel #10
0
func registerByName(cmds []namedCmd) {
	ch := backend.GetEditor().CommandHandler()
	for _, cmd := range cmds {
		if err := ch.Register(cmd.name, cmd.cmd); err != nil {
			log.Error("Failed to register command %s: %s", cmd.name, err)
		}
	}
}
Beispiel #11
0
func (e *Editor) SetClipboard(n string) {
	if err := e.clipboardSetter(n); err != nil {
		log.Error("Could not set clipboard: %v", err)
	}

	// Keep a local copy in case the system clipboard isn't working
	e.clipboard = n
}
Beispiel #12
0
func (w *Window) runCommand(c WindowCommand, name string) error {
	defer func() {
		if r := recover(); r != nil {
			log.Error("Paniced while running window command %s %v: %v\n%s", name, c, r, string(debug.Stack()))
		}
	}()
	return c.Run(w)
}
Beispiel #13
0
func setColorMode() {
	var (
		mode256 bool
		pal     = make([]termbox.RGB, 0, 256)
	)

	if err := termbox.SetColorMode(termbox.ColorMode256); err != nil {
		log.Error("Unable to use 256 color mode: %s", err)
	} else {
		log.Debug("Using 256 color mode")
		mode256 = true
	}

	if !mode256 {
		pal = pal[:10] // Not correct, but whatever
		pal[termbox.ColorBlack] = termbox.RGB{R: 0, G: 0, B: 0}
		pal[termbox.ColorWhite] = termbox.RGB{R: 255, G: 255, B: 255}
		pal[termbox.ColorRed] = termbox.RGB{R: 255, G: 0, B: 0}
		pal[termbox.ColorGreen] = termbox.RGB{R: 0, G: 255, B: 0}
		pal[termbox.ColorBlue] = termbox.RGB{R: 0, G: 0, B: 255}
		pal[termbox.ColorMagenta] = termbox.RGB{R: 255, G: 0, B: 255}
		pal[termbox.ColorYellow] = termbox.RGB{R: 255, G: 255, B: 0}
		pal[termbox.ColorCyan] = termbox.RGB{R: 0, G: 255, B: 255}

		diff := func(i, j byte) int {
			v := int(i) - int(j)
			if v < 0 {
				return -v
			}
			return v
		}
		palLut = func(col textmate.Color) termbox.Attribute {
			mindist := 10000000
			mini := 0
			for i, c := range pal {
				if dist := diff(c.R, col.R) + diff(c.G, col.G) + diff(c.B, col.B); dist < mindist {
					mindist = dist
					mini = i
				}
			}
			return termbox.Attribute(mini)
		}
	} else {
		palLut = func(col textmate.Color) termbox.Attribute {
			tc := termbox.RGB{R: col.R, G: col.G, B: col.B}
			for i, c := range pal {
				if c == tc {
					return termbox.Attribute(i)
				}
			}
			l := len(pal)
			log.Debug("Adding colour: %d %+v %+v", l, col, tc)
			pal = append(pal, tc)
			termbox.SetColorPalette(pal)
			return termbox.Attribute(l)
		}
	}
}
Beispiel #14
0
func (e *Editor) GetClipboard() string {
	if n, err := e.clipboardGetter(); err == nil {
		return n
	} else {
		log.Error("Could not get clipboard: %v", err)
	}

	return e.clipboard
}
Beispiel #15
0
func (e *Editor) load(pkg *packages.Packet) {
	if err := pkg.Load(); err != nil {
		log.Error("Failed to load packet %s: %s", pkg.Name(), err)
	} else {
		log.Info("Loaded %s", pkg.Name())
		if err := e.Watch(pkg.Name(), pkg); err != nil {
			log.Warn("Couldn't watch %s: %s", pkg.Name(), err)
		}
	}
}
func newPlugin(pl *packages.Plugin, m *py.Module) (p *plugin) {
	p = &plugin{pl, m}
	p.FileChanged(p.Name())
	if err := watcher.Watch(p.Name(), p); err != nil {
		log.Error("Couldn't watch %s: %s", p.Name(), err)
	}
	p.loadKeyBindings()
	p.loadSettings()
	return
}
Beispiel #17
0
// Put back watchers on watching files under the directory
func (w *Watcher) removeDir(name string) {
	for p, _ := range w.watched {
		if filepath.Dir(p) == name {
			if err := w.watch(p); err != nil {
				log.Error("Could not watch: %s", err)
				continue
			}
		}
	}
	w.dirs = remove(w.dirs, name)
}
Beispiel #18
0
// On plugin reload we will scan for plugin files
// and packets in plugin path
func (p *Plugin) Reload() {
	var files []os.FileInfo
	log.Info("Reloading plugin %s", p.Name())
	f, err := os.Open(p.path)
	if err != nil {
		log.Error("Couldn't open dir: %s", err)
		return
	}
	defer f.Close()
	fi, err := f.Readdir(-1)
	if err != nil {
		log.Error("Couldn't read dir: %s", err)
		return
	}
	for _, f := range fi {
		if p.suffix != "" && strings.HasSuffix(f.Name(), p.suffix) {
			files = append(files, f)
		}
	}
	p.files = files
}
Beispiel #19
0
// called when a view is closed
func (t *qmlfrontend) onClose(v *backend.View) {
	w2 := t.windows[v.Window()]
	for i := range w2.views {
		if w2.views[i].bv == v {
			w2.window.ObjectByName("tabs").Call("removeTab", i)
			copy(w2.views[i:], w2.views[i+1:])
			w2.views = w2.views[:len(w2.views)-1]
			return
		}
	}
	log.Error("Couldn't find closed view...")
}
Beispiel #20
0
// Remove watchers created on files under this directory because
// one watcher on the parent directory is enough for all of them
func (w *Watcher) flushDir(name string) {
	if exist(w.dirs, name) {
		return
	}
	w.dirs = append(w.dirs, name)
	for _, p := range w.watchers {
		if filepath.Dir(p) == name && !exist(w.dirs, p) {
			if err := w.removeWatch(p); err != nil {
				log.Error("Couldn't unwatch file %s: %s", p, err)
			}
		}
	}
}
Beispiel #21
0
// Observe dispatches notifications received by the watcher. This function will
// return when the watcher is closed.
func (w *Watcher) Observe() {
	for {
		select {
		case ev, ok := <-w.wchr.Events:
			if !ok {
				break
			}
			func() {
				w.lock.Lock()
				defer w.lock.Unlock()
				w.apply(ev)
				name := ev.Name
				// If the name refers to a directory run all watched
				// callbacks for wathed files under the directory
				if exist(w.dirs, name) {
					for p, _ := range w.watched {
						if filepath.Dir(p) == name {
							ev.Name = p
							w.apply(ev)
						}
					}
				}
				dir := filepath.Dir(name)
				// The watcher will be removed if the file is deleted
				// so we need to watch the parent directory for when the
				// file is created again
				if ev.Op&fsnotify.Remove != 0 {
					w.watchers = remove(w.watchers, name)
					w.lock.Unlock()
					w.Watch(dir, nil)
					w.lock.Lock()
				}
				// We will apply parent directory FileChanged callbacks to,
				// if one of the files inside the directory has changed
				if cbs, exist := w.watched[dir]; ev.Op&fsnotify.Write != 0 && exist {
					for _, cb := range cbs {
						if c, ok := cb.(FileChangedCallback); ok {
							c.FileChanged(dir)
						}
					}
				}

			}()
		case err, ok := <-w.wchr.Errors:
			if !ok {
				break
			}
			log.Error("Watcher error: %s", err)
		}
	}
}
Beispiel #22
0
func (w *Window) remove(v *View) {
	w.lock.Lock()
	defer w.lock.Unlock()
	for i, vv := range w.views {
		if v == vv {
			end := len(w.views) - 1
			if i != end {
				copy(w.views[i:], w.views[i+1:])
			}
			w.views = w.views[:end]
			return
		}
	}
	log.Error("Wanted to remove view %+v, but it doesn't appear to be a child of this window", v)
}
func (c *CommandGlue) callBool(name string, args backend.Args) bool {
	gs := py.GilState_Ensure()
	defer gs.Release()

	var (
		pyargs, r py.Object
		err       error
	)
	if pyargs, err = c.CreatePyArgs(args); err != nil {
		log.Error(err)
		return false
	}
	defer pyargs.Decref()

	if r, err = c.CallMethodObjArgs(name, pyargs); err != nil {
		log.Error(err)
		return true
	}
	defer r.Decref()
	if r, ok := r.(*py.Bool); ok {
		return r.Bool()
	}
	return true
}
func (c *CommandGlue) Description() string {
	gs := py.GilState_Ensure()
	defer gs.Release()

	var (
		pyargs, r py.Object
		err       error
	)
	if pyargs, err = c.CreatePyArgs(c.args); err != nil {
		log.Error(err)
		return ""
	}
	defer pyargs.Decref()

	if r, err = c.CallMethodObjArgs("description", pyargs); err != nil {
		log.Error(err)
		return ""
	}
	defer r.Decref()
	if r, ok := r.(*py.Unicode); ok {
		return r.String()
	}
	return ""
}
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()
	}
}
Beispiel #26
0
func (e *Editor) remove(w *Window) {
	edl.Lock()
	defer edl.Unlock()
	for i, ww := range e.windows {
		if w == ww {
			end := len(e.windows) - 1
			if i != end {
				copy(e.windows[i:], e.windows[i+1:])
			}
			e.windows = e.windows[:end]
			return
		}
	}
	log.Error("Wanted to remove window %+v, but it doesn't appear to be a child of this editor", w)
}
Beispiel #27
0
func (v *View) runCommand(cmd TextCommand, name string) error {
	e := v.BeginEdit()
	e.command = name
	//	e.args = args
	e.bypassUndo = cmd.BypassUndo()

	defer func() {
		v.EndEdit(e)
		if r := recover(); r != nil {
			log.Error("Paniced while running text command %s %v: %v\n%s", name, cmd, r, string(debug.Stack()))
		}
	}()
	p := Prof.Enter("view.cmd." + name)
	defer p.Exit()
	return cmd.Run(v, e)
}
Beispiel #28
0
// Returns packet file data if any error occurred
// on reading file we will return nil
func (p *Packet) Get() interface{} {
	e := []byte(`{}`)
	if p.group() == "keymap" {
		e = []byte(`[]`)
	}

	if _, err := os.Stat(p.path); os.IsNotExist(err) {
		log.Finest("%s doesn't exist yet", p.path)
		return e
	}

	d, err := ioutil.ReadFile(p.path)
	if err != nil {
		log.Error("Couldn't read file: %s", err)
		return e
	}
	return d
}
Beispiel #29
0
func (v *View) FileChanged(filename string) {
	log.Finest("Reloading %s", filename)

	if saving, ok := v.Settings().Get("lime.saving", false).(bool); ok && saving {
		// This reload was triggered by ourselves saving to this file, so don't reload it
		return
	}
	if !GetEditor().Frontend().OkCancelDialog("File was changed by another program, reload?", "reload") {
		return
	}

	if d, err := ioutil.ReadFile(filename); err != nil {
		log.Error("Could not read file: %s\n. Error was: %v", filename, err)
	} else {
		edit := v.BeginEdit()
		end := v.buffer.Size()
		v.Replace(edit, Region{0, end}, string(d))
		v.EndEdit(edit)
	}
}
Beispiel #30
0
func (v *View) Find(pat string, pos int, flags int) Region {
	r := Region{pos, v.buffer.Size()}
	s := v.buffer.Substr(r)

	if flags&LITERAL != 0 {
		pat = "\\Q" + pat
	}
	if flags&IGNORECASE != 0 {
		pat = "(?im)" + pat
	} else {
		pat = "(?m)" + pat
	}
	// Using regexp instead of rubex because rubex doesn't
	// support flag for treating pattern as a literal text
	if re, err := regexp.Compile(pat); err != nil {
		log.Error(err)
	} else if loc := re.FindStringIndex(s); loc != nil {
		return Region{pos + loc[0], pos + loc[1]}
	}
	return Region{-1, -1}
}