func sublime_RunCommand(tu *py.Tuple) (py.Object, error) {
	var (
		arg1 string
		arg2 backend.Args
	)
	if v, err := tu.GetItem(0); err != nil {
		return nil, err
	} else {
		if v3, err2 := fromPython(v); err2 != nil {
			return nil, err2
		} else {
			if v2, ok := v3.(string); !ok {
				return nil, fmt.Errorf("Expected type string for backend.Editor.RunCommand() arg1, not %s", v.Type())
			} else {
				arg1 = v2
			}
		}
	}
	arg2 = make(backend.Args)
	if v, err := tu.GetItem(1); err == nil {
		if v3, err2 := fromPython(v); err2 != nil {
			return nil, err2
		} else {
			if v2, ok := v3.(backend.Args); !ok {
				return nil, fmt.Errorf("Expected type backend.Args for backend.Editor.RunCommand() arg2, not %s", v.Type())
			} else {
				arg2 = v2
			}
		}
	}
	backend.GetEditor().RunCommand(arg1, arg2)
	return toPython(nil)
}
Beispiel #2
0
func (o *View) Py_run_command(tu *py.Tuple) (py.Object, error) {
	var (
		arg1 string
		arg2 backend.Args
	)
	v, err := tu.GetItem(0)
	if err != nil {
		return nil, err
	}
	if v2, ok := v.(*py.Unicode); !ok {
		return nil, fmt.Errorf("Expected type *py.Unicode for backend.View.RunCommand() arg1, not %s", v.Type())
	} else {
		arg1 = v2.String()
	}
	arg2 = make(backend.Args)
	if v, err := tu.GetItem(1); err == nil {
		v2, ok := v.(*py.Dict)
		if !ok {
			return nil, fmt.Errorf("Expected type *py.Dict for backend.View.RunCommand() arg2, not %s", v.Type())
		}
		if v, err := fromPython(v2); err != nil {
			return nil, err
		} else {
			arg2 = v.(backend.Args)
		}
	}
	backend.GetEditor().CommandHandler().RunTextCommand(o.data, arg1, arg2)
	return toPython(nil)
}
Beispiel #3
0
// key HandleFunc for the http /key endpoint. This only happens if the client
// doesn't support websockets.
func (t *tbfe) key(w http.ResponseWriter, req *http.Request) {
	log.Debug("key: %s", req)
	kc := req.FormValue("keyCode")
	var kp keys.KeyPress
	v, _ := strconv.ParseInt(kc, 10, 32)

	if req.FormValue("altKey") == "true" {
		kp.Alt = true
	}
	if req.FormValue("ctrlKey") == "true" {
		kp.Ctrl = true
	}
	if req.FormValue("metaKey") == "true" {
		kp.Super = true
	}
	if req.FormValue("shiftKey") == "true" {
		kp.Shift = true
	}

	if !kp.Shift {
		v = int64(unicode.ToLower(rune(v)))
	}
	kp.Key = keys.Key(v)
	kp.Text = string(v)
	backend.GetEditor().HandleInput(kp)
}
Beispiel #4
0
func sublime_OkCancelDialog(tu *py.Tuple) (py.Object, error) {
	var (
		arg1 string
		arg2 string
	)
	if v, err := tu.GetItem(0); err != nil {
		return nil, err
	} else {
		if v3, err2 := fromPython(v); err2 != nil {
			return nil, err2
		} else {
			if v2, ok := v3.(string); !ok {
				return nil, fmt.Errorf("Expected type string for backend.DummyFrontend.OkCancelDialog() arg1, not %s", v.Type())
			} else {
				arg1 = v2
			}
		}
	}
	if v, err := tu.GetItem(1); err != nil {
		return nil, err
	} else {
		if v3, err2 := fromPython(v); err2 != nil {
			return nil, err2
		} else {
			if v2, ok := v3.(string); !ok {
				return nil, fmt.Errorf("Expected type string for backend.DummyFrontend.OkCancelDialog() arg2, not %s", v.Type())
			} else {
				arg2 = v2
			}
		}
	}
	backend.GetEditor().Frontend().OkCancelDialog(arg1, arg2)
	return toPython(nil)
}
Beispiel #5
0
func register(cmds []cmd) {
	e := backend.GetEditor()
	for i := range cmds {
		if err := e.CommandHandler().Register(cmds[i].name, cmds[i].cmd); err != nil {
			log4go.Error("Failed to register command %s: %s", cmds[i].name, err)
		}
	}
}
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 (t *tbfe) setupEditor() *backend.Editor {
	ed := backend.GetEditor()
	ed.SetFrontend(t)
	ed.LogInput(false)
	ed.LogCommands(false)

	return ed
}
Beispiel #8
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)
		}
	}
}
func sublime_PackagesPath() (py.Object, error) {
	ret0 := backend.GetEditor().PackagesPath()
	var err error
	var pyret0 py.Object

	pyret0, err = toPython(ret0)
	if err != nil {
		return nil, err
	}
	return pyret0, err
}
func sublime_NewWindow() (py.Object, error) {
	ret0 := backend.GetEditor().NewWindow()
	var err error
	var pyret0 py.Object

	pyret0, err = toPython(ret0)
	if err != nil {
		return nil, err
	}
	return pyret0, err
}
Beispiel #11
0
func (p *plugin) loadKeyBindings() {
	ed := backend.GetEditor()
	tmp := ed.KeyBindings().Parent()

	ed.KeyBindings().SetParent(p)
	p.KeyBindings().Parent().KeyBindings().SetParent(tmp)

	pt := path.Join(p.Name(), "Default.sublime-keymap")
	p.load(packages.NewPacket(pt, p.KeyBindings().Parent().KeyBindings()))

	pt = path.Join(p.Name(), "Default ("+ed.Plat()+").sublime-keymap")
	p.load(packages.NewPacket(pt, p.KeyBindings()))
}
Beispiel #12
0
func (p *plugin) loadSettings() {
	ed := backend.GetEditor()
	tmp := ed.Settings().Parent()

	ed.Settings().SetParent(p)
	p.Settings().Parent().Settings().Parent().Settings().SetParent(tmp)

	pt := path.Join(p.Name(), "Preferences.sublime-settings")
	p.load(packages.NewPacket(pt, p.Settings().Parent().Settings().Parent().Settings()))

	pt = path.Join(p.Name(), "Preferences ("+ed.Plat()+").sublime-settings")
	p.load(packages.NewPacket(pt, p.Settings().Parent().Settings()))

	pt = path.Join(backend.LIME_USER_PACKAGES_PATH, "Preferences.sublime-settings")
	p.load(packages.NewPacket(pt, p.Settings()))
}
Beispiel #13
0
func (o *View) Py_visible_region() (py.Object, error) {
	ret0 := backend.GetEditor().Frontend().VisibleRegion(o.data)
	var err error
	var pyret0 py.Object

	pyret0, err = _regionClass.Alloc(1)
	if err != nil {
		return nil, err
	} else if v2, ok := pyret0.(*Region); !ok {
		return nil, fmt.Errorf("Unable to convert return value to the right type?!: %s", pyret0.Type())
	} else {
		v2.data = ret0
	}
	if err != nil {
		return nil, err
	}
	return pyret0, err
}
func sublime_SetClipboard(tu *py.Tuple) (py.Object, error) {
	var (
		arg1 string
	)
	if v, err := tu.GetItem(0); err != nil {
		return nil, err
	} else {
		if v3, err2 := fromPython(v); err2 != nil {
			return nil, err2
		} else {
			if v2, ok := v3.(string); !ok {
				return nil, fmt.Errorf("Expected type string for backend.Editor.SetClipboard() arg1, not %s", v.Type())
			} else {
				arg1 = v2
			}
		}
	}
	backend.GetEditor().SetClipboard(arg1)
	return toPython(nil)
}
Beispiel #15
0
func TestUpdateVisibleRegion(t *testing.T) {
	var (
		fe tbfe
		e  = backend.GetEditor()
		w  = e.NewWindow()
		v  = w.NewFile()
	)

	fe.layout = make(map[*backend.View]layout)
	fe.layout[v] = layout{0, 0, 100, 100 - *consoleHeight - 1, Region{}, 0}
	fe.setupCallbacks(v)

	edit := v.BeginEdit()
	v.Insert(edit, 0, "foo")
	v.EndEdit(edit)

	if end := fe.layout[v].visible.End(); end != 3 {
		t.Fatalf("Expected 3, got %d", end)
	}
}
func sublime_LogInput(tu *py.Tuple) (py.Object, error) {
	var (
		arg1 bool
	)
	if v, err := tu.GetItem(0); err != nil {
		return nil, err
	} else {
		if v3, err2 := fromPython(v); err2 != nil {
			return nil, err2
		} else {
			if v2, ok := v3.(bool); !ok {
				return nil, fmt.Errorf("Expected type bool for backend.Editor.LogInput() arg1, not %s", v.Type())
			} else {
				arg1 = v2
			}
		}
	}
	backend.GetEditor().LogInput(arg1)
	return toPython(nil)
}
Beispiel #17
0
func (view *View) Py_show(tu *py.Tuple, kw *py.Dict) (py.Object, error) {
	var (
		arg1 text.Region
	)
	v, err := tu.GetItem(0)
	if err != nil {
		return nil, err
	}
	if v2, ok := v.(*Region); !ok {
		if v2, ok := v.(*py.Long); !ok {
			return nil, fmt.Errorf("Expected type *Region or *Int for primitives.Buffer.Substr() arg1, not %s", v.Type())
		} else {
			arg1.A = int(v2.Int64())
			arg1.B = arg1.A + 1
		}
	} else {
		arg1 = v2.data
	}
	backend.GetEditor().Frontend().Show(view.data, arg1)
	return toPython(nil)
}
Beispiel #18
0
func sublime_Unregister(tu *py.Tuple) (py.Object, error) {
	var (
		arg1 string
	)
	if v, err := tu.GetItem(0); err != nil {
		return nil, err
	} else {
		if v3, err2 := fromPython(v); err2 != nil {
			return nil, err2
		} else {
			if v2, ok := v3.(string); !ok {
				return nil, fmt.Errorf("Expected type string for backend.commandHandler.Unregister() arg1, not %s", v.Type())
			} else {
				arg1 = v2
			}
		}
	}
	if err := backend.GetEditor().CommandHandler().Unregister(arg1); err != nil {
		return nil, err
	} else {
		return toPython(nil)
	}
}
Beispiel #19
0
func (t *qmlfrontend) HandleInput(keycode int, modifiers int) bool {
	log4go.Debug("qmlfrontend.HandleInput: key=%x, modifiers=%x", keycode, modifiers)
	shift := false
	alt := false
	ctrl := false
	super := false

	if key, ok := lut[keycode]; ok {
		ed := backend.GetEditor()

		if (modifiers & shift_mod) != 0 {
			shift = true
		}
		if (modifiers & alt_mod) != 0 {
			alt = true
		}
		if (modifiers & ctrl_mod) != 0 {
			if runtime.GOOS == "darwin" {
				super = true
			} else {
				ctrl = true
			}
		}
		if (modifiers & meta_mod) != 0 {
			if runtime.GOOS == "darwin" {
				ctrl = true
			} else {
				super = true
			}
		}

		ed.HandleInput(backend.KeyPress{Key: key, Shift: shift, Alt: alt, Ctrl: ctrl, Super: super})
		return true
	}
	return false
}
Beispiel #20
0
func (t *qmlfrontend) RunCommandWithArgs(command string, args backend.Args) {
	ed := backend.GetEditor()
	go ed.RunCommand(command, args)
}
Beispiel #21
0
func (t *tbfe) loop() {
	backend.OnNew.Add(func(v *backend.View) {
		v.Settings().AddOnChange("lime.frontend.html.render", func(name string) { t.dirty = true })
	})
	backend.OnModified.Add(func(v *backend.View) {
		t.dirty = true
	})
	backend.OnSelectionModified.Add(func(v *backend.View) {
		t.dirty = true
	})

	ed := backend.GetEditor()
	ed.SetFrontend(t)
	ed.LogInput(false)
	ed.LogCommands(false)
	c := ed.Console()
	if sc, err := textmate.LoadTheme("../../3rdparty/bundles/TextMate-Themes/GlitterBomb.tmTheme"); err != nil {
		log4go.Error(err)
	} else {
		scheme = sc
	}

	defer func() {
		fmt.Println(util.Prof)
	}()

	w := ed.NewWindow()
	v := w.OpenFile("main.go", 0)
	v.Settings().Set("trace", true)
	v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage")
	c.Buffer().AddCallback(t.scroll)

	sel := v.Sel()
	sel.Clear()
	//	end := v.Buffer().Size() - 2
	sel.Add(Region{0, 0})
	// sel.Add(Region{end - 22, end - 22})
	// sel.Add(Region{end - 16, end - 20})
	// sel.Add(Region{end - 13, end - 10})

	{
		w, h := 800, 600
		t.lock.Lock()
		t.layout[v] = layout{0, 0, w, h - console_height - 1, Region{}, 0}
		t.layout[c] = layout{0, h - console_height + 1, w, console_height - 5, Region{}, 0}
		t.lock.Unlock()
		t.Show(v, Region{1, 1})
	}
	t.Show(v, Region{100, 100})
	t.Show(v, Region{1, 1})

	go func() {
		ed.Init()
		sublime.Init()
	}()
	log4go.Debug("serving")
	http.HandleFunc("/key", t.key)
	http.HandleFunc("/", t.ServeHTTP)
	http.HandleFunc("/view", t.view)
	if err := http.ListenAndServe("localhost:8080", nil); err != nil {
		log4go.Error("Error serving: %s", err)
	}
	log4go.Debug("Done")
}
Beispiel #22
0
func (t *tbfe) scroll(b Buffer, pos, delta int) {
	t.Show(backend.GetEditor().Console(), Region{b.Size(), b.Size()})
}
Beispiel #23
0
func TestSublime(t *testing.T) {
	ed := backend.GetEditor()
	ed.Console().Buffer().AddCallback(func(b text.Buffer, pos, delta int) {
		t.Logf("%s", b.Substr(text.Region{pos, pos + delta}))
	})
	w := ed.NewWindow()
	Init()
	l := py.NewLock()
	py.AddToPath("testdata")
	py.AddToPath("testdata/plugins")
	if m, err := py.Import("sublime_plugin"); err != nil {
		t.Fatal(err)
	} else {
		scanpath("testdata/", m)
	}

	subl, err := py.Import("sublime")
	if err != nil {
		t.Fatal(err)
	}

	if w, err := _windowClass.Alloc(1); err != nil {
		t.Fatal(err)
	} else {
		(w.(*Window)).data = &backend.Window{}
		subl.AddObject("test_window", w)
	}

	if dir, err := os.Open("testdata"); err != nil {
		t.Error(err)
	} else if files, err := dir.Readdirnames(0); err != nil {
		t.Error(err)
	} else {
		for _, fn := range files {
			if filepath.Ext(fn) == ".py" {
				log4go.Debug("Running %s", fn)
				if _, err := py.Import(fn[:len(fn)-3]); err != nil {
					log4go.Error(err)
					t.Error(err)
				} else {
					log4go.Debug("Ran %s", fn)
				}
			}
		}
	}

	var f func(indent string, v py.Object, buf *bytes.Buffer)
	f = func(indent string, v py.Object, buf *bytes.Buffer) {
		b := v.Base()
		if dir, err := b.Dir(); err != nil {
			t.Error(err)
		} else {
			if l, ok := dir.(*py.List); ok {
				sl := l.Slice()

				if indent == "" {
					for _, v2 := range sl {
						if item, err := b.GetAttr(v2); err != nil {
							t.Error(err)
						} else {
							ty := item.Type()
							line := fmt.Sprintf("%s%s\n", indent, v2)
							buf.WriteString(line)
							if ty == py.TypeType {
								f(indent+"\t", item, buf)
							}
							item.Decref()
						}
					}
				} else {
					for _, v2 := range sl {
						buf.WriteString(fmt.Sprintf("%s%s\n", indent, v2))
					}
				}

			} else {
				ty := dir.Type()
				t.Error("Unexpected type:", ty)
			}
			dir.Decref()
		}
	}
	buf := bytes.NewBuffer(nil)
	f("", subl, buf)

	l.Unlock()

	const expfile = "testdata/api.txt"
	if d, err := ioutil.ReadFile(expfile); err != nil {
		if err := ioutil.WriteFile(expfile, buf.Bytes(), 0644); err != nil {
			t.Error(err)
		}
	} else if diff := util.Diff(string(d), buf.String()); diff != "" {
		t.Error(diff)
	}
	ed.LogCommands(true)
	tests := []string{
		"state",
		"registers",
		"settings",
		"constants",
		"registers",
		"cmd_data",
		"marks",
	}

	for _, test := range tests {
		ed.CommandHandler().RunWindowCommand(w, "vintage_ex_run_data_file_based_tests", backend.Args{"suite_name": test})
	}
	for _, w := range ed.Windows() {
		for _, v := range w.Views() {
			if strings.HasSuffix(v.Buffer().FileName(), "sample.txt") {
				continue
			}
			if strings.Index(v.Buffer().Substr(text.Region{0, v.Buffer().Size()}), "FAILED") != -1 {
				t.Error(v.Buffer())
			}
		}
	}

	var v *backend.View
	for _, v2 := range w.Views() {
		if v == nil || v2.Buffer().Size() > v.Buffer().Size() {
			v = v2
		}
	}
}
Beispiel #24
0
func (t *qmlfrontend) scroll(b Buffer) {
	t.Show(backend.GetEditor().Console(), Region{b.Size(), b.Size()})
}
Beispiel #25
0
func (t *qmlfrontend) loop() (err error) {
	backend.OnNew.Add(t.onNew)
	backend.OnClose.Add(t.onClose)
	backend.OnLoad.Add(t.onLoad)

	ed := backend.GetEditor()
	ed.Init()
	go sublime.Init()
	ed.SetFrontend(t)
	ed.LogInput(false)
	ed.LogCommands(false)
	c := ed.Console()
	t.Console = &frontendView{bv: c}
	c.Buffer().AddObserver(t.Console)
	c.Buffer().AddObserver(t)

	var (
		engine    *qml.Engine
		component qml.Object
		// WaitGroup keeping track of open windows
		wg sync.WaitGroup
	)

	// create and setup a new engine, destroying
	// the old one if one exists.
	//
	// This is needed to re-load qml files to get
	// the new file contents from disc as otherwise
	// the old file would still be what is referenced.
	newEngine := func() (err error) {
		if engine != nil {
			log.Debug("calling destroy")
			// TODO(.): calling this appears to make the editor *very* crash-prone, just let it leak for now
			// engine.Destroy()
			engine = nil
		}
		log.Debug("calling newEngine")
		engine = qml.NewEngine()
		log.Debug("setvar frontend")
		engine.Context().SetVar("frontend", t)
		log.Debug("setvar editor")
		engine.Context().SetVar("editor", backend.GetEditor())

		log.Debug("loadfile")
		component, err = engine.LoadFile(qmlMainFile)
		if err != nil {
			return err
		}
		limeViewComponent, err = engine.LoadFile(qmlViewFile)
		return
	}
	if err := newEngine(); err != nil {
		log.Error(err)
	}

	backend.OnNewWindow.Add(func(w *backend.Window) {
		fw := &frontendWindow{bw: w}
		t.windows[w] = fw
		if component != nil {
			fw.launch(&wg, component)
		}
	})

	// TODO: should be done backend side
	if sc, err := textmate.LoadTheme("../../packages/themes/TextMate-Themes/Monokai.tmTheme"); err != nil {
		log.Error(err)
	} else {
		scheme = sc
	}

	defer func() {
		fmt.Println(util.Prof)
	}()

	w := ed.NewWindow()
	v := w.OpenFile("main.go", 0)
	// TODO: should be done backend side
	v.Settings().Set("syntax", "../../packages/go.tmbundle/Syntaxes/Go.tmLanguage")
	v = w.OpenFile("../../backend/editor.go", 0)
	// TODO: should be done backend side
	v.Settings().Set("syntax", "../../packages/go.tmbundle/Syntaxes/Go.tmLanguage")

	watch, err := fsnotify.NewWatcher()
	if err != nil {
		log.Errorf("Unable to create file watcher: %s", err)
		return
	}
	defer watch.Close()
	watch.Watch(".")
	defer watch.RemoveWatch(".")

	reloadRequested := false

	go func() {
		for {
			select {
			case ev := <-watch.Event:
				if ev != nil && strings.HasSuffix(ev.Name, ".qml") && ev.IsModify() && !ev.IsAttrib() {
					reloadRequested = true
					// Close all open windows to de-reference all
					// qml objects
					for _, v := range t.windows {
						if v.window != nil {
							v.window.Hide()
							v.window.Destroy()
							v.window = nil
						}
					}
				}
			}
		}
	}()

	for {
		// Reset reload status
		reloadRequested = false

		log.Debug("Waiting for all windows to close")
		// wg would be the WaitGroup all windows belong to, so first we wait for
		// all windows to close.
		wg.Wait()
		log.Debug("All windows closed. reloadRequest: %v", reloadRequested)
		// then we check if there's a reload request in the pipe
		if !reloadRequested || len(t.windows) == 0 {
			// This would be a genuine exit; all windows closed by the user
			break
		}

		// *We* closed all windows because we want to reload freshly changed qml
		// files.
		for {
			log.Debug("Calling newEngine")
			if err := newEngine(); err != nil {
				// Reset reload status
				reloadRequested = false
				log.Error(err)
				for !reloadRequested {
					// This loop allows us to re-try reloading
					// if there was an error in the file this time,
					// we just loop around again when we receive the next
					// reload request (ie on the next save of the file).
					time.Sleep(time.Second)
				}
				continue
			}
			log.Debug("break")
			break
		}
		log.Debug("re-launching all windows")
		// Succeeded loading the file, re-launch all windows
		for _, v := range t.windows {
			v.launch(&wg, component)
		}
	}
	return
}
Beispiel #26
0
func main() {
	cleanup()
	var sublime_methods = ""
	sn := func(t reflect.Type, m reflect.Method) string {
		sn := "sublime_" + m.Name
		sublime_methods += fmt.Sprintf("{Name: \"%s\", Func: %s},\n", pyname(m.Name)[1:], sn)
		return sn
	}
	data := [][]string{
		{"../backend/sublime/region_generated.go", generateWrapper(reflect.TypeOf(text.Region{}), true, regexp.MustCompile("Cut").MatchString)},
		{"../backend/sublime/regionset_generated.go", generateWrapper(reflect.TypeOf(&text.RegionSet{}), false, regexp.MustCompile("Less|Swap|Adjust|Has|Cut").MatchString)},
		{"../backend/sublime/edit_generated.go", generateWrapper(reflect.TypeOf(&backend.Edit{}), false, regexp.MustCompile("Apply|Undo").MatchString)},
		{"../backend/sublime/view_generated.go", generateWrapper(reflect.TypeOf(&backend.View{}), false, regexp.MustCompile("Buffer|Syntax|CommandHistory|Show|AddRegions|UndoStack|Transform").MatchString)},
		{"../backend/sublime/window_generated.go", generateWrapper(reflect.TypeOf(&backend.Window{}), false, regexp.MustCompile("OpenFile|SetActiveView").MatchString)},
		{"../backend/sublime/settings_generated.go", generateWrapper(reflect.TypeOf(&text.Settings{}), false, regexp.MustCompile("Parent|Set|Get|UnmarshalJSON|MarshalJSON").MatchString)},
		{"../backend/sublime/view_buffer_generated.go", generatemethodsEx(
			reflect.TypeOf(backend.GetEditor().Console().Buffer()),
			regexp.MustCompile("Erase|Insert|Substr|SetFile|AddCallback|Data|Runes|Settings|Index|Close|Unlock|Lock").MatchString,
			"o.data.Buffer().",
			func(t reflect.Type, m reflect.Method) string {
				mn := ""
				switch m.Name {
				case "Line", "LineR", "FullLine", "FullLineR", "WordR", "Word":
					mn = strings.ToLower(m.Name)
				case "Id":
					mn = "Py_buffer_id"
				default:
					mn = "Py" + pyname(m.Name)
				}
				return "(o *View) " + mn
			})},
		{"../backend/sublime/commands_generated.go", generatemethodsEx(reflect.TypeOf(backend.GetEditor().CommandHandler()),
			regexp.MustCompile("RunWindowCommand|RunTextCommand|RunApplicationCommand").MatchString,
			"backend.GetEditor().CommandHandler().",
			sn),
		},
		{"../backend/sublime/frontend_generated.go", generatemethodsEx(reflect.TypeOf(backend.GetEditor().Frontend()),
			regexp.MustCompile("Show|VisibleRegion").MatchString,
			"backend.GetEditor().Frontend().",
			sn),
		},
		{"../backend/sublime/sublime_api_generated.go", generatemethodsEx(reflect.TypeOf(backend.GetEditor()),
			regexp.MustCompile("Info|HandleInput|CommandHandler|Windows|Frontend|Console|SetActiveWindow|Init|Watch|Watcher").MatchString,
			"backend.GetEditor().",
			sn),
		},
	}
	data[len(data)-1][1] += fmt.Sprintf(`var sublime_methods = []py.Method{
		%s
	}`, sublime_methods)
	for _, gen := range data {
		if gen[0] == "" {
			continue
		}
		wr := `// This file was generated as part of a build step and shouldn't be manually modified
			package sublime

			import (
				"fmt"
				"lime/3rdparty/libs/gopy/lib"
				"lime/backend"
				"github.com/quarnster/util/text"
			)
			var (
				_ = backend.View{}
				_ = text.Region{}
				_ = fmt.Errorf
			)
			` + gen[1]
		if err := ioutil.WriteFile(gen[0], []byte(wr), 0644); err != nil {
			panic(err)
		} else {
			c := exec.Command("go", "fmt", gen[0])
			if o, err := c.CombinedOutput(); err != nil {
				panic(fmt.Errorf("%s, %s", o, err))
			} else {
				fmt.Printf("%s", string(o))
			}
		}
	}
}
Beispiel #27
0
func (t *qmlfrontend) loop() (err error) {

	backend.OnNew.Add(func(v *backend.View) {
		fv := &frontendView{bv: v}
		v.Buffer().AddCallback(fv.bufferChanged)
		v.Settings().AddOnChange("blah", func(name string) {
			if name == "lime.syntax.updated" {
				// force redraw, as the syntax regions might have changed...
				for i := range fv.FormattedLine {
					fv.formatLine(i)
				}
			}
		})

		fv.Title.Text = v.Buffer().FileName()
		if len(fv.Title.Text) == 0 {
			fv.Title.Text = "untitled"
		}

		w2 := t.windows[v.Window()]
		w2.views = append(w2.views, fv)
		w2.Len = len(w2.views)
		t.qmlChanged(w2, &w2.Len)
	})

	backend.OnClose.Add(func(v *backend.View) {
		w2 := t.windows[v.Window()]
		for i := range w2.views {
			if w2.views[i].bv == v {
				copy(w2.views[i:], w2.views[i+1:])
				w2.views = w2.views[:len(w2.views)-1]
				w2.Len = len(w2.views)
				t.qmlChanged(w2, &w2.Len)
				return
			}
		}
		log4go.Error("Couldn't find closed view...")
	})

	backend.OnLoad.Add(func(v *backend.View) {
		w2 := t.windows[v.Window()]
		i := 0
		for i, _ = range w2.views {
			if w2.views[i].bv == v {
				break
			}
		}
		v2 := w2.views[i]
		v2.Title.Text = v.Buffer().FileName()
		t.qmlChanged(v2, &v2.Title)
	})

	ed := backend.GetEditor()
	ed.SetFrontend(t)
	ed.LogInput(false)
	ed.LogCommands(false)
	c := ed.Console()
	t.Console = &frontendView{bv: c}
	c.Buffer().AddCallback(t.Console.bufferChanged)
	c.Buffer().AddCallback(t.scroll)

	const qmlMainFile = "main.qml"
	var (
		engine    *qml.Engine
		component qml.Object
		// WaitGroup keeping track of open windows
		wg sync.WaitGroup
	)

	// create and setup a new engine, destroying
	// the old one if one exists.
	//
	// This is needed to re-load qml files to get
	// the new file contents from disc as otherwise
	// the old file would still be what is referenced.
	newEngine := func() (err error) {
		if engine != nil {
			log4go.Debug("calling destroy")
			// TODO(.): calling this appears to make the editor *very* crash-prone, just let it leak for now
			// engine.Destroy()
			engine = nil
		}
		log4go.Debug("calling newEngine")
		engine = qml.NewEngine()
		log4go.Debug("setvar frontend")
		engine.Context().SetVar("frontend", t)
		log4go.Debug("setvar editor")
		engine.Context().SetVar("editor", backend.GetEditor())

		log4go.Debug("loadfile")
		component, err = engine.LoadFile(qmlMainFile)
		return
	}
	if err := newEngine(); err != nil {
		log4go.Error(err)
	}

	backend.OnNewWindow.Add(func(w *backend.Window) {
		fw := &frontendWindow{bw: w}
		t.windows[w] = fw
		if component != nil {
			fw.launch(&wg, component)
		}
	})

	// TODO: should be done backend side
	if sc, err := textmate.LoadTheme("../../3rdparty/bundles/TextMate-Themes/Monokai.tmTheme"); err != nil {
		log4go.Error(err)
	} else {
		scheme = sc
	}

	defer func() {
		fmt.Println(util.Prof)
	}()

	w := ed.NewWindow()
	v := w.OpenFile("main.go", 0)
	// TODO: should be done backend side
	v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage")
	v.Sel().Clear()
	v.Sel().Add(Region{0, 0})
	v = w.OpenFile("../../backend/editor.go", 0)
	// TODO: should be done backend side
	v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage")
	v.Sel().Clear()
	v.Sel().Add(Region{0, 0})

	ed.Init()
	sublime.Init()

	watch, err := fsnotify.NewWatcher()
	if err != nil {
		log4go.Error("Unable to create file watcher: %s", err)
		return
	}
	defer watch.Close()
	watch.Watch(".")
	defer watch.RemoveWatch(".")

	reloadRequested := false

	go func() {
		for {
			select {
			case ev := <-watch.Event:
				if ev != nil && strings.HasSuffix(ev.Name, ".qml") && ev.IsModify() && !ev.IsAttrib() {
					reloadRequested = true
					// Close all open windows to de-reference all
					// qml objects
					for _, v := range t.windows {
						if v.window != nil {
							v.window.Hide()
							v.window.Destroy()
							v.window = nil
						}
					}
				}
			}
		}
	}()

	for {
		// Reset reload status
		reloadRequested = false

		log4go.Debug("Waiting for all windows to close")
		// wg would be the WaitGroup all windows belong to, so first we wait for
		// all windows to close.
		wg.Wait()
		log4go.Debug("All windows closed. reloadRequest: %v", reloadRequested)
		// then we check if there's a reload request in the pipe
		if !reloadRequested || len(t.windows) == 0 {
			// This would be a genuine exit; all windows closed by the user
			break
		}

		// *We* closed all windows because we want to reload freshly changed qml
		// files.
		for {
			log4go.Debug("Calling newEngine")
			if err := newEngine(); err != nil {
				// Reset reload status
				reloadRequested = false
				log4go.Error(err)
				for !reloadRequested {
					// This loop allows us to re-try reloading
					// if there was an error in the file this time,
					// we just loop around again when we receive the next
					// reload request (ie on the next save of the file).
					time.Sleep(time.Second)
				}
				continue
			}
			log4go.Debug("break")
			break
		}
		log4go.Debug("re-launching all windows")
		// Succeeded loading the file, re-launch all windows
		for _, v := range t.windows {
			v.launch(&wg, component)
		}
	}
	return
}
Beispiel #28
0
func main() {
	cleanup()
	var sublime_methods = ""
	sn := func(t reflect.Type, m reflect.Method) string {
		sn := "sublime_" + m.Name
		sublime_methods += fmt.Sprintf("{Name: \"%s\", Func: %s},\n", pyname(m.Name)[1:], sn)
		return sn
	}
	data := [][]string{
		{"./backend/sublime/region_generated.go", generateWrapper(reflect.TypeOf(text.Region{}), true, regexp.MustCompile("Cut").MatchString)},
		{"./backend/sublime/regionset_generated.go", generateWrapper(reflect.TypeOf(&text.RegionSet{}), false, regexp.MustCompile("Less|Swap|Adjust|Has|Cut").MatchString)},
		{"./backend/sublime/edit_generated.go", generateWrapper(reflect.TypeOf(&backend.Edit{}), false, regexp.MustCompile("Apply|Undo").MatchString)},
		{"./backend/sublime/view_generated.go", generateWrapper(reflect.TypeOf(&backend.View{}), false, regexp.MustCompile("Buffer|Syntax|CommandHistory|Show|AddRegions|UndoStack|Transform|Reload|Save|Close|ExpandByClass|Erased|FileChanged|Inserted").MatchString)},
		{"./backend/sublime/window_generated.go", generateWrapper(reflect.TypeOf(&backend.Window{}), false, regexp.MustCompile("OpenFile|SetActiveView|Close").MatchString)},
		{"./backend/sublime/settings_generated.go", generateWrapper(reflect.TypeOf(&text.Settings{}), false, regexp.MustCompile("Parent|Set|Get|UnmarshalJSON|MarshalJSON").MatchString)},
		{"./backend/sublime/view_buffer_generated.go", generatemethodsEx(
			reflect.TypeOf(backend.GetEditor().Console().Buffer()),
			regexp.MustCompile("Erase|Insert|Substr|SetFile|AddCallback|AddObserver|RemoveObserver|Data|Runes|Settings|Index|Close|Unlock|Lock").MatchString,
			"o.data.Buffer().",
			func(t reflect.Type, m reflect.Method) string {
				mn := ""
				switch m.Name {
				case "Line", "LineR", "FullLine", "FullLineR", "WordR", "Word":
					mn = strings.ToLower(m.Name)
				case "Id":
					mn = "Py_buffer_id"
				default:
					mn = "Py" + pyname(m.Name)
				}
				return "(o *View) " + mn
			})},
		{"./backend/sublime/commands_generated.go", generatemethodsEx(reflect.TypeOf(backend.GetEditor().CommandHandler()),
			regexp.MustCompile("RunWindowCommand|RunTextCommand|RunApplicationCommand|RegisterWithDefault").MatchString,
			"backend.GetEditor().CommandHandler().",
			sn),
		},
		{"./backend/sublime/frontend_generated.go", generatemethodsEx(reflect.TypeOf(backend.GetEditor().Frontend()),
			regexp.MustCompile("Show|VisibleRegion|DefaultAction").MatchString,
			"backend.GetEditor().Frontend().",
			sn),
		},
		{"./backend/sublime/sublime_api_generated.go", generatemethodsEx(reflect.TypeOf(backend.GetEditor()),
			regexp.MustCompile("Info|HandleInput|CommandHandler|Windows|Frontend|Console|SetActiveWindow|Init|Watch|Observe|SetClipboardFuncs|KeyBindings").MatchString,
			"backend.GetEditor().",
			sn),
		},
	}
	data[len(data)-1][1] += fmt.Sprintf(`var sublime_methods = []py.Method{
		%s
	}`, sublime_methods)
	var year = strconv.FormatInt(int64(time.Now().Year()), 10)

	for _, gen := range data {
		if gen[0] == "" {
			continue
		}
		wr := `// Copyright ` + year + ` The lime Authors.
			// Use of this source code is governed by a 2-clause
			// BSD-style license that can be found in the LICENSE file.

			// This file was generated by tasks/build/gen_python_api.go and shouldn't be manually modified

			package sublime

			import (
				"fmt"
				"github.com/limetext/gopy/lib"
				"github.com/limetext/lime/backend"
				"github.com/limetext/text"
			)
			var (
				_ = backend.View{}
				_ = text.Region{}
				_ = fmt.Errorf
			)
			` + gen[1]
		if err := ioutil.WriteFile(gen[0], []byte(wr), 0644); err != nil {
			panic(err)
		} else {
			c := exec.Command("go", "fmt", gen[0])
			if o, err := c.CombinedOutput(); err != nil {
				panic(fmt.Errorf("%s, %s", o, err))
			} else {
				fmt.Printf("%s", string(o))
			}
		}
	}
}
Beispiel #29
0
func TestSublime(t *testing.T) {
	ed := backend.GetEditor()
	ed.Console().Buffer().AddCallback(func(b text.Buffer, pos, delta int) {
		t.Logf("%s", b.Substr(text.Region{pos, pos + delta}))
	})
	w := ed.NewWindow()
	Init()
	l := py.NewLock()
	py.AddToPath("testdata")
	py.AddToPath("testdata/plugins")
	if m, err := py.Import("sublime_plugin"); err != nil {
		t.Fatal(err)
	} else {
		plugins := backend.ScanPlugins("testdata/", ".py")
		for _, p := range plugins {
			loadPlugin(p, m)
		}
	}

	subl, err := py.Import("sublime")
	if err != nil {
		t.Fatal(err)
	}

	if w, err := _windowClass.Alloc(1); err != nil {
		t.Fatal(err)
	} else {
		(w.(*Window)).data = &backend.Window{}
		subl.AddObject("test_window", w)
	}

	if dir, err := os.Open("testdata"); err != nil {
		t.Error(err)
	} else if files, err := dir.Readdirnames(0); err != nil {
		t.Error(err)
	} else {
		for _, fn := range files {
			if filepath.Ext(fn) == ".py" {
				log4go.Debug("Running %s", fn)
				if _, err := py.Import(fn[:len(fn)-3]); err != nil {
					log4go.Error(err)
					t.Error(err)
				} else {
					log4go.Debug("Ran %s", fn)
				}
			}
		}
	}

	// Testing plugin reload
	data := []byte(`import sublime, sublime_plugin

class TestToxt(sublime_plugin.TextCommand):
    def run(self, edit):
        print("my view's id is: %d" % self.view.id())
        self.view.insert(edit, 0, "Tada")
		`)
	if err := ioutil.WriteFile("testdata/plugins/reload.py", data, 0644); err != nil {
		t.Fatalf("Couldn't write file: %s", err)
	}
	data = []byte(`try:
    import traceback
    import sublime
    print("new file")
    v = sublime.test_window.new_file()
    print("running command")
    v.run_command("test_toxt")
    print("command ran")
    assert v.substr(sublime.Region(0, v.size())) == "Tada"
except:
    traceback.print_exc()
    raise
		`)
	time.Sleep(time.Millisecond * 10)
	if err := ioutil.WriteFile("testdata/reload_test.py", data, 0644); err != nil {
		t.Fatalf("Couldn't write file: %s", err)
	}
	log4go.Debug("Running %s", "reload_test.py")
	if _, err := py.Import("reload_test"); err != nil {
		log4go.Error(err)
		t.Error(err)
	} else {
		log4go.Debug("Ran %s", "reload_test.py")
	}
	os.Remove("testdata/plugins/reload.py")
	os.Remove("testdata/reload_test.py")

	var f func(indent string, v py.Object, buf *bytes.Buffer)
	f = func(indent string, v py.Object, buf *bytes.Buffer) {
		b := v.Base()
		if dir, err := b.Dir(); err != nil {
			t.Error(err)
		} else {
			if l, ok := dir.(*py.List); ok {
				sl := l.Slice()

				if indent == "" {
					for _, v2 := range sl {
						if item, err := b.GetAttr(v2); err != nil {
							t.Error(err)
						} else {
							ty := item.Type()
							line := fmt.Sprintf("%s%s\n", indent, v2)
							buf.WriteString(line)
							if ty == py.TypeType {
								f(indent+"\t", item, buf)
							}
							item.Decref()
						}
					}
				} else {
					for _, v2 := range sl {
						buf.WriteString(fmt.Sprintf("%s%s\n", indent, v2))
					}
				}

			} else {
				ty := dir.Type()
				t.Error("Unexpected type:", ty)
			}
			dir.Decref()
		}
	}
	buf := bytes.NewBuffer(nil)
	f("", subl, buf)

	l.Unlock()

	const expfile = "testdata/api.txt"
	if d, err := ioutil.ReadFile(expfile); err != nil {
		if err := ioutil.WriteFile(expfile, buf.Bytes(), 0644); err != nil {
			t.Error(err)
		}
	} else if diff := util.Diff(string(d), buf.String()); diff != "" {
		t.Error(diff)
	}
	ed.LogCommands(true)
	tests := []string{
		"state",
		"registers",
		"settings",
		"constants",
		"registers",
		"cmd_data",
		"marks",
	}

	for _, test := range tests {
		ed.CommandHandler().RunWindowCommand(w, "vintage_ex_run_data_file_based_tests", backend.Args{"suite_name": test})
	}
	for _, w := range ed.Windows() {
		for _, v := range w.Views() {
			if strings.HasSuffix(v.Buffer().FileName(), "sample.txt") {
				continue
			}
			if strings.Index(v.Buffer().Substr(text.Region{0, v.Buffer().Size()}), "FAILED") != -1 {
				t.Error(v.Buffer())
			}
		}
	}

	var v *backend.View
	for _, v2 := range w.Views() {
		if v == nil || v2.Buffer().Size() > v.Buffer().Size() {
			v = v2
		}
	}
}
Beispiel #30
0
// Launches the provided command in a new goroutine
// (to avoid locking up the GUI)
func (t *qmlfrontend) RunCommand(command string) {
	ed := backend.GetEditor()
	go ed.RunCommand(command, make(backend.Args))
}