func BenchmarkTransformTranscribe(b *testing.B) { b.StopTimer() w := GetEditor().NewWindow() defer w.Close() v := w.NewFile() defer func() { v.SetScratch(true) v.Close() }() sc, err := textmate.LoadTheme("../packages/themes/TextMate-Themes/GlitterBomb.tmTheme") if err != nil { b.Fatal(err) } v.Settings().Set("syntax", "textmate/testdata/Go.tmLanguage") d, err := ioutil.ReadFile("view.go") if err != nil { b.Fatal(err) } var wg sync.WaitGroup wg.Add(1) v.Settings().AddOnChange("benchmark", func(key string) { if key == "lime.syntax.updated" { wg.Done() } }) e := v.BeginEdit() v.Insert(e, 0, string(d)) v.EndEdit(e) wg.Wait() b.StartTimer() for i := 0; i < b.N; i++ { v.Transform(sc, text.Region{A: 0, B: v.Buffer().Size()}).Transcribe() } fmt.Println(util.Prof.String()) }
func TestTransform(t *testing.T) { w := GetEditor().NewWindow() defer w.Close() v := w.NewFile() defer func() { v.SetScratch(true) v.Close() }() sc, err := textmate.LoadTheme("../packages/themes/TextMate-Themes/GlitterBomb.tmTheme") if err != nil { t.Fatal(err) } d, err := ioutil.ReadFile("view.go") if err != nil { t.Fatal(err) } e := v.BeginEdit() v.Insert(e, 0, string(d)) v.EndEdit(e) if v.Transform(sc, text.Region{A: 0, B: 100}) != nil { t.Error("Expected view.Transform return nil when the syntax isn't set yet") } v.Settings().Set("syntax", "textmate/testdata/Go.tmLanguage") time.Sleep(time.Second) a := v.Transform(sc, text.Region{A: 0, B: 100}).Transcribe() v.Transform(sc, text.Region{A: 100, B: 200}).Transcribe() c := v.Transform(sc, text.Region{A: 0, B: 100}).Transcribe() if !reflect.DeepEqual(a, c) { t.Errorf("not equal:\n%v\n%v", a, c) } }
// 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() } w, h := termbox.Size() t.handleResize(h, w, true) t.console.Buffer().AddObserver(&t) t.setupCallbacks(t.currentView) path := path.Join(backend.LIME_PACKAGES_PATH, "themes", "TextMate-Themes", "Monokai.tmTheme") if sc, err := textmate.LoadTheme(path); err != nil { log.Error(err) } else { scheme = sc } setColorMode() setSchemeSettings() return &t }
func (t *tbfe) loop() { backend.OnNew.Add(func(v *backend.View) { v.Settings().AddOnChange("lime.frontend.html.render", func(name string) { if name != "lime.syntax.updated" { return } t.SetDirty() }) }) // TODO: maybe not useful? /*backend.OnModified.Add(func(v *backend.View) { t.SetDirty() })*/ backend.OnSelectionModified.Add(func(v *backend.View) { t.BroadcastData(t.GetSelectionMessage(v)) }) ed := backend.GetEditor() ed.SetFrontend(t) ed.LogInput(false) ed.LogCommands(false) c := ed.Console() if sc, err := textmate.LoadTheme(path.Join(backend.LIME_PACKAGES_PATH, "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) //v.Settings().Set("trace", true) v.Settings().Set("syntax", path.Join(backend.LIME_PACKAGES_PATH, "go.tmbundle", "Syntaxes", "Go.tmLanguage")) c.Buffer().AddObserver(t) 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 ed.Init() log.Debug("Serving on port %d", *port) http.HandleFunc("/", t.ServeHTTP) http.HandleFunc("/view", t.view) http.HandleFunc("/key", t.key) http.HandleFunc("/themes/", t.theme) http.Handle("/ws", websocket.Handler(t.WebsocketServer)) if err := http.ListenAndServe(fmt.Sprintf("localhost:%d", *port), nil); err != nil { log.Errorf("Error serving: %s", err) } log.Debug("Done") }
func (t *qmlfrontend) loop() (err error) { backend.OnNew.Add(t.onNew) backend.OnClose.Add(t.onClose) backend.OnLoad.Add(t.onLoad) backend.OnSelectionModified.Add(t.onSelectionModified) ed := backend.GetEditor() 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) go ed.Init() 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() engine.On("quit", t.Quit) 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.SetSyntaxFile("../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 t.Quit() } } } }() 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 }