Exemple #1
0
// Called when a new view is opened
func (t *qmlfrontend) onNew(v *backend.View) {
	fv := &frontendView{bv: v}
	v.Buffer().AddObserver(fv)
	v.Settings().AddOnChange("blah", fv.onChange)

	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)

	tabs := w2.window.ObjectByName("tabs")
	tab := tabs.Call("addTab", "", limeViewComponent).(qml.Object)
	try_now := func() {
		item := tab.Property("item").(qml.Object)
		if item.Addr() == 0 {
			// Happens as the item isn't actually loaded until we switch to the tab.
			// Hence connecting to the loaded signal
			return
		}
		item.Set("myView", fv)
		item.Set("fontSize", v.Settings().Get("font_size", 12).(float64))
		item.Set("fontFace", v.Settings().Get("font_face", "Helvetica").(string))
	}
	tab.On("loaded", try_now)
	try_now()
	tabs.Set("currentIndex", tabs.Property("count").(int)-1)
}
Exemple #2
0
// Called when a new view is opened
func (t *qmlfrontend) onNew(v *backend.View) {
	fv := &frontendView{bv: v}
	v.Buffer().AddCallback(fv.bufferChanged)
	v.Settings().AddOnChange("blah", fv.onChange)

	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)

	tabs := w2.window.ObjectByName("tabs")
	tab := tabs.Call("addTab", "", limeViewComponent).(qml.Object)
	try_now := func() {
		item := tab.Property("item").(qml.Object)
		if item.Addr() == 0 {
			// Happens as the item isn't actually loaded until we switch to the tab.
			// Hence connecting to the loaded signal
			return
		}
		item.Set("myView", fv)
	}
	tab.On("loaded", try_now)
	try_now()
}
Exemple #3
0
// called when a view has loaded
func (t *qmlfrontend) onLoad(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)
}
Exemple #4
0
func (t *tbfe) VisibleRegion(v *backend.View) Region {
	t.lock.Lock()
	r, ok := t.layout[v]
	t.lock.Unlock()
	if !ok || r.lastUpdate != v.Buffer().ChangeCount() {
		t.Show(v, r.visible)
		t.lock.Lock()
		r = t.layout[v]
		t.lock.Unlock()
	}
	return r.visible
}
Exemple #5
0
// called when a view has loaded
func (t *qmlfrontend) onLoad(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()
	tabs := w2.window.ObjectByName("tabs")
	tab := tabs.Call("getTab", i).(qml.Object)
	tab.Set("title", v2.Title.Text)
}
Exemple #6
0
Fichier : main.go Projet : rzh/lime
func (t *tbfe) FormatLine(v *backend.View, line int) string {
	buf := bytes.NewBuffer(nil)
	vr := v.Buffer().Line(v.Buffer().TextPoint(line, 0))
	log4go.Debug("FormatLine: %d, %s", line, vr)
	if vr.Size() == 0 {
		return ""
	}
	recipie := v.Transform(scheme, vr).Transcribe()
	highlight_line := false
	if b, ok := v.Settings().Get("highlight_line", highlight_line).(bool); ok {
		highlight_line = b
	}
	lastEnd := vr.Begin()
	for _, reg := range recipie {
		if lastEnd != reg.Region.Begin() {
			fmt.Fprintf(buf, "<span>%s</span>", v.Buffer().Substr(Region{lastEnd, reg.Region.Begin()}))
		}
		fmt.Fprintf(buf, "<span style=\"white-space:pre; color:#%s; background:#%s\">%s</span>", htmlcol(reg.Flavour.Foreground), htmlcol(reg.Flavour.Background), v.Buffer().Substr(reg.Region))
		lastEnd = reg.Region.End()
	}
	if lastEnd != vr.End() {
		io.WriteString(buf, v.Buffer().Substr(Region{lastEnd, vr.End()}))
	}
	return buf.String()
}
Exemple #7
0
func (t *tbfe) setupCallbacks(view *backend.View) {
	// Ensure that the visible region currently presented is
	// inclusive of the insert/erase delta.
	view.Buffer().AddObserver(&tbfeBufferDeltaObserver{t: t, view: view})

	backend.OnNew.Add(func(v *backend.View) {
		v.Settings().AddOnChange("lime.frontend.termbox.render", func(name string) { t.render() })
	})

	backend.OnModified.Add(func(v *backend.View) {
		t.render()
	})

	backend.OnSelectionModified.Add(func(v *backend.View) {
		t.render()
	})
}
Exemple #8
0
func (t *tbfe) clip(v *backend.View, s, e int) Region {
	p := util.Prof.Enter("clip")
	defer p.Exit()
	h := t.layout[v].height
	if e-s > h {
		e = s + h
	} else if e-s < h {
		s = e - h
	}
	if e2, _ := v.Buffer().RowCol(v.Buffer().TextPoint(e, 0)); e2 < e {
		e = e2
	}
	if s < 0 {
		s = 0
	}
	e = s + h
	r := Region{v.Buffer().TextPoint(s, 0), v.Buffer().TextPoint(e, 0)}
	return v.Buffer().LineR(r)
}
Exemple #9
0
func (t tbfe) setupCallbacks(view *backend.View) {
	// Ensure that the visible region currently presented is
	// inclusive of the insert/erase delta.
	view.Buffer().AddCallback(func(b Buffer, pos, delta int) {
		visible := t.layout[view].visible
		t.Show(view, Region{visible.Begin(), visible.End() + delta})
	})

	backend.OnNew.Add(func(v *backend.View) {
		v.Settings().AddOnChange("lime.frontend.termbox.render", func(name string) { t.render() })
	})

	backend.OnModified.Add(func(v *backend.View) {
		t.render()
	})

	backend.OnSelectionModified.Add(func(v *backend.View) {
		t.render()
	})
}
Exemple #10
0
func (t *tbfe) Show(v *backend.View, r Region) {
	t.lock.Lock()
	l := t.layout[v]
	t.lock.Unlock()
	p := util.Prof.Enter("show")
	defer p.Exit()

	lv := l.visible

	s1, _ := v.Buffer().RowCol(lv.Begin())
	e1, _ := v.Buffer().RowCol(lv.End())
	s2, _ := v.Buffer().RowCol(r.Begin())
	e2, _ := v.Buffer().RowCol(r.End())

	r1 := Region{s1, e1}
	r2 := Region{s2, e2}

	r3 := r1.Cover(r2)
	diff := 0
	if d1, d2 := Abs(r1.Begin()-r3.Begin()), Abs(r1.End()-r3.End()); d1 > d2 {
		diff = r3.Begin() - r1.Begin()
	} else {
		diff = r3.End() - r1.End()
	}
	r3.A = r1.Begin() + diff
	r3.B = r1.End() + diff

	r3 = t.clip(v, r3.A, r3.B)
	l.visible = r3
	t.lock.Lock()
	t.layout[v] = l
	t.lock.Unlock()
	t.render()
}
Exemple #11
0
func (t *tbfe) renderView(wr io.Writer, v *backend.View, lay layout) {
	p := util.Prof.Enter("render")
	defer p.Exit()

	vr := lay.visible
	runes := v.Buffer().Substr(vr)
	recipie := v.Transform(scheme, vr).Transcribe()
	highlight_line := false
	if b, ok := v.Settings().Get("highlight_line", highlight_line).(bool); ok {
		highlight_line = b
	}
	lastEnd := 0
	for _, reg := range recipie {
		if lastEnd != reg.Region.Begin() {
			io.WriteString(wr, runes[lastEnd:reg.Region.Begin()])
		}
		fmt.Fprintf(wr, "<span style=\"color:#%s; background-color:#%s\">%s</span>", htmlcol(reg.Flavour.Foreground), htmlcol(reg.Flavour.Background), runes[reg.Region.Begin():reg.Region.End()])
		lastEnd = reg.Region.End()
	}
	if lastEnd != vr.End() {
		io.WriteString(wr, v.Buffer().Substr(Region{lastEnd, vr.End()}))
	}
}
Exemple #12
0
func (t *tbfe) renderLStatus(v *backend.View, y int, fg, bg termbox.Attribute) {
	st := v.Status()
	sel := v.Sel()
	j := 0

	for k, v := range st {
		s := fmt.Sprintf("%s: %s, ", k, v)
		addString(j, y, s, fg, bg)
	}

	if sel.Len() == 0 {
		return
	} else if l := sel.Len(); l > 1 {
		s := fmt.Sprintf("%d selection regions", l)
		j = addString(j, y, s, fg, bg)
	} else if r := sel.Get(0); r.Size() == 0 {
		row, col := v.Buffer().RowCol(r.A)
		s := fmt.Sprintf("Line %d, Column %d", row, col)
		j = addString(j, y, s, fg, bg)
	} else {
		ls := v.Buffer().Lines(r)
		s := v.Buffer().Substr(r)
		if len(ls) < 2 {
			s := fmt.Sprintf("%d characters selected", len(s))
			j = addString(j, y, s, fg, bg)
		} else {
			s := fmt.Sprintf("%d lines %d characters selected", len(ls), len(s))
			j = addString(j, y, s, fg, bg)
		}
	}

	if t.status_message != "" {
		s := fmt.Sprintf("; %s", t.status_message)
		addString(j, y, s, fg, bg)
	}
}
Exemple #13
0
func (t *tbfe) renderView(v *backend.View, lay layout) {
	p := util.Prof.Enter("render")
	defer p.Exit()

	sx, sy, w, h := lay.x, lay.y, lay.width, lay.height
	vr := lay.visible
	runes := v.Buffer().Substr(vr)
	x, y := sx, sy
	ex, ey := sx+w, sy+h

	caretStyle := t.settings.caretStyle
	if t.settings.caretBlink && blink {
		t.settings.caretStyle = 0
	}

	recipie := v.Transform(scheme, vr).Transcribe()

	fg, bg := defaultFg, defaultBg
	sel := v.Sel()

	line, _ := v.Buffer().RowCol(vr.Begin())
	eofline, _ := v.Buffer().RowCol(v.Buffer().Size())
	lineNumberRenderSize := len(intToRunes(eofline))

	for i, r := range runes {
		o := vr.Begin() + i
		curr := 0
		fg, bg = defaultFg, defaultBg

		if t.settings.lineNumbers {
			renderLineNumber(&line, &x, y, lineNumberRenderSize, fg, bg)
		}

		for curr < len(recipie) && (o >= recipie[curr].Region.Begin()) {
			if o < recipie[curr].Region.End() {
				fg = palLut(textmate.Color(recipie[curr].Flavour.Foreground))
				bg = palLut(textmate.Color(recipie[curr].Flavour.Background))
			}
			curr++
		}
		if sel.Contains(Region{o, o}) {
			fg = fg | t.settings.caretStyle
		}
		if r == '\t' {
			add := (x + 1 + (t.settings.tabSize - 1)) &^ (t.settings.tabSize - 1)
			for x < add {
				if x < ex {
					termbox.SetCell(x, y, ' ', fg, bg)
				}
				fg = fg &^ termbox.AttrUnderline // Just looks weird with a long underline
				x++
			}
			continue
		} else if r == '\n' {
			x = sx
			y++
			if y > ey {
				break
			}
			continue
		}
		if x < ex {
			termbox.SetCell(x, y, r, fg, bg)
		}
		x++
	}

	// restore original caretStyle before blink modification
	t.settings.caretStyle = caretStyle
}
Exemple #14
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
		}
	}
}
Exemple #15
0
func (t *qmlfrontend) VisibleRegion(v *backend.View) Region {
	// TODO
	return Region{0, v.Buffer().Size()}
}
Exemple #16
0
func (t *tbfe) renderView(v *backend.View, lay layout) {
	p := util.Prof.Enter("render")
	defer p.Exit()

	sx, sy, w, h := lay.x, lay.y, lay.width, lay.height
	vr := lay.visible
	runes := v.Buffer().Substr(vr)
	x, y := sx, sy
	ex, ey := sx+w, sy+h

	style, _ := v.Settings().Get("caret_style", "underline").(string)
	inverse, _ := v.Settings().Get("inverse_caret_state", false).(bool)

	caretStyle := getCaretStyle(style, inverse)
	oldCaretStyle := caretStyle

	caretBlink, _ := v.Settings().Get("caret_blink", true).(bool)
	if caretBlink && blink {
		caretStyle = 0
	}

	tabSize := 4
	if i, ok := v.Settings().Get("tab_size", tabSize).(int); ok {
		tabSize = i
	}

	lineNumbers, _ := v.Settings().Get("line_numbers", true).(bool)

	recipie := v.Transform(scheme, vr).Transcribe()

	fg, bg := defaultFg, defaultBg
	sel := v.Sel()

	line, _ := v.Buffer().RowCol(vr.Begin())
	eofline, _ := v.Buffer().RowCol(v.Buffer().Size())
	lineNumberRenderSize := len(intToRunes(eofline))

	for i, r := range runes {
		o := vr.Begin() + i
		curr := 0
		fg, bg = defaultFg, defaultBg

		if lineNumbers {
			renderLineNumber(&line, &x, y, lineNumberRenderSize, fg, bg)
		}

		// TODO: doc
		for curr < len(recipie) && (o >= recipie[curr].Region.Begin()) {
			if o < recipie[curr].Region.End() {
				fg = palLut(textmate.Color(recipie[curr].Flavour.Foreground))
				bg = palLut(textmate.Color(recipie[curr].Flavour.Background))
			}
			curr++
		}

		iscursor := sel.Contains(Region{o, o})
		if iscursor {
			fg = fg | caretStyle
			termbox.SetCell(x, y, ' ', fg, bg)
		}

		if r == '\t' {
			add := (x + 1 + (tabSize - 1)) &^ (tabSize - 1)
			for ; x < add; x++ {
				if x < ex {
					termbox.SetCell(x, y, ' ', fg, bg)
				}
				// A long cursor looks weird
				fg = fg & ^(termbox.AttrUnderline | termbox.AttrReverse)
			}
			continue
		} else if r == '\n' {
			x = sx
			if y++; y > ey {
				break
			} else if lineNumbers {
				// This results in additional calls to renderLineNumber.
				// Maybe just accumulate positions needing line numbers, rendering them
				// after the loop?
				renderLineNumber(&line, &x, y, lineNumberRenderSize, defaultFg, defaultBg)
			}
			continue
		}
		if x < ex {
			termbox.SetCell(x, y, r, fg, bg)
		}
		x++
	}
	fg, bg = defaultFg, defaultBg
	// Need this if the cursor is at the end of the buffer
	o := vr.Begin() + len(runes)
	iscursor := sel.Contains(Region{o, o})
	if iscursor {
		fg = fg | caretStyle
		termbox.SetCell(x, y, ' ', fg, bg)
	}

	// restore original caretStyle before blink modification
	caretStyle = oldCaretStyle

	if rs := sel.Regions(); len(rs) > 0 {
		if r := rs[len(rs)-1]; !vr.Covers(r) {
			t.Show(v, r)
		}
	}

	fg, bg = defaultFg, palLut(textmate.Color{28, 29, 26, 1})
	y = t.window_layout.height - statusbarHeight
	// Draw status bar bottom of window
	for i := 0; i < t.window_layout.width; i++ {
		termbox.SetCell(i, y, ' ', fg, bg)
	}
	t.renderLStatus(v, y, fg, bg)
	// The right status
	rns := []rune(fmt.Sprintf("Tab Size:%d   %s", tabSize, "Go"))
	x = t.window_layout.width - 1 - len(rns)
	addRunes(x, y, rns, fg, bg)
}
Exemple #17
0
func (t *tbfe) VisibleRegion(v *backend.View) Region {
	// TODO
	return Region{0, v.Buffer().Size()}
}
Exemple #18
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
		}
	}
}
Exemple #19
0
func (t *tbfe) renderView(v *backend.View, lay layout) {
	p := util.Prof.Enter("render")
	defer p.Exit()

	sx, sy, w, h := lay.x, lay.y, lay.width, lay.height
	vr := lay.visible
	runes := v.Buffer().Substr(vr)
	x, y := sx, sy
	ex, ey := sx+w, sy+h

	style, _ := v.Settings().Get("caret_style", "underline").(string)
	inverse, _ := v.Settings().Get("inverse_caret_state", false).(bool)

	caretStyle := getCaretStyle(style, inverse)
	caretBlink, _ := v.Settings().Get("caret_blink", true).(bool)
	if caretBlink && blink {
		caretStyle = 0
	}
	tabSize := 4
	ts := v.Settings().Get("tab_size", tabSize)
	// TODO(.): crikey...
	if i, ok := ts.(int); ok {
		tabSize = i
	} else if f, ok := ts.(float64); ok {
		tabSize = int(f)
	}

	lineNumbers, _ := v.Settings().Get("line_numbers", true).(bool)

	recipie := v.Transform(scheme, vr).Transcribe()

	fg, bg := defaultFg, defaultBg
	sel := v.Sel()

	line, _ := v.Buffer().RowCol(vr.Begin())
	eofline, _ := v.Buffer().RowCol(v.Buffer().Size())
	lineNumberRenderSize := len(intToRunes(eofline))

	for i, r := range runes {
		o := vr.Begin() + i
		curr := 0
		fg, bg = defaultFg, defaultBg

		if lineNumbers {
			renderLineNumber(&line, &x, y, lineNumberRenderSize, fg, bg)
		}

		for curr < len(recipie) && (o >= recipie[curr].Region.Begin()) {
			if o < recipie[curr].Region.End() {
				fg = palLut(textmate.Color(recipie[curr].Flavour.Foreground))
				bg = palLut(textmate.Color(recipie[curr].Flavour.Background))
			}
			curr++
		}
		iscursor := sel.Contains(Region{o, o})
		if iscursor {
			fg = fg | caretStyle
			termbox.SetCell(x, y, ' ', fg, bg)
		}
		if r == '\t' {
			add := (x + 1 + (tabSize - 1)) &^ (tabSize - 1)
			for x < add {
				if x < ex {
					termbox.SetCell(x, y, ' ', fg, bg)
				}
				// A long cursor looks weird
				fg = fg & ^(termbox.AttrUnderline | termbox.AttrReverse)
				x++
			}
			continue
		} else if r == '\n' {
			x = sx
			if y++; y > ey {
				break
			} else if lineNumbers {
				renderLineNumber(&line, &x, y, lineNumberRenderSize, fg, bg)
			}
			continue
		}
		if x < ex {
			termbox.SetCell(x, y, r, fg, bg)
		}
		x++
	}
	fg, bg = defaultFg, defaultBg
	// Need this if the cursor is at the end of the buffer
	o := vr.Begin() + len(runes)
	iscursor := sel.Contains(Region{o, o})
	if iscursor {
		fg = fg | caretStyle
		termbox.SetCell(x, y, ' ', fg, bg)
	}

	// restore original caretStyle before blink modification
	caretStyle = caretStyle
}