Skip to content

Commit 7906e5a

Browse files
authored
chore: enable MND linter and fix all magic number issues (#1180)
1 parent 481d409 commit 7906e5a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+338
-166
lines changed

.golangci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ linters:
9999
- makezero # finds slice declarations with non-zero initial length
100100
- mirror # reports wrong mirror patterns of bytes/strings usage
101101
# TODO enable
102-
# - mnd # detects magic numbers
102+
- mnd # detects magic numbers
103103
- musttag # enforces field tags in (un)marshaled structs
104104
- nakedret # finds naked returns in functions greater than a specified function length
105105
# TODO enable : Many reports. A bit hard to understand the nesting value.

src/cmd/main.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,25 @@ func Run(content embed.FS) {
4949
fmt.Println(variable.LastDirFile)
5050
return nil
5151
}
52-
fmt.Printf("%-*s %s\n", 55, lipgloss.NewStyle().Foreground(lipgloss.Color("#66b2ff")).
53-
Render("[Configuration file path]"), variable.ConfigFile)
54-
fmt.Printf("%-*s %s\n", 55, lipgloss.NewStyle().Foreground(lipgloss.Color("#ffcc66")).
55-
Render("[Hotkeys file path]"), variable.HotkeysFile)
56-
fmt.Printf("%-*s %s\n", 55, lipgloss.NewStyle().Foreground(lipgloss.Color("#66ff66")).
57-
Render("[Log file path]"), variable.LogFile)
58-
fmt.Printf("%-*s %s\n", 55, lipgloss.NewStyle().Foreground(lipgloss.Color("#ff9999")).
59-
Render("[Configuration directory path]"), variable.SuperFileMainDir)
60-
fmt.Printf("%-*s %s\n", 55, lipgloss.NewStyle().Foreground(lipgloss.Color("#ff66ff")).
61-
Render("[Data directory path]"), variable.SuperFileDataDir)
52+
fmt.Printf("%-*s %s\n",
53+
common.HelpKeyColumnWidth,
54+
lipgloss.NewStyle().Foreground(lipgloss.Color("#66b2ff")).Render("[Configuration file path]"),
55+
variable.ConfigFile,
56+
)
57+
fmt.Printf("%-*s %s\n",
58+
common.HelpKeyColumnWidth,
59+
lipgloss.NewStyle().Foreground(lipgloss.Color("#ffcc66")).Render("[Hotkeys file path]"),
60+
variable.HotkeysFile,
61+
)
62+
logStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#66ff66"))
63+
configStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#ff9999"))
64+
dataStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#ff66ff"))
65+
fmt.Printf("%-*s %s\n", common.HelpKeyColumnWidth,
66+
logStyle.Render("[Log file path]"), variable.LogFile)
67+
fmt.Printf("%-*s %s\n", common.HelpKeyColumnWidth,
68+
configStyle.Render("[Configuration directory path]"), variable.SuperFileMainDir)
69+
fmt.Printf("%-*s %s\n", common.HelpKeyColumnWidth,
70+
dataStyle.Render("[Data directory path]"), variable.SuperFileDataDir)
6271
return nil
6372
},
6473
Flags: []cli.Flag{
@@ -267,7 +276,7 @@ func shouldCheckForUpdate(now, last time.Time) bool {
267276
}
268277

269278
func checkAndNotifyUpdate() {
270-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
279+
ctx, cancel := context.WithTimeout(context.Background(), common.DefaultCLIContextTimeout)
271280
defer cancel()
272281

273282
resp, err := fetchLatestRelease(ctx)

src/internal/common/string_function.go

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,17 @@ import (
1616
"github.com/charmbracelet/x/ansi"
1717
)
1818

19+
// Size calculation constants
20+
const (
21+
KilobyteSize = 1000 // SI decimal unit
22+
KibibyteSize = 1024 // Binary unit
23+
TabWidth = 4 // Standard tab expansion width
24+
DefaultBufferSize = 1024 // Default buffer size for string operations
25+
NonBreakingSpace = 0xa0 // Unicode non-breaking space
26+
EscapeChar = 0x1b // ANSI escape character
27+
ASCIIMax = 0x7f // Maximum ASCII character value
28+
)
29+
1930
func TruncateText(text string, maxChars int, tails string) string {
2031
truncatedText := ansi.Truncate(text, maxChars-len(tails), "")
2132
if text != truncatedText {
@@ -51,6 +62,7 @@ func TruncateMiddleText(text string, maxChars int, tails string) string {
5162
return text
5263
}
5364

65+
//nolint:mnd // standard halving for center truncation
5466
halfEllipsisLength := (maxChars - 3) / 2
5567
// TODO : Use ansi.Substring to correctly handle ANSI escape codes
5668
truncatedText := text[:halfEllipsisLength] + tails + text[utf8.RuneCountInString(text)-halfEllipsisLength:]
@@ -116,12 +128,12 @@ func FormatFileSize(size int64) string {
116128

117129
// TODO : Remove duplication here
118130
if Config.FileSizeUseSI {
119-
unitIndex := int(math.Floor(math.Log(float64(size)) / math.Log(1000)))
120-
adjustedSize := float64(size) / math.Pow(1000, float64(unitIndex))
131+
unitIndex := int(math.Floor(math.Log(float64(size)) / math.Log(KilobyteSize)))
132+
adjustedSize := float64(size) / math.Pow(KilobyteSize, float64(unitIndex))
121133
return fmt.Sprintf("%.2f %s", adjustedSize, unitsDec[unitIndex])
122134
}
123-
unitIndex := int(math.Floor(math.Log(float64(size)) / math.Log(1024)))
124-
adjustedSize := float64(size) / math.Pow(1024, float64(unitIndex))
135+
unitIndex := int(math.Floor(math.Log(float64(size)) / math.Log(KibibyteSize)))
136+
adjustedSize := float64(size) / math.Pow(KibibyteSize, float64(unitIndex))
125137
return fmt.Sprintf("%.2f %s", adjustedSize, unitsBin[unitIndex])
126138
}
127139

@@ -132,7 +144,7 @@ func CheckAndTruncateLineLengths(text string, maxLength int) string {
132144

133145
for _, line := range lines {
134146
// Replace tabs with spaces
135-
expandedLine := strings.ReplaceAll(line, "\t", strings.Repeat(" ", 4))
147+
expandedLine := strings.ReplaceAll(line, "\t", strings.Repeat(" ", TabWidth))
136148
truncatedLine := ansi.Truncate(expandedLine, maxLength, "")
137149
result.WriteString(truncatedLine + "\n")
138150
}
@@ -180,7 +192,7 @@ func IsTextFile(filename string) (bool, error) {
180192
defer file.Close()
181193

182194
reader := bufio.NewReader(file)
183-
buffer := make([]byte, 1024)
195+
buffer := make([]byte, DefaultBufferSize)
184196
cnt, err := reader.Read(buffer)
185197
if err != nil && !errors.Is(err, io.EOF) {
186198
return false, err
@@ -204,7 +216,7 @@ func MakePrintableWithEscCheck(line string, allowEsc bool) string { //nolint: go
204216
}
205217
// It needs to be handled separately since considered a space,
206218
// It is multi-byte in UTF-8, But it has zero display width
207-
if r == 0xa0 {
219+
if r == NonBreakingSpace {
208220
sb.WriteRune(r)
209221
continue
210222
}
@@ -215,13 +227,13 @@ func MakePrintableWithEscCheck(line string, allowEsc bool) string { //nolint: go
215227
sb.WriteString(" ")
216228
continue
217229
}
218-
if r == 0x1b {
230+
if r == EscapeChar {
219231
if allowEsc {
220232
sb.WriteRune(r)
221233
}
222234
continue
223235
}
224-
if r > 0x7f {
236+
if r > ASCIIMax {
225237
if unicode.IsSpace(r) && utf8.RuneLen(r) > 1 {
226238
// See https://github.com/charmbracelet/x/issues/466
227239
// Space chacters spanning more than one bytes are not handled well by

src/internal/common/style_function.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ func GenerateNewFileTextInput() textinput.Model {
269269
t.PlaceholderStyle = ModalStyle
270270
t.Focus()
271271
t.CharLimit = 156
272+
//nolint:mnd // modal width minus padding
272273
t.Width = ModalWidth - 10
273274
return t
274275
}
@@ -304,7 +305,7 @@ func GeneratePinnedRenameTextInput(cursorPos int, defaultValue string) textinput
304305
ti.SetCursor(cursorPos)
305306
ti.Focus()
306307
ti.CharLimit = 156
307-
ti.Width = Config.SidebarWidth - 4
308+
ti.Width = Config.SidebarWidth - PanelPadding
308309
return ti
309310
}
310311

src/internal/common/ui_consts.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package common
2+
3+
import "time"
4+
5+
// Shared UI/layout constants to replace magic numbers flagged by mnd.
6+
const (
7+
HelpKeyColumnWidth = 55 // width of help key column in CLI help
8+
DefaultCLIContextTimeout = 5 * time.Second // default CLI context timeout for CLI ops
9+
10+
PanelPadding = 3 // rows reserved around file list (borders/header/footer)
11+
BorderPadding = 2 // rows/cols for outer border frame
12+
InnerPadding = 4 // cols for inner content padding (truncate widths)
13+
FooterGroupCols = 3 // columns per group in footer layout math
14+
15+
DefaultFilePanelWidth = 10 // default width for file panels
16+
FilePanelMax = 10 // max number of file panels supported
17+
MinWidthForRename = 18 // minimal width for rename input to render
18+
ResponsiveWidthThreshold = 95 // width breakpoint for layout behavior
19+
20+
HeightBreakA = 30 // responsive height tiers
21+
HeightBreakB = 35
22+
HeightBreakC = 40
23+
HeightBreakD = 45
24+
25+
ReRenderChunkDivisor = 100 // divisor for re-render throttling
26+
27+
FilePanelWidthUnit = 20 // width unit used to calculate max file panels
28+
DefaultPreviewTimeout = 500 * time.Millisecond // preview operation timeout
29+
30+
// File permissions
31+
ExtractedFileMode = 0644 // default permissions for extracted files
32+
ExtractedDirMode = 0755 // default permissions for extracted directories
33+
34+
// UI positioning
35+
CenterDivisor = 2 // divisor for centering UI elements
36+
)

src/internal/default_config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func defaultModelConfig(toggleDotFile, toggleFooter, firstUse bool,
3030
fileModel: fileModel{
3131
filePanels: filePanelSlice(firstPanelPaths),
3232
filePreview: preview.New(),
33-
width: 10,
33+
width: common.DefaultFilePanelWidth,
3434
},
3535
helpMenu: newHelpMenuModal(),
3636
promptModal: prompt.DefaultModel(prompt.PromptMinHeight, prompt.PromptMinWidth),

src/internal/file_operations_extract.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"golift.io/xtractr"
99

1010
"github.com/yorukot/superfile/src/config/icon"
11+
"github.com/yorukot/superfile/src/internal/common"
1112
"github.com/yorukot/superfile/src/internal/ui/processbar"
1213
)
1314

@@ -20,8 +21,8 @@ func extractCompressFile(src, dest string, processBar *processbar.Model) error {
2021
x := &xtractr.XFile{
2122
FilePath: src,
2223
OutputDir: dest,
23-
FileMode: 0644,
24-
DirMode: 0755,
24+
FileMode: common.ExtractedFileMode,
25+
DirMode: common.ExtractedDirMode,
2526
}
2627

2728
_, _, _, err = xtractr.ExtractFile(x)

src/internal/function.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ func getTypeOrderingFunc(elements []element, reversed bool) sliceOrderFunc {
242242
}
243243

244244
func panelElementHeight(mainPanelHeight int) int {
245-
return mainPanelHeight - 3
245+
return mainPanelHeight - common.PanelPadding
246246
}
247247

248248
// TODO : replace usage of this with slices.contains
@@ -291,6 +291,7 @@ func renameIfDuplicate(destination string) (string, error) {
291291

292292
// Extract base name without existing suffix
293293
counter := 1
294+
//nolint:mnd // 3 = full match + 2 capture groups
294295
if match := suffixRegexp.FindStringSubmatch(name); len(match) == 3 {
295296
name = match[1] // base name without (N)
296297
if num, err := strconv.Atoi(match[2]); err == nil {

src/internal/handle_file_operations.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,10 @@ func (m *model) panelItemRename() {
9797
m.fileModel.renaming = true
9898
panel.renaming = true
9999
m.firstTextInput = true
100-
panel.rename = common.GenerateRenameTextInput(m.fileModel.width-4, cursorPos, panel.element[panel.cursor].name)
100+
panel.rename = common.GenerateRenameTextInput(
101+
m.fileModel.width-common.InnerPadding,
102+
cursorPos,
103+
panel.element[panel.cursor].name)
101104
}
102105

103106
func (m *model) getDeleteCmd(permDelete bool) tea.Cmd {

src/internal/handle_modal.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"path/filepath"
77
"strings"
88

9+
"github.com/yorukot/superfile/src/internal/common"
910
"github.com/yorukot/superfile/src/internal/utils"
1011
)
1112

@@ -160,7 +161,7 @@ func (m *model) helpMenuListUp() {
160161
// Similarly, we use max(..., 0) to ensure the renderIndex doesn't become negative,
161162
// which can happen if the number of items is less than the view height.
162163
// This prevents a potential out-of-bounds panic during rendering.
163-
m.helpMenu.renderIndex = max(len(m.helpMenu.filteredData)-(m.helpMenu.height-4), 0)
164+
m.helpMenu.renderIndex = max(len(m.helpMenu.filteredData)-(m.helpMenu.height-common.InnerPadding), 0)
164165
}
165166
}
166167

@@ -189,7 +190,7 @@ func (m *model) helpMenuListDown() {
189190
m.helpMenu.renderIndex++
190191
}
191192
// Clamp renderIndex to bottom.
192-
bottom := len(m.helpMenu.filteredData) - (m.helpMenu.height - 4)
193+
bottom := len(m.helpMenu.filteredData) - (m.helpMenu.height - common.InnerPadding)
193194
if bottom < 0 {
194195
bottom = 0
195196
}

0 commit comments

Comments
 (0)