Beispiel #1
0
// TODO
func Init() {
	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)
	}

	plugins := packages.ScanPlugins(backend.LIME_USER_PACKAGES_PATH, ".py")
	for _, p := range plugins {
		// TODO: add all plugins after supporting all commands
		if p.Name() == path.Join("..", "..", "3rdparty", "bundles", "Vintageous") {
			pl := newPlugin(p, m)
			pl.reload()
			if err := watcher.Watch(pl.Name(), pl); err != nil {
				log.Error("Couldn't watch %s: %s", pl.Name(), err)
			}
		}
	}

	go watcher.Observe()
}
Beispiel #2
0
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
// 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/Python/Python (Windows).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, platSettings := &HasSettings{}, &HasSettings{}, &HasSettings{}

	defSettings.Settings().SetParent(v.window)
	platSettings.Settings().SetParent(defSettings)
	usrSettings.Settings().SetParent(platSettings)
	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_PACKAGES_PATH, s[1], s[1]+" ("+ed.Plat()+").sublime-settings")
		ed.load(packages.NewPacket(p, platSettings.Settings()))

		p = path.Join(LIME_USER_PACKAGES_PATH, s[1]+".sublime-settings")
		ed.load(packages.NewPacket(p, usrSettings.Settings()))
	}
}
Beispiel #4
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.Settings() // Just to initialize it
		log.AddFilter("console", log.DEBUG, log.NewLogWriter(ed.handleLog))
		go ed.inputthread()
		go ed.Observe()
	}
	return ed
}
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{0, 0})
	v.buffer.Settings().Set("lime.last_save_change_count", v.buffer.ChangeCount())
	v.SetScratch(false)

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

	return v
}
Beispiel #6
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 #7
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 #8
0
func (e *Editor) loadSetting(pkg *packages.Packet) {
	if err := pkg.Load(); err != nil {
		log.Error(err)
	} else {
		log.Info("Loaded %s", pkg.Name())
		e.Watch(pkg.Name(), pkg)
	}
}
Beispiel #9
0
// Returns packet file data if any error occurred
// on reading file we will return nil
func (p *Packet) Get() interface{} {
	d, err := ioutil.ReadFile(p.path)
	if err != nil {
		log.Error("Couldn't read file: %s", err)
		return []byte{}
	}
	return d
}
Beispiel #10
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 #11
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 #12
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{0, 0, 0}
		pal[termbox.ColorWhite] = termbox.RGB{255, 255, 255}
		pal[termbox.ColorRed] = termbox.RGB{255, 0, 0}
		pal[termbox.ColorGreen] = termbox.RGB{0, 255, 0}
		pal[termbox.ColorBlue] = termbox.RGB{0, 0, 255}
		pal[termbox.ColorMagenta] = termbox.RGB{255, 0, 255}
		pal[termbox.ColorYellow] = termbox.RGB{255, 255, 0}
		pal[termbox.ColorCyan] = termbox.RGB{0, 255, 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{col.R, col.G, 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 #13
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 #14
0
func (e *Editor) loadKeyBinding(pkg *packages.Packet) {
	if err := pkg.Load(); err != nil {
		log.Error(err)
	} else {
		log.Info("Loaded %s", pkg.Name())
		e.Watch(pkg.Name(), pkg)
	}
	e.keyBindings.Merge(pkg.MarshalTo().(*keys.KeyBindings))
}
Beispiel #15
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 #16
0
// Initialize scan for loading user and limetext defaults
// except settings because for settings we have a hierarchy
// i.e commands, snippets etc
func ScanPackets(path string) Packets {
	var packets Packets
	walkFn := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			log.Error("Error on walking: %s", err)
			return err
		}
		s := filepath.Ext(info.Name())
		for _, t := range types {
			if t != "settings" && strings.Contains(s, t) {
				packets = append(packets, NewPacket(path, new(keys.KeyBindings)))
			}
		}
		return nil
	}
	if err := filepath.Walk(path, walkFn); err != nil {
		log.Error("Can't walk: %s", err)
	}
	return packets
}
Beispiel #17
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 #18
0
// On plugin reload we will scan for plugin files
// and packets in plugin path
func (p *Plugin) Reload() {
	var (
		files []os.FileInfo
		pckts Packets
	)
	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)
			continue
		}
		s := filepath.Ext(f.Name())
		for _, t := range types {
			if !strings.Contains(s, t) {
				continue
			}
			var pckt *Packet
			if t == "keymap" {
				pckt = NewPacket(pt.Join(p.path, f.Name()), new(keys.KeyBindings))
			} else {
				// We don't have any settings hierarchy for plugins at this moment
				pckt = NewPacket(pt.Join(p.path, f.Name()), p.Settings())
			}
			pckts = append(pckts, pckt)
		}
	}
	p.files = files
	p.packets = pckts
}
Beispiel #19
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 {
			if err := w.removeWatch(p); err != nil {
				log.Error("Couldn't unwatch file %s: %s", p, err)
			}
		}
	}
}
Beispiel #20
0
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
}
Beispiel #21
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()
	}
}
Beispiel #22
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 #23
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)
}
Beispiel #24
0
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 ""
}
Beispiel #25
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 #26
0
func (lp *LanguageParser) Parse() (*parser.Node, error) {
	sdata := string(lp.data)
	rn := parser.Node{P: lp, Name: lp.l.ScopeName}
	defer func() {
		if r := recover(); r != nil {
			log.Error("Panic during parse: %v\n", r)
			log.Debug("%v", rn)
		}
	}()
	iter := maxiter
	for i := 0; i < len(sdata) && iter > 0; iter-- {
		pat, ret := lp.l.RootPattern.Cache(sdata, i)
		nl := strings.IndexAny(sdata[i:], "\n\r")
		if nl != -1 {
			nl += i
		}
		if ret == nil {
			break
		} else if nl > 0 && nl <= ret[0] {
			i = nl
			for i < len(sdata) && (sdata[i] == '\n' || sdata[i] == '\r') {
				i++
			}
		} else {
			n := pat.CreateNode(sdata, i, lp, ret)
			rn.Append(n)

			i = n.Range.B
		}
	}
	rn.UpdateRange()
	if len(sdata) != 0 {
		lut := make([]int, len(sdata)+1)
		j := 0
		for i := range sdata {
			lut[i] = j
			j++
		}
		lut[len(sdata)] = len(lp.data)
		lp.patch(lut, &rn)
	}
	if iter == 0 {
		panic("reached maximum number of iterations")
	}
	return &rn, nil
}
Beispiel #27
0
func (w *Watcher) Observe() {
	for {
		select {
		case ev := <-w.wchr.Events:
			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 := <-w.wchr.Errors:
			log.Error("Watcher error: %s", err)
		}
	}
}
Beispiel #28
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 #29
0
// Creates and initializes the frontend.
func createFrontend() *tbfe {
	var t tbfe
	t.dorender = make(chan bool, render_chan_len)
	t.shutdown = make(chan bool, 2)
	t.layout = make(map[*backend.View]layout)

	t.editor = t.setupEditor()
	t.console = t.editor.Console()
	t.currentWindow = t.editor.NewWindow()

	// Assuming that all extra arguments are files
	if files := flag.Args(); len(files) > 0 {
		for _, file := range files {
			t.currentView = createNewView(file, t.currentWindow)
		}
	} else {
		t.currentView = t.currentWindow.NewFile()
	}

	t.console.Buffer().AddCallback(t.scroll)
	t.setupCallbacks(t.currentView)

	path := path.Join("..", "..", "3rdparty", "bundles", "TextMate-Themes", "Monokai.tmTheme")
	if sc, err := textmate.LoadTheme(path); err != nil {
		log.Error(err)
	} else {
		scheme = sc
	}

	setColorMode()
	setSchemeSettings()

	w, h := termbox.Size()
	t.handleResize(h, w, true)

	// These might take a while
	t.editor.Init()
	go sublime.Init()

	return &t
}
Beispiel #30
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))
		l := make([]layout, 0, len(t.layout))
		for k, v := range t.layout {
			vs = append(vs, k)
			l = append(l, v)
		}
		runes := []rune(t.status_message)
		t.lock.Unlock()

		w, h := termbox.Size()
		for i := 0; i < w && i < len(runes); i++ {
			termbox.SetCell(i, h-2, runes[i], defaultFg, defaultBg)
		}

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

		termbox.Flush()
	}

	for _ = range t.dorender {
		log.Finest("Rendering")
		dorender()
	}
}