189 lines
3.5 KiB
Go
189 lines
3.5 KiB
Go
package codeview
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"loov.dev/lensm/internal/comments"
|
|
"loov.dev/lensm/internal/disasm"
|
|
)
|
|
|
|
type View uint8
|
|
|
|
const (
|
|
ViewNone View = iota
|
|
ViewGoAsm
|
|
ViewNativeAsm
|
|
ViewSource
|
|
)
|
|
|
|
// CommentView maps a pane to its comment-store view. ok is false for
|
|
// CodeViewNone, which has no comments.
|
|
func (v View) CommentView() (view comments.View, ok bool) {
|
|
switch v {
|
|
case ViewGoAsm:
|
|
return comments.ViewGoAsm, true
|
|
case ViewNativeAsm:
|
|
return comments.ViewNativeAsm, true
|
|
case ViewSource:
|
|
return comments.ViewSource, true
|
|
default:
|
|
return "", false
|
|
}
|
|
}
|
|
|
|
type TextSelection struct {
|
|
View View
|
|
Anchor int
|
|
Head int
|
|
Active bool
|
|
}
|
|
|
|
func (s *TextSelection) Clear() {
|
|
*s = TextSelection{}
|
|
}
|
|
|
|
func (s *TextSelection) Begin(view View, line int, extend bool) {
|
|
if view == ViewNone || line < 0 {
|
|
s.Clear()
|
|
return
|
|
}
|
|
if !extend || !s.Active || s.View != view {
|
|
s.View = view
|
|
s.Anchor = line
|
|
}
|
|
s.Head = line
|
|
s.Active = true
|
|
}
|
|
|
|
func (s *TextSelection) Extend(view View, line int) {
|
|
if !s.Active || s.View != view || line < 0 {
|
|
return
|
|
}
|
|
s.Head = line
|
|
}
|
|
|
|
func (s TextSelection) Range() (from, to int, ok bool) {
|
|
if !s.Active {
|
|
return 0, 0, false
|
|
}
|
|
from, to = s.Anchor, s.Head
|
|
if from > to {
|
|
from, to = to, from
|
|
}
|
|
return from, to, true
|
|
}
|
|
|
|
func (s TextSelection) Contains(view View, line int) bool {
|
|
if s.View != view {
|
|
return false
|
|
}
|
|
from, to, ok := s.Range()
|
|
return ok && from <= line && line <= to
|
|
}
|
|
|
|
type sourceTextRow struct {
|
|
Text string
|
|
}
|
|
|
|
func sourceTextRows(code *disasm.Code) []sourceTextRow {
|
|
if code == nil {
|
|
return nil
|
|
}
|
|
var rows []sourceTextRow
|
|
for sourceIndex, source := range code.Source {
|
|
if sourceIndex > 0 {
|
|
rows = append(rows, sourceTextRow{})
|
|
}
|
|
rows = append(rows, sourceTextRow{Text: "// " + source.File})
|
|
for blockIndex, block := range source.Blocks {
|
|
if blockIndex > 0 {
|
|
rows = append(rows, sourceTextRow{})
|
|
}
|
|
for _, line := range block.Lines {
|
|
rows = append(rows, sourceTextRow{Text: line})
|
|
}
|
|
}
|
|
}
|
|
return rows
|
|
}
|
|
|
|
// sourceRowCount mirrors the rows produced by sourceTextRows without
|
|
// building them; it runs on every pointer event.
|
|
func sourceRowCount(code *disasm.Code) int {
|
|
if code == nil {
|
|
return 0
|
|
}
|
|
count := 0
|
|
for sourceIndex, source := range code.Source {
|
|
if sourceIndex > 0 {
|
|
count++
|
|
}
|
|
count++
|
|
for blockIndex, block := range source.Blocks {
|
|
if blockIndex > 0 {
|
|
count++
|
|
}
|
|
count += len(block.Lines)
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
func sourceRowAtY(code *disasm.Code, scroll float32, lineHeight int, y float32) int {
|
|
if code == nil || lineHeight <= 0 {
|
|
return -1
|
|
}
|
|
relative := y - scroll
|
|
if relative < 0 {
|
|
return -1
|
|
}
|
|
row := int(relative / float32(lineHeight))
|
|
if row < 0 || row >= sourceRowCount(code) {
|
|
return -1
|
|
}
|
|
return row
|
|
}
|
|
|
|
func (s TextSelection) Text(code *disasm.Code) string {
|
|
if code == nil {
|
|
return ""
|
|
}
|
|
from, to, ok := s.Range()
|
|
if !ok {
|
|
return ""
|
|
}
|
|
|
|
var lines []string
|
|
switch s.View {
|
|
case ViewGoAsm, ViewNativeAsm:
|
|
if from < 0 {
|
|
from = 0
|
|
}
|
|
if to >= len(code.Insts) {
|
|
to = len(code.Insts) - 1
|
|
}
|
|
for i := from; i <= to; i++ {
|
|
text := code.Insts[i].Text
|
|
if s.View == ViewNativeAsm {
|
|
text = strings.ToUpper(code.Insts[i].NativeText)
|
|
}
|
|
lines = append(lines, text)
|
|
}
|
|
case ViewSource:
|
|
rows := sourceTextRows(code)
|
|
if from < 0 {
|
|
from = 0
|
|
}
|
|
if to >= len(rows) {
|
|
to = len(rows) - 1
|
|
}
|
|
for i := from; i <= to; i++ {
|
|
lines = append(lines, rows[i].Text)
|
|
}
|
|
}
|
|
if len(lines) == 0 {
|
|
return ""
|
|
}
|
|
return strings.Join(lines, "\n") + "\n"
|
|
}
|