More work on porting diff kitten

This commit is contained in:
Kovid Goyal 2023-03-18 15:14:31 +05:30
parent e4d936b5ed
commit ee82cb5a52
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 160 additions and 14 deletions

View File

@ -163,17 +163,17 @@ func (self *Collection) Len() int { return len(self.all_paths) }
func (self *Collection) Items() int { return len(self.all_paths) } func (self *Collection) Items() int { return len(self.all_paths) }
func (self *Collection) Apply(f func(path, typ, data string) error) error { func (self *Collection) Apply(f func(path, typ, changed_path string) error) error {
for _, path := range self.all_paths { for _, path := range self.all_paths {
typ := self.type_map[path] typ := self.type_map[path]
data := "" changed_path := ""
switch typ { switch typ {
case "diff": case "diff":
data = self.changes[path] changed_path = self.changes[path]
case "rename": case "rename":
data = self.renames[path] changed_path = self.renames[path]
} }
if err := f(path, typ, data); err != nil { if err := f(path, typ, changed_path); err != nil {
return err return err
} }
} }

View File

@ -63,6 +63,7 @@ func get_ssh_file(hostname, rpath string) (string, error) {
} }
cmd = append(cmd, rpath) cmd = append(cmd, rpath)
c := exec.Command(cmd[0], cmd[1:]...) c := exec.Command(cmd[0], cmd[1:]...)
c.Stdin, c.Stderr = os.Stdin, os.Stderr
stdout, err := c.Output() stdout, err := c.Output()
if err != nil { if err != nil {
return "", fmt.Errorf("Failed to ssh into remote host %s to get file %s with error: %w", hostname, rpath, err) return "", fmt.Errorf("Failed to ssh into remote host %s to get file %s with error: %w", hostname, rpath, err)
@ -134,12 +135,15 @@ func main(_ *cli.Command, opts_ *Options, args []string) (rc int, err error) {
if err != nil { if err != nil {
return 1, err return 1, err
} }
h := Handler{left: left, right: right, lp: lp}
lp.OnInitialize = func() (string, error) { lp.OnInitialize = func() (string, error) {
lp.SetCursorVisible(false) lp.SetCursorVisible(false)
lp.AllowLineWrapping(false) lp.AllowLineWrapping(false)
lp.SetWindowTitle(fmt.Sprintf("%s vs. %s", left, right)) lp.SetWindowTitle(fmt.Sprintf("%s vs. %s", left, right))
h.initialize()
return "", nil return "", nil
} }
lp.OnWakeup = h.on_wakeup
lp.OnFinalize = func() string { lp.OnFinalize = func() string {
lp.SetCursorVisible(true) lp.SetCursorVisible(true)
return "" return ""

View File

@ -321,7 +321,9 @@ func do_diff(file1, file2 string, context_count int) (ans *Patch, err error) {
return return
} }
func diff(jobs []struct{ file1, file2 string }, context_count int) (ans map[string]*Patch, err error) { type diff_job struct{ file1, file2 string }
func diff(jobs []diff_job, context_count int) (ans map[string]*Patch, err error) {
ans = make(map[string]*Patch) ans = make(map[string]*Patch)
ctx := images.Context{} ctx := images.Context{}
type result struct { type result struct {

125
tools/cmd/diff/ui.go Normal file
View File

@ -0,0 +1,125 @@
// License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
package diff
import (
"fmt"
"kitty/tools/tui/loop"
)
var _ = fmt.Print
type ResultType int
const (
COLLECTION ResultType = iota
DIFF
HIGHLIGHT
)
type Reference struct {
}
type AsyncResult struct {
err error
rtype ResultType
collection *Collection
diff_map map[string]*Patch
}
type Handler struct {
async_results chan AsyncResult
left, right string
collection *Collection
diff_map map[string]*Patch
lp *loop.Loop
current_context_count, original_context_count int
added_count, removed_count int
}
func (self *Handler) calculate_statistics() {
self.added_count, self.removed_count = self.collection.added_count, self.collection.removed_count
for _, patch := range self.diff_map {
self.added_count += patch.added_count
self.removed_count += patch.removed_count
}
}
func (self *Handler) initialize() {
self.current_context_count = opts.Context
if self.current_context_count < 0 {
self.current_context_count = int(conf.Num_context_lines)
}
self.original_context_count = self.current_context_count
self.lp.SetDefaultColor(loop.FOREGROUND, conf.Foreground)
self.lp.SetDefaultColor(loop.CURSOR, conf.Foreground)
self.lp.SetDefaultColor(loop.BACKGROUND, conf.Background)
self.lp.SetDefaultColor(loop.SELECTION_BG, conf.Select_bg)
if !conf.Select_fg.IsNull {
self.lp.SetDefaultColor(loop.SELECTION_FG, conf.Select_fg.Color)
}
self.async_results = make(chan AsyncResult, 32)
go func() {
r := AsyncResult{}
r.collection, r.err = create_collection(self.left, self.right)
self.async_results <- r
self.lp.WakeupMainThread()
}()
}
func (self *Handler) generate_diff() {
self.diff_map = nil
jobs := make([]diff_job, 0, 32)
self.collection.Apply(func(path, typ, changed_path string) error {
if typ == "diff" {
if is_path_text(path) && is_path_text(changed_path) {
jobs = append(jobs, diff_job{path, changed_path})
}
}
return nil
})
go func() {
r := AsyncResult{rtype: DIFF}
r.diff_map, r.err = diff(jobs, self.current_context_count)
self.async_results <- r
self.lp.WakeupMainThread()
}()
}
func (self *Handler) on_wakeup() error {
var r AsyncResult
for {
select {
case r = <-self.async_results:
if r.err != nil {
return r.err
}
r.err = self.handle_async_result(r)
if r.err != nil {
return r.err
}
default:
return nil
}
}
}
func (self *Handler) handle_async_result(r AsyncResult) error {
switch r.rtype {
case COLLECTION:
self.collection = r.collection
self.generate_diff()
case DIFF:
self.diff_map = r.diff_map
self.calculate_statistics()
self.render_diff()
self.scroll_pos = 0
if self.restore_position != nil {
self.set_current_position(self.restore_position)
self.restore_position = nil
}
self.draw_screen()
case HIGHLIGHT:
}
return nil
}

View File

@ -22,6 +22,7 @@ import (
"kitty/tools/cli" "kitty/tools/cli"
"kitty/tools/config" "kitty/tools/config"
"kitty/tools/tty" "kitty/tools/tty"
"kitty/tools/tui/loop"
"kitty/tools/tui/subseq" "kitty/tools/tui/subseq"
"kitty/tools/utils" "kitty/tools/utils"
"kitty/tools/utils/style" "kitty/tools/utils/style"
@ -716,7 +717,7 @@ func ColorSettingsAsEscapeCodes(settings map[string]string) string {
w.WriteString(sharp) w.WriteString(sharp)
} }
set_default_color := func(name, defval string, num int) { set_default_color := func(name, defval string, num loop.DefaultColor) {
w.WriteString("\033]") w.WriteString("\033]")
defer func() { w.WriteString("\033\\") }() defer func() { w.WriteString("\033\\") }()
val, found := settings[name] val, found := settings[name]
@ -726,20 +727,20 @@ func ColorSettingsAsEscapeCodes(settings map[string]string) string {
if val != "" { if val != "" {
rgba, err := style.ParseColor(val) rgba, err := style.ParseColor(val)
if err == nil { if err == nil {
w.WriteString(strconv.Itoa(num)) w.WriteString(strconv.Itoa(int(num)))
w.WriteByte(';') w.WriteByte(';')
w.WriteString(rgba.AsRGBSharp()) w.WriteString(rgba.AsRGBSharp())
return return
} }
} }
w.WriteByte('1') w.WriteByte('1')
w.WriteString(strconv.Itoa(num)) w.WriteString(strconv.Itoa(int(num)))
} }
set_default_color("foreground", style.DefaultColors.Foreground, 10) set_default_color("foreground", style.DefaultColors.Foreground, loop.FOREGROUND)
set_default_color("background", style.DefaultColors.Background, 11) set_default_color("background", style.DefaultColors.Background, loop.BACKGROUND)
set_default_color("cursor", style.DefaultColors.Cursor, 12) set_default_color("cursor", style.DefaultColors.Cursor, loop.CURSOR)
set_default_color("selection_background", style.DefaultColors.SelectionBg, 17) set_default_color("selection_background", style.DefaultColors.SelectionBg, loop.SELECTION_BG)
set_default_color("selection_foreground", style.DefaultColors.SelectionFg, 19) set_default_color("selection_foreground", style.DefaultColors.SelectionFg, loop.SELECTION_FG)
w.WriteString("\033]4") w.WriteString("\033]4")
for i := 0; i < 256; i++ { for i := 0; i < 256; i++ {

View File

@ -381,3 +381,17 @@ func (self *Loop) Quit(exit_code int) {
self.exit_code = exit_code self.exit_code = exit_code
self.keep_going = false self.keep_going = false
} }
type DefaultColor int
const (
BACKGROUND DefaultColor = 11
FOREGROUND = 10
CURSOR = 12
SELECTION_BG = 17
SELECTION_FG = 18
)
func (self *Loop) SetDefaultColor(which DefaultColor, val style.RGBA) {
self.QueueWriteString(fmt.Sprintf("\033]%d;%s\033\\", int(which), val.AsRGBSharp()))
}