Skip to content

Commit

Permalink
feat: made the cli look nice
Browse files Browse the repository at this point in the history
  • Loading branch information
AbsoluteZero000 committed Oct 5, 2024
1 parent a34ae9e commit d36be7c
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 26 deletions.
14 changes: 14 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
module github.com/absolutezero000/encoding

go 1.22.5

require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/lipgloss v0.13.0 // indirect
github.com/charmbracelet/x/ansi v0.1.4 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/term v0.25.0 // indirect
)
26 changes: 26 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM=
github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
15 changes: 1 addition & 14 deletions huffman/huffman.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,7 @@ func Encode(root *Node, content string, verbose bool) (data []byte, bitLength in
compressionRatio := float64(len(bitString)) / float64(len(content)*8) * 100

if verbose {
fmt.Println("Original content:")
fmt.Println(content)

fmt.Println("\nHuffman Codes:")
for char, code := range codes {
fmt.Printf("Character: '%c', Code: %s\n", char, code)
}

fmt.Println("\nBit string before conversion:")
fmt.Println(bitString)

fmt.Printf("\nOriginal size: %d bits\n", len(content)*8)
fmt.Printf("Compressed size: %d bits\n", len(bitString))
fmt.Printf("Compression ratio: %.2f%%\n\n", compressionRatio)
printCompressionStats(content, codes, bitString, compressionRatio)
}

return encoded, len(bitString)
Expand Down
105 changes: 105 additions & 0 deletions huffman/huffman_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package huffman
import (
"bytes"
"container/heap"
"fmt"
"github.com/charmbracelet/lipgloss"
"math"
)

Expand Down Expand Up @@ -148,3 +150,106 @@ func bytesToBitString(data []byte, bitLength int) string {

return result.String()
}

func printCompressionStats(content string, codes map[rune]string, bitString string, compressionRatio float64) {
colors := struct {
primary string
secondary string
accent string
text string
border string
}{
primary: "#7D56F4",
secondary: "#2D3748",
accent: "#48BB78",
text: "#FAFAFA",
border: "#4A5568",
}

maxWidth := 100

baseStyle := lipgloss.NewStyle().
PaddingLeft(1).
PaddingRight(1).
BorderStyle(lipgloss.RoundedBorder())

headerStyle := lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(colors.text)).
Background(lipgloss.Color(colors.primary)).
PaddingLeft(2).
PaddingRight(2).
MarginBottom(1)

contentBoxStyle := baseStyle.
Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color(colors.border)).
Padding(1).
Width(maxWidth)

codeRowStyle := lipgloss.NewStyle().
PaddingLeft(1).
PaddingRight(1).
MarginBottom(1).
Width(maxWidth - 4)

statStyle := lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color(colors.accent))

fmt.Println(headerStyle.Render("Original Content"))
contentChunks := splitLongString(content, maxWidth-6)
formattedContent := lipgloss.JoinVertical(lipgloss.Left, contentChunks...)
fmt.Println(contentBoxStyle.Render(formattedContent))
fmt.Println()

fmt.Println(headerStyle.Render("Huffman Codes"))
codeBox := ""
for char, code := range codes {
var row string
if char == '\n' {
row = fmt.Sprintf("Character: '\\n' │ Code: %-20s", code)
} else {
row = fmt.Sprintf("Character: '%c' │ Code: %-20s", char, code)
}
codeBox += codeRowStyle.Render(row) + "\n"
}
fmt.Println(contentBoxStyle.Render(codeBox))
fmt.Println()

fmt.Println(headerStyle.Render("Bit String"))
bitStringChunks := splitLongString(bitString, maxWidth-6)
formattedBitString := lipgloss.JoinVertical(lipgloss.Left, bitStringChunks...)
fmt.Println(contentBoxStyle.Render(formattedBitString))
fmt.Println()

statsStyle := contentBoxStyle.
Width(50).
Align(lipgloss.Center)

stats := fmt.Sprintf(
"%s: %d bits\n%s: %d bits\n%s: %.2f%%",
statStyle.Render("Original size"),
len(content)*8,
statStyle.Render("Compressed size"),
len(bitString),
statStyle.Render("Compression ratio"),
compressionRatio,
)
fmt.Println(headerStyle.Render("Compression Statistics"))
fmt.Println(statsStyle.Render(stats))
}

func splitLongString(s string, chunkSize int) []string {
var chunks []string
runes := []rune(s)

for i := 0; i < len(runes); i += chunkSize {
end := i + chunkSize
if end > len(runes) {
end = len(runes)
}
chunks = append(chunks, string(runes[i:end]))
}
return chunks
}
19 changes: 7 additions & 12 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"flag"
"fmt"
"github.com/absolutezero000/encoding/huffman"
"log"
"os"
Expand All @@ -19,23 +18,19 @@ func main() {
log.Fatalf("Failed to read file %s: %v", *inputFile, err)
}

var encodedData []byte
var bitLength int
HuffmanTreeRoot := huffman.MakeTree(string(data))

encodedData, bitLength = huffman.Encode(HuffmanTreeRoot, string(data), *verbose)
_ = huffman.Decode(HuffmanTreeRoot, encodedData, bitLength, *verbose)
encodedData, _ := huffman.Encode(HuffmanTreeRoot, string(data), *verbose)

if *outputFile != "" {
if err := os.WriteFile(*outputFile, encodedData, 0600); err != nil {
log.Printf("Error writing to output file %s: %v", *outputFile, err)
}
}

treeData, _ := huffman.SerializeTree(HuffmanTreeRoot)

fmt.Println(treeData)

treeRoot, _ := huffman.DeserializeTree(treeData)
_ = huffman.Decode(treeRoot, encodedData, bitLength, *verbose)
// treeData, _ := huffman.SerializeTree(HuffmanTreeRoot)
//
// fmt.Println(treeData)
//
// treeRoot, _ := huffman.DeserializeTree(treeData)
// _ = huffman.Decode(treeRoot, encodedData, bitLength, *verbose)
}

0 comments on commit d36be7c

Please sign in to comment.