Skip to content

Commit

Permalink
Added translation visualization with terminal graphic iterface. kitty…
Browse files Browse the repository at this point in the history
…, sizel, iterm
  • Loading branch information
trezorg committed May 16, 2024
1 parent 5be3ffe commit 99e83c9
Show file tree
Hide file tree
Showing 11 changed files with 433 additions and 193 deletions.
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ require (
)

require (
github.com/BourgeoisBear/rasterm v1.1.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dolmen-go/kittyimg v0.0.0-20220904140504-22f6493b700f // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/stretchr/objx v0.1.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/BourgeoisBear/rasterm v1.1.1 h1:J94gv2pRv+G0jXj9Pf3jUk2qQtWPCiTsiRGxlXoQvgo=
github.com/BourgeoisBear/rasterm v1.1.1/go.mod h1:Ifd+To5s/uyUiYx+B4fxhS8lUNwNLSxDBjskmC5pEyw=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
Expand All @@ -6,6 +8,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dolmen-go/kittyimg v0.0.0-20220904140504-22f6493b700f h1:kei70IBuJLGrL+Ah46gX2jp2c+QWErJRa50TVO/j8Ig=
github.com/dolmen-go/kittyimg v0.0.0-20220904140504-22f6493b700f/go.mod h1:Bx/aNirksPWCgrgQ23kkHBXJLNIypTl9uLzmcKMrKnY=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand All @@ -27,6 +31,14 @@ github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0 h1:3UeQBvD0TFrlV
github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0/go.mod h1:IXCdmsXIht47RaVFLEdVnh1t+pgYtTAhQGj73kz+2DM=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
18 changes: 18 additions & 0 deletions internal/files/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,21 @@ func (f *FileDownloader) Download(url string) (string, error) {
func (f *FileDownloader) Remove(path string) error {
return os.Remove(path)
}

// DownloadBytes downloads file into bytes slice
func (f *FileDownloader) DownloadBytes(url string) ([]byte, error) {
resp, err := http.Get(url)
if err != nil {
return nil, fmt.Errorf("cannot read URL: %s, %w", url, err)
}
defer func() {
cErr := resp.Body.Close()
if cErr != nil {
slog.Error("cannot close response body", "error", cErr)
}
}()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("bad status: %s", resp.Status)
}
return io.ReadAll(resp.Body)
}
File renamed without changes.
53 changes: 53 additions & 0 deletions internal/visualizer/kittyterm/image.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package kittyterm

import (
"fmt"
"image"
_ "image/gif" // gif
_ "image/jpeg"
_ "image/png"
"io"
"log/slog"
"net/http"
"net/url"
"os"

"github.com/dolmen-go/kittyimg"
)

func showFromReader(r io.Reader) error {
img, _, err := image.Decode(r)
if err != nil {
return fmt.Errorf("cannot read image from reader. %w", err)
}
return kittyimg.Fprintln(os.Stdout, img)
}

func open(u *url.URL) error {
resp, err := http.Get(u.String())
if err != nil {
return fmt.Errorf("cannot read URL: %s, %w", u, err)
}
defer func() {
if cErr := resp.Body.Close(); cErr != nil {
slog.Error("cannot close response body", "error", cErr)
}
}()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("bad status: %s", resp.Status)
}
if err = showFromReader(resp.Body); err != nil {
return fmt.Errorf("cannot read image from url: %s. %w", u, err)
}
return nil
}

type Visualizer func(u *url.URL) error

func (v Visualizer) Show(u *url.URL) error {
return v(u)
}

func New() Visualizer {
return Visualizer(open)
}
128 changes: 128 additions & 0 deletions internal/visualizer/term/term.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package term

import (
"bytes"
"fmt"
"image"
"io"
"log/slog"
"net/http"
"net/url"
"os"

"github.com/BourgeoisBear/rasterm"
)

type Mode string

const (
Sixel Mode = "sixel"
Iterm Mode = "iterm"
Kitty Mode = "kitty"
Unknown Mode = "unknown"
)

func getMode() Mode {
if rasterm.IsKittyCapable() {
return Kitty
}
var err error
var ok bool
if ok, err = rasterm.IsSixelCapable(); ok {
return Sixel
}
if err != nil {
slog.Error("error checking sixel capable term", "error", err)
}

if rasterm.IsItermCapable() {
return Iterm
}
return Unknown
}

func showImage(w io.Writer, r io.Reader) error {
data, err := io.ReadAll(r)
if err != nil {
return err
}
reader := bytes.NewReader(data)
ln := int64(len(data))

img, format, err := image.Decode(reader)
if err != nil {
return err
}

_, err = reader.Seek(0, 0)
if err != nil {
return err
}

switch getMode() {
case Iterm:

// WEZ/ITERM SUPPORT ALL FORMATS, SO NO NEED TO RE-ENCODE TO PNG
err = rasterm.ItermCopyFileInline(w, reader, ln)

case Sixel:

if iPaletted, bOK := img.(*image.Paletted); bOK {
err = rasterm.SixelWriteImage(w, iPaletted)
} else {
slog.Debug("not paletted image, skipping")
}

case Kitty:

if format == "png" {
// fmt.Println("Kitty PNG Local File")
// eF := rasterm.KittyWritePNGLocal(w, fpath, rasterm.KittyImgOpts{})
// fmt.Println("\nKitty PNG Inline")
if err = rasterm.KittyCopyPNGInline(w, reader, rasterm.KittyImgOpts{}); err != nil {
return err
}
// err = errors.Join(eI, eF)
} else {
if err = rasterm.KittyWriteImage(w, img, rasterm.KittyImgOpts{}); err != nil {
return err
}
}

default:
return nil

}

fmt.Println("")
return err
}

func open(u *url.URL) error {
resp, err := http.Get(u.String())
if err != nil {
return fmt.Errorf("cannot read URL: %s, %w", u, err)
}
defer func() {
if cErr := resp.Body.Close(); cErr != nil {
slog.Error("cannot close response body", "error", cErr)
}
}()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("bad status: %s", resp.Status)
}
if err = showImage(os.Stdout, resp.Body); err != nil {
return fmt.Errorf("cannot read image from url: %s. %w", u, err)
}
return nil
}

type Visualizer func(u *url.URL) error

func (v Visualizer) Show(u *url.URL) error {
return v(u)
}

func New() Visualizer {
return Visualizer(open)
}
84 changes: 0 additions & 84 deletions pkg/api/helpers.go

This file was deleted.

Loading

0 comments on commit 99e83c9

Please sign in to comment.