Skip to content

Instantly share code, notes, and snippets.

@bwiggs
Created February 25, 2015 04:16
Show Gist options
  • Save bwiggs/b86d577b31519ba13c4a to your computer and use it in GitHub Desktop.
Save bwiggs/b86d577b31519ba13c4a to your computer and use it in GitHub Desktop.
limetext refactor snippet
// newQmlEngine creates a new qml engine. Destroys the old one if set.
//
// 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.
func (t *qmlfrontend) newQmlEngine() (err error) {
if t.engine != nil {
// TODO(.): calling this appears to make the editor *very* crash-prone, just let it leak for now
// engine.Destroy()
t.engine = nil
}
t.engine = qml.NewEngine()
t.engine.Context().SetVar("frontend", t)
t.engine.Context().SetVar("editor", backend.GetEditor())
return
}
// loop is the main application loop started by qml.Run
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 (
windowComponent qml.Object // main QML windowComponent
wg sync.WaitGroup // keeps track of open windows
)
if err := t.newQmlEngine(); err != nil {
log.Error(err)
}
windowComponent, err = t.engine.LoadFile(qmlMainFile)
if err != nil {
return err
}
limeViewComponent, err = t.engine.LoadFile(qmlViewFile)
if err != nil {
return err
}
backend.OnNewWindow.Add(func(w *backend.Window) {
fw := &frontendWindow{bw: w}
t.windows[w] = fw
if windowComponent != nil {
fw.launch(&wg, windowComponent)
}
})
// 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 := t.newQmlEngine(); 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, windowComponent)
}
}
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment