Skip to content

Commit 854c6c0

Browse files
authored
Merge pull request #8 from dark0dave/feature/stringIssueFinder
feat(string): Issue finder
2 parents 9b3606a + 4029021 commit 854c6c0

7 files changed

Lines changed: 207 additions & 23 deletions

File tree

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"request": "attach",
1111
"mode": "remote",
1212
"port": 2345,
13-
"host": "0.0.0.0",
13+
"host": "127.0.0.1",
1414
"showLog": true
1515
}
1616
]

cmd/check-varriables.go

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package cmd
2+
3+
import (
4+
"io/fs"
5+
"path/filepath"
6+
"strings"
7+
8+
"github.com/charmbracelet/bubbles/table"
9+
tea "github.com/charmbracelet/bubbletea"
10+
"github.com/charmbracelet/lipgloss"
11+
"github.com/dark0dave/infinity_dialog/pkg/translation"
12+
"github.com/dark0dave/infinity_dialog/pkg/util"
13+
)
14+
15+
type checkVariables struct {
16+
table table.Model
17+
}
18+
19+
func NewCheck() checkVariables {
20+
columns := []table.Column{
21+
{Title: "Lang", Width: int(0.1 * float64(width))},
22+
{Title: "Filename", Width: int(0.2 * float64(width))},
23+
{Title: "Missing Ids", Width: int(0.5 * float64(width))},
24+
}
25+
26+
t := table.New(
27+
table.WithColumns(columns),
28+
table.WithFocused(true),
29+
table.WithHeight(height-7),
30+
)
31+
32+
s := table.DefaultStyles()
33+
s.Header = s.Header.
34+
BorderStyle(lipgloss.NormalBorder()).
35+
BorderForeground(lipgloss.Color("240")).
36+
BorderTop(true).
37+
BorderBottom(true).
38+
Bold(false)
39+
s.Selected = s.Selected.
40+
Foreground(lipgloss.Color("229")).
41+
Background(lipgloss.Color("57")).
42+
Bold(false)
43+
t.SetStyles(s)
44+
45+
return checkVariables{table: t}
46+
}
47+
48+
func difference(slice1 *[]string, slice2 *[]string) *[]string {
49+
diff := []string{}
50+
m := map[string]int{}
51+
52+
for _, s := range *slice1 {
53+
m[s] = 1
54+
}
55+
for _, s := range *slice2 {
56+
m[s] += 1
57+
}
58+
for k, v := range m {
59+
if v == 1 {
60+
diff = append(diff, k)
61+
}
62+
}
63+
return &diff
64+
}
65+
66+
func genRows(path string) *[]table.Row {
67+
rows := map[string]map[string][]string{}
68+
_ = filepath.WalkDir(path, func(path string, file fs.DirEntry, err error) error {
69+
if err != nil {
70+
return err
71+
}
72+
ext := filepath.Ext(file.Name())
73+
if !file.IsDir() && strings.ToLower(ext) == ".tra" {
74+
fileContent, err := util.ReadFileToSlice(path)
75+
if err != nil {
76+
return err
77+
}
78+
variables, err := translation.FromFileContents(fileContent)
79+
if err == nil {
80+
lang := strings.ToLower(filepath.Base(filepath.Dir(path)))
81+
if len(rows[lang]) == 0 {
82+
rows[lang] = map[string][]string{}
83+
}
84+
for _, v := range *variables {
85+
rows[lang][file.Name()] = append(rows[lang][file.Name()], v.Identifier)
86+
}
87+
}
88+
}
89+
return nil
90+
})
91+
largest := map[string][]string{}
92+
for _, files := range rows {
93+
for filename, vars := range files {
94+
if len(largest[filename]) < len(vars) {
95+
largest[filename] = vars
96+
}
97+
}
98+
}
99+
out := []table.Row{}
100+
for lang, _ := range rows {
101+
for filename, vars := range largest {
102+
size_for_lang := rows[lang][filename]
103+
for _, diff := range *difference(&vars, &size_for_lang) {
104+
out = append(out, table.Row{lang, filename, diff})
105+
}
106+
107+
}
108+
}
109+
return &out
110+
}
111+
112+
func (c checkVariables) Init() tea.Cmd { return nil }
113+
114+
func (c checkVariables) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
115+
switch msg := msg.(type) {
116+
case SelectedFilePath:
117+
rows := genRows(string(msg))
118+
c.table.SetRows(*rows)
119+
return c, nil
120+
case tea.WindowSizeMsg:
121+
h, w := docStyle.GetFrameSize()
122+
h1, w1 := baseStyle.GetFrameSize()
123+
h += h1
124+
w += w1
125+
if msg.Height > h {
126+
c.table.SetHeight(msg.Height - h)
127+
}
128+
if msg.Width > w {
129+
ratio := float64(msg.Width - w)
130+
c.table.SetColumns([]table.Column{
131+
{Title: "Lang", Width: int(0.1 * ratio)},
132+
{Title: "Filename", Width: int(0.2 * float64(width))},
133+
{Title: "Missing Ids", Width: int(0.5 * float64(width))},
134+
})
135+
c.table.SetWidth(int(ratio))
136+
}
137+
case tea.KeyMsg:
138+
switch msg.String() {
139+
case "q", "esc":
140+
return state.PreviousCommand(), nil
141+
case "ctrl+c", "ctrl+d":
142+
return c, tea.Quit
143+
case "enter":
144+
// TODO: Render missing vars
145+
}
146+
}
147+
var cmd tea.Cmd
148+
c.table, cmd = c.table.Update(msg)
149+
return c, cmd
150+
}
151+
152+
func (c checkVariables) View() string {
153+
body := []string{c.table.View(), "\n\n", c.table.HelpView(), " enter"}
154+
return baseStyle.Render(body...)
155+
}

cmd/initial.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ type initial struct {
3030

3131
func InitialModel() initial {
3232
items := []list.Item{
33-
item{title: "Traverse", desc: "Show tree of locations through a mod"},
33+
item{title: "Check", desc: "Check all strings in a mod/directory"},
3434
item{title: "Discover", desc: "Find all strings in a mod/directory"},
35+
item{title: "Traverse", desc: "Show tree of locations through a mod"},
3536
item{title: "View", desc: "View any Infinity Engine file or text file"},
3637
// TODO: Implement these
3738
// item{title: "Add", desc: "Add strings to tra"},
@@ -67,19 +68,25 @@ func (i initial) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
6768
return i, tea.Quit
6869
}
6970
switch i.list.SelectedItem().FilterValue() {
70-
case "Traverse":
71+
case "Check":
7172
d := NewDirectoryPicker(true, "Select a Mod Directory")
72-
f := NewDirectoryPicker(false, "Select an area to start")
73-
t := NewTree()
74-
v := NewFileView()
75-
state.SetNextCommand(d).SetNextCommand(f).SetNextCommand(t).SetNextCommand(v)
73+
c := NewCheck()
74+
// f := NewFileView()
75+
state.SetNextCommand(d).SetNextCommand(c)
7676
return state.SetAndGetNextCommand(i), SendSelectedFile(current_path)
7777
case "Discover":
7878
d := NewDirectoryPicker(true, "Select a Mod Directory")
7979
l := NewList()
8080
f := NewFileView()
8181
state.SetNextCommand(d).SetNextCommand(l).SetNextCommand(f)
8282
return state.SetAndGetNextCommand(i), SendSelectedFile(current_path)
83+
case "Traverse":
84+
d := NewDirectoryPicker(true, "Select a Mod Directory")
85+
f := NewDirectoryPicker(false, "Select an area to start")
86+
t := NewTree()
87+
v := NewFileView()
88+
state.SetNextCommand(d).SetNextCommand(f).SetNextCommand(t).SetNextCommand(v)
89+
return state.SetAndGetNextCommand(i), SendSelectedFile(current_path)
8390
case "View":
8491
d := NewDirectoryPicker(false, "Select a file to start")
8592
v := NewFileView()

cmd/list-varriables.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type listVariables struct {
2222

2323
func generateRows(path string, file fs.FileInfo) *[]table.Row {
2424
rows := []table.Row{}
25-
fileContent, err := util.ReadFileToString(path)
25+
fileContent, err := util.ReadFileToSlice(path)
2626
if err != nil {
2727
return &rows
2828
}

pkg/translation/varriables.go

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package translation
33
import (
44
"errors"
55
"fmt"
6+
"strings"
67
"unicode"
78

89
"golang.org/x/text/runes"
@@ -49,7 +50,8 @@ func ToAscii(str string) string {
4950
return result
5051
}
5152

52-
func FromString(s string, start int) (*Variable, error) {
53+
func FromString(s string) (*Variable, error) {
54+
start := 0
5355
v := &Variable{}
5456
for i := start; i < len(s); i++ {
5557
// 48->57 is 0-9 in ascii
@@ -88,24 +90,28 @@ func FromString(s string, start int) (*Variable, error) {
8890
return v, nil
8991
}
9092

91-
func FromFileContents(fileContents string) (*[]Variable, error) {
93+
func FromFileContents(fileContents *[]string) (*[]Variable, error) {
9294
out := []Variable{}
93-
for n := 0; n < len(fileContents); n++ {
95+
multi := false
96+
buffer := ""
97+
for _, line := range *fileContents {
9498
// Deal with single line comment
95-
if n+1 < len(fileContents) && fileContents[n] == '/' && fileContents[n+1] == '/' {
96-
n++
97-
for n < len(fileContents) {
98-
s := fileContents[n]
99-
if s == '\n' {
100-
break
99+
if len(line) > 2 && line[0:1] != "//" {
100+
if !multi && strings.Count(line, "~") != 2 {
101+
multi = true
102+
buffer += line
103+
} else if strings.Count(line, "~") == 1 {
104+
multi = false
105+
buffer += line
106+
if v, err := FromString(buffer); err == nil {
107+
out = append(out, *v)
108+
}
109+
} else {
110+
if v, err := FromString(line); err == nil {
111+
out = append(out, *v)
101112
}
102-
n++
103113
}
104114
}
105-
if v, err := FromString(fileContents, n); err == nil {
106-
out = append(out, *v)
107-
n = v.end()
108-
}
109115
}
110116
return &out, nil
111117
}

pkg/translation/varriables_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func TestString(t *testing.T) {
3939
},
4040
}
4141
for _, tc := range testCases {
42-
v, err := FromString(tc.testString, 0)
42+
v, err := FromString(tc.testString)
4343
if !errors.Is(err, tc.error) {
4444
t.Fatalf("Unexpected Error:\n%+v\n%+v", err, tc.error)
4545
}

pkg/util/read.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package util
22

33
import (
4+
"bufio"
45
"io/fs"
56
"os"
67
"path/filepath"
@@ -40,3 +41,18 @@ func ReadFileToString(path string) (string, error) {
4041
}
4142
return string(*data), nil
4243
}
44+
45+
func ReadFileToSlice(path string) (*[]string, error) {
46+
file, err := os.Open(path)
47+
if err != nil {
48+
return nil, err
49+
}
50+
defer file.Close()
51+
52+
lines := []string{}
53+
scanner := bufio.NewScanner(file)
54+
for scanner.Scan() {
55+
lines = append(lines, scanner.Text())
56+
}
57+
return &lines, scanner.Err()
58+
}

0 commit comments

Comments
 (0)