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
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) 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 {
typ := self.type_map[path]
data := ""
changed_path := ""
switch typ {
case "diff":
data = self.changes[path]
changed_path = self.changes[path]
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
}
}

View File

@@ -63,6 +63,7 @@ func get_ssh_file(hostname, rpath string) (string, error) {
}
cmd = append(cmd, rpath)
c := exec.Command(cmd[0], cmd[1:]...)
c.Stdin, c.Stderr = os.Stdin, os.Stderr
stdout, err := c.Output()
if err != nil {
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 {
return 1, err
}
h := Handler{left: left, right: right, lp: lp}
lp.OnInitialize = func() (string, error) {
lp.SetCursorVisible(false)
lp.AllowLineWrapping(false)
lp.SetWindowTitle(fmt.Sprintf("%s vs. %s", left, right))
h.initialize()
return "", nil
}
lp.OnWakeup = h.on_wakeup
lp.OnFinalize = func() string {
lp.SetCursorVisible(true)
return ""

View File

@@ -321,7 +321,9 @@ func do_diff(file1, file2 string, context_count int) (ans *Patch, err error) {
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)
ctx := images.Context{}
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
}