-
-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/wish #33
Conversation
WalkthroughWalkthroughThe changes to the project include the addition of a GitHub Actions workflow for a Go project, introducing SSH server functionality to start and manage remote interactions with Changes
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
go.sum
is excluded by!**/*.sum
Files selected for processing (15)
- .github/workflows/go.yml (1 hunks)
- cmd/root.go (1 hunks)
- cmd/server.go (1 hunks)
- go.mod (1 hunks)
- main.go (1 hunks)
- utils/commenter/commenter.go (1 hunks)
- utils/commenter/commenter_test.go (1 hunks)
- utils/modfile/modfile.go (1 hunks)
- utils/modfile/modfile_test.go (1 hunks)
- utils/server/server.go (1 hunks)
- utils/tui/model.go (1 hunks)
- utils/tui/modelutils/file.go (1 hunks)
- utils/tui/modelutils/option.go (1 hunks)
- utils/tui/modelutils/selectorutils.go (1 hunks)
- utils/tui/modelutils/text.go (1 hunks)
Files not summarized due to errors (11)
- utils/server/server.go: Error: Server error. Please try again later.
- cmd/root.go: Error: Server error. Please try again later.
- go.mod: Error: Server error. Please try again later.
- utils/tui/modelutils/selectorutils.go: Error: Server error. Please try again later.
- utils/tui/modelutils/option.go: Error: Server error. Please try again later.
- utils/tui/modelutils/text.go: Error: Server error. Please try again later.
- utils/tui/model.go: Error: Server error. Please try again later.
- utils/commenter/commenter_test.go: Error: Server error. Please try again later.
- cmd/server.go: Error: Server error. Please try again later.
- main.go: Error: Server error. Please try again later.
- utils/commenter/commenter.go: Error: Server error. Please try again later.
Files not reviewed due to errors (6)
- main.go (Error: Server error. Please try again later.)
- utils/commenter/commenter_test.go (Error: Server error. Please try again later.)
- utils/commenter/commenter.go (Error: Server error. Please try again later.)
- utils/tui/modelutils/option.go (Error: Server error. Please try again later.)
- cmd/root.go (no review received)
- utils/tui/model.go (no review received)
Files skipped from review due to trivial changes (1)
- .github/workflows/go.yml
Additional comments not posted (20)
go.mod (1)
5-15
: Review of module dependencies: All dependencies appear correctly specified.The dependencies listed are appropriate for the project, and there are no signs of unnecessary or outdated packages.
Also applies to: 17-49
cmd/server.go (1)
20-33
: Review ofserverCmd
CLI command: Correctly defined and initialized.The
serverCmd
is well-defined with appropriate descriptions and is correctly registered within the command tree.utils/tui/modelutils/text.go (1)
16-16
: Add documentation for the newIsLabel
field.The new field
IsLabel
has been added to theLabelInput
struct to distinguish between labels and line numbers. It's a good practice to add a comment explaining the purpose and usage of this field for better code readability and maintenance.utils/modfile/modfile.go (9)
1-14
: LGTM!The package declaration and imports look good.
16-25
: LGTM!The
Config
struct is well-defined.
147-152
: LGTM!The
shouldProcessLine
function is well-implemented.
257-276
: LGTM!The
createBackup
function is well-implemented.
278-283
: LGTM!The
restoreBackup
function is well-implemented.
285-308
: LGTM!The
findLines
function is well-implemented.
310-381
: LGTM!The
selectCommentChars
function is well-implemented.
383-413
: LGTM!The
CommentChars
map is comprehensive and well-defined.
27-42
: Add a default case to handle unsupported actions.The
setModFunc
function should handle unsupported actions explicitly.- return nil, fmt.Errorf("invalid action. Please provide 'comment', 'uncomment', or 'toggle'") + default: + return nil, fmt.Errorf("invalid action: %s. Please provide 'comment', 'uncomment', or 'toggle'", action)Likely invalid or redundant comment.
utils/modfile/modfile_test.go (8)
10-98
: LGTM!The
TestWriteChanges
function is well-implemented and covers various scenarios.
100-183
: LGTM!The
TestPrintChanges
function is well-implemented and covers various scenarios.
187-345
: LGTM!The
TestChangeFile
function is well-implemented and covers various scenarios.
349-362
: LGTM!The
TestCreateBackup
function is well-implemented.
364-380
: LGTM!The
TestRestoreBackup
function is well-implemented.
382-401
: LGTM!The
TestSelectCommentChars
function is well-implemented and covers various scenarios.
402-424
: LGTM!The
TestFindLines
function is well-implemented and covers various scenarios.
426-452
: LGTM!The utility functions are well-implemented and aid in setting up and cleaning up test files.
func executeRemoteCommand(remotePath string) { | ||
parts := strings.SplitN(remotePath, "@", 2) | ||
if len(parts) != 2 { | ||
fmt.Println("Invalid format. Usage: tgcom -w user@remote:/path/folder") | ||
os.Exit(1) | ||
} | ||
|
||
userHost := parts[0] | ||
pathParts := strings.SplitN(parts[1], ":", 2) | ||
if len(pathParts) != 2 { | ||
fmt.Println("Invalid format. Usage: tgcom -w user@remote:/path/folder") | ||
os.Exit(1) | ||
} | ||
|
||
host := pathParts[0] | ||
dir := pathParts[1] | ||
|
||
sshCmd := "ssh" | ||
sshArgs := []string{"-t", "-p", "2222", userHost + "@" + host, "tgcom", dir} | ||
|
||
// Start SSH command with PTY | ||
if err := startSSHWithPTY(sshCmd, sshArgs); err != nil { | ||
log.Fatalf("Error starting SSH with PTY: %v", err) | ||
} | ||
} | ||
|
||
func startSSHWithPTY(cmd string, args []string) error { | ||
// Create SSH command | ||
sshCommand := exec.Command(cmd, args...) | ||
|
||
// Start PTY | ||
ptmx, err := pty.Start(sshCommand) | ||
if err != nil { | ||
return fmt.Errorf("failed to start PTY: %w", err) | ||
} | ||
defer ptmx.Close() | ||
|
||
// Set terminal attributes | ||
oldState, err := term.MakeRaw(int(os.Stdin.Fd())) | ||
if err != nil { | ||
return fmt.Errorf("failed to make terminal raw: %w", err) | ||
} | ||
defer term.Restore(int(os.Stdin.Fd()), oldState) | ||
|
||
// Resize PTY to current terminal size | ||
if err := resizePTY(ptmx); err != nil { | ||
return fmt.Errorf("failed to resize PTY: %w", err) | ||
} | ||
|
||
// Forward input to PTY | ||
go func() { | ||
_, _ = io.Copy(ptmx, os.Stdin) | ||
}() | ||
|
||
// Forward output from PTY | ||
go func() { | ||
_, _ = io.Copy(os.Stdout, ptmx) | ||
}() | ||
|
||
// Handle PTY signals and resize | ||
go func() { | ||
ch := make(chan os.Signal, 1) | ||
signal.Notify(ch, syscall.SIGWINCH) | ||
for range ch { | ||
if err := resizePTY(ptmx); err != nil { | ||
log.Printf("Error resizing PTY: %v", err) | ||
} | ||
} | ||
}() | ||
|
||
// Wait for SSH command to finish | ||
if err := sshCommand.Wait(); err != nil { | ||
return fmt.Errorf("SSH command failed: %w", err) | ||
} | ||
|
||
// Wait a bit before exiting to ensure all output is processed | ||
time.Sleep(100 * time.Millisecond) | ||
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review of SSH command execution functions: Enhance error handling and resource management.
- Resource Management: Ensure that all resources like PTY and terminal states are properly managed. Consider adding more robust cleanup in error scenarios.
- Error Handling: The error handling could be more descriptive, providing more context about the failures.
Refactor the error handling to provide more detailed error messages and ensure resources are cleaned up even when errors occur.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
Outside diff range and nitpick comments (2)
cmd/root.go (2)
Line range hint
154-191
: Add error handling for writer flush operation.The function lacks error handling for the writer flush operation at the end.
- return writer.Flush() + if err := writer.Flush(); err != nil { + return fmt.Errorf("failed to flush writer: %w", err) + } + return nil
Line range hint
168-199
: Add error handling for writer flush operation inwriteChanges
.Ensure that the
writeChanges
function includes error handling for the writer flush operation.- return writer.Flush() + if err := writer.Flush(); err != nil { + return fmt.Errorf("failed to flush writer: %w", err) + } + return nil
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
go.sum
is excluded by!**/*.sum
Files selected for processing (15)
- .github/workflows/go.yml (1 hunks)
- cmd/root.go (1 hunks)
- cmd/server.go (1 hunks)
- go.mod (1 hunks)
- main.go (1 hunks)
- utils/commenter/commenter.go (1 hunks)
- utils/commenter/commenter_test.go (1 hunks)
- utils/modfile/modfile.go (1 hunks)
- utils/modfile/modfile_test.go (1 hunks)
- utils/server/server.go (1 hunks)
- utils/tui/model.go (1 hunks)
- utils/tui/modelutils/file.go (1 hunks)
- utils/tui/modelutils/option.go (1 hunks)
- utils/tui/modelutils/selectorutils.go (1 hunks)
- utils/tui/modelutils/text.go (1 hunks)
Files not summarized due to errors (5)
- main.go: Error: Server error. Please try again later.
- utils/tui/modelutils/file.go: Error: Server error. Please try again later.
- utils/server/server.go: Error: Server error. Please try again later.
- cmd/root.go: Error: Server error. Please try again later.
- utils/tui/modelutils/option.go: Error: Server error. Please try again later.
Files not reviewed due to errors (1)
- utils/modfile/modfile_test.go (no review received)
Files skipped from review due to trivial changes (3)
- .github/workflows/go.yml
- go.mod
- utils/commenter/commenter_test.go
Additional context used
golangci-lint
utils/commenter/commenter.go
[warning] 61-61: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block
(revive)
utils/tui/modelutils/option.go
[warning] 63-63: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block
(revive)
[warning] 5-5: exported: exported type ModeSelector should have comment or be unexported
(revive)
90-90: unnecessary trailing newline
(whitespace)
65-65: unnecessary leading newline
(whitespace)
utils/tui/modelutils/file.go
[warning] 11-11: exported: exported type FilesSelector should have comment or be unexported
(revive)
[warning] 23-23: exported: exported function InitialModel should have comment or be unexported
(revive)
utils/tui/model.go
142-142: unnecessary trailing newline
(whitespace)
84-84: ineffectual assignment to counter
(ineffassign)
118-118: ineffectual assignment to counter
(ineffassign)
utils/modfile/modfile.go
60-60: Error return value of
file.Close
is not checked(errcheck)
103-103: Error return value of
tmpFile.Close
is not checked(errcheck)
108-108: Error return value of
tmpFile.Close
is not checked(errcheck)
109-109: Error return value of
os.Remove
is not checked(errcheck)
116-116: Error return value of
tmpFile.Close
is not checked(errcheck)
117-117: Error return value of
os.Remove
is not checked(errcheck)
123-123: Error return value of
tmpFile.Close
is not checked(errcheck)
124-124: Error return value of
os.Remove
is not checked(errcheck)
130-130: Error return value of
os.Remove
is not checked(errcheck)
141-141: Error return value of
os.Remove
is not checked(errcheck)
[warning] 300-300: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block
(revive)
41-41: unnecessary trailing newline
(whitespace)
198-198: unnecessary leading newline
(whitespace)
230-230: unnecessary leading newline
(whitespace)
241-241: unnecessary trailing newline
(whitespace)
utils/modfile/modfile_test.go
[medium] 373-373: G306: Expect WriteFile permissions to be 0600 or less
(gosec)
[warning] 43-43: unused-parameter: parameter 'commentChars' seems to be unused, consider removing or renaming it as _
(revive)
[warning] 54-54: unused-parameter: parameter 'commentChars' seems to be unused, consider removing or renaming it as _
(revive)
[warning] 133-133: unused-parameter: parameter 'commentChars' seems to be unused, consider removing or renaming it as _
(revive)
[warning] 144-144: unused-parameter: parameter 'commentChars' seems to be unused, consider removing or renaming it as _
(revive)
187-187: unnecessary leading newline
(whitespace)
347-347: unnecessary trailing newline
(whitespace)
Additional comments not posted (42)
main.go (1)
1-9
: LGTM!The
main.go
file correctly initializes the main command execution for the application.utils/tui/modelutils/option.go (2)
14-21
: LGTM!The
NewModeSelector
function correctly initializes a newModeSelector
instance.
23-25
: LGTM!The
Init
function correctly initializes theModeSelector
instance.utils/tui/modelutils/selectorutils.go (7)
11-18
: LGTM!The
Contains
function is implemented correctly.
20-28
: LGTM!The
Remove
function is implemented correctly.
30-36
: LGTM!The
IsDirectory
function is implemented correctly.
38-51
: LGTM!The
GetParentDirectory
function is implemented correctly.
53-65
: LGTM!The
GetPathOfEntry
function is implemented correctly.
67-93
: LGTM!The
moveToNextDir
function is implemented correctly.
95-127
: LGTM!The
moveToPreviousDir
function is implemented correctly.cmd/server.go (5)
20-28
: LGTM!The
serverCmd
Cobra command is implemented correctly.
30-33
: LGTM!The
init
function is implemented correctly.
35-59
: LGTM!The
executeRemoteCommand
function is implemented correctly.
61-113
: LGTM!The
startSSHWithPTY
function is implemented correctly.
116-125
: LGTM!The
resizePTY
function is implemented correctly.utils/tui/modelutils/text.go (6)
21-28
: LGTM!The
NewLabelInput
function is implemented correctly.
30-32
: LGTM!The
LabelInput.Init
function is implemented correctly.
34-60
: LGTM!The
LabelInput.Update
function is implemented correctly.
62-80
: LGTM!The
LabelInput.View
function is implemented correctly.
83-87
: LGTM!The
StartTicker
function is implemented correctly.
91-133
: LGTM!The
validateInput
function is implemented correctly.utils/tui/modelutils/file.go (5)
23-50
: LGTM!The
InitialModel
function is implemented correctly.Tools
golangci-lint
[warning] 23-23: exported: exported function InitialModel should have comment or be unexported
(revive)
52-54
: LGTM!The
FilesSelector.Init
function is implemented correctly.
56-102
: LGTM!The
FilesSelector.Update
function is implemented correctly.
104-140
: LGTM!The
FilesSelector.View
function is implemented correctly.
142-163
: LGTM!The
paint
function is implemented correctly.cmd/root.go (7)
40-45
: LGTM!The code changes are approved.
76-84
: LGTM!The code changes are approved.
129-157
: LGTM!The code changes are approved.
159-173
: LGTM!The code changes are approved.
147-152
: LGTM!The code changes are approved.
20-37
: Verify the existence and correctness ofexecuteRemoteCommand
.The
executeRemoteCommand
function is invoked but not defined in this file. Ensure it exists and is correctly implemented.Verification successful
The
executeRemoteCommand
function is correctly implemented and exists incmd/server.go
.
cmd/server.go:35-59
: The function splits theremotePath
string, validates its format, constructs SSH command arguments, and starts an SSH session with a pseudo-terminal.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the existence and correctness of `executeRemoteCommand`. # Test: Search for the function definition. Expect: Function definition exists. rg --type go --pcre2 'func executeRemoteCommand'Length of output: 111
Script:
#!/bin/bash # Description: Retrieve the implementation of `executeRemoteCommand` function for review. # Extract the function implementation from cmd/server.go ast-grep --lang go --pattern 'func executeRemoteCommand($_) { $$$ }' cmd/server.goLength of output: 1187
47-74
: Verify the existence and correctness ofserverCmd
.The
serverCmd
variable is added to the root command but not defined in this file. Ensure it exists and is correctly implemented.Verification successful
The
serverCmd
is correctly implemented and the initial review comment is accurate.
- The
serverCmd
variable is defined incmd/server.go
and correctly set up as acobra.Command
.- The
Run
function inserverCmd
callsserver.StartServer()
, which is defined inutils/server/server.go
.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the existence and correctness of `serverCmd`. # Test: Search for the variable definition. Expect: Variable definition exists. rg --type go --pcre2 'var serverCmd'Length of output: 84
Script:
#!/bin/bash # Description: Extract and verify the implementation of `serverCmd` in `cmd/server.go`. # Extract the implementation of `serverCmd`. ast-grep --lang go --pattern $'var serverCmd = &cobra.Command{ $$$ }' cmd/server.goLength of output: 457
Script:
#!/bin/bash # Description: Verify the existence and correctness of `server.StartServer`. # Test: Search for the function definition. Expect: Function definition exists. rg --type go --pcre2 'func StartServer'Length of output: 85
utils/tui/model.go (5)
13-29
: LGTM!The code changes are approved.
31-34
: LGTM!The code changes are approved.
146-165
: LGTM!The code changes are approved.
201-216
: LGTM!The code changes are approved.
168-199
: Add error handling for writer flush operation inwriteChanges
.Ensure that the
writeChanges
function includes error handling for the writer flush operation.- return writer.Flush() + if err := writer.Flush(); err != nil { + return fmt.Errorf("failed to flush writer: %w", err) + } + return nilLikely invalid or redundant comment.
utils/modfile/modfile.go (4)
16-25
: LGTM!The code changes are approved.
27-42
: LGTM!The code changes are approved.
Tools
golangci-lint
41-41: unnecessary trailing newline
(whitespace)
147-152
: LGTM!The code changes are approved.
193-223
: Remove unnecessary newlines.There are some unnecessary leading and trailing newlines in the
printChanges
function.- fmt.Printf("%d: %s -> %s\n", currentLine, lineContent, modified) + fmt.Printf("%d: %s -> %s", currentLine, lineContent, modified)Likely invalid or redundant comment.
Tools
golangci-lint
198-198: unnecessary leading newline
(whitespace)
utils/tui/modelutils/option.go
Outdated
func (m ModeSelector) View() string { | ||
if len(m.Choices) == 2 { | ||
s := paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n" | ||
for i, choice := range m.Choices { | ||
cursor := " " | ||
if m.cursor == i { | ||
cursor = ">" | ||
} | ||
s += cursor + " " + choice + "\n" | ||
} | ||
return s | ||
} else { | ||
s := "" | ||
switch m.Speed { | ||
|
||
case "Slow mode": | ||
s += paint("silver").Render("Select action for file: "+m.File) + "\n\n" | ||
for i, choice := range m.Choices { | ||
cursor := " " | ||
if m.cursor == i { | ||
cursor = ">" | ||
} | ||
s += cursor + " " + choice + "\n" | ||
} | ||
|
||
case "Fast mode": | ||
s += paint("silver").Render("Select action:") + "\n\n" | ||
for i, choice := range m.Choices { | ||
cursor := " " | ||
if m.cursor == i { | ||
cursor = ">" | ||
} | ||
s += cursor + " " + choice + "\n" | ||
} | ||
} | ||
return s + paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down") | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix unnecessary leading and trailing newlines.
The function should be refactored to remove unnecessary leading and trailing newlines.
- if len(m.Choices) == 2 {
- s := paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n"
- for i, choice := range m.Choices {
- cursor := " "
- if m.cursor == i {
- cursor = ">"
- }
- s += cursor + " " + choice + "\n"
- }
- return s
- } else {
- s := ""
- switch m.Speed {
- case "Slow mode":
- s += paint("silver").Render("Select action for file: "+m.File) + "\n\n"
- for i, choice := range m.Choices {
- cursor := " "
- if m.cursor == i {
- cursor = ">"
- }
- s += cursor + " " + choice + "\n"
- }
- case "Fast mode":
- s += paint("silver").Render("Select action:") + "\n\n"
- for i, choice := range m.Choices {
- cursor := " "
- if m.cursor == i {
- cursor = ">"
- }
- s += cursor + " " + choice + "\n"
- }
- }
- return s + paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down")
- }
+ if len(m.Choices) == 2 {
+ s := paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n"
+ for i, choice := range m.Choices {
+ cursor := " "
+ if m.cursor == i {
+ cursor = ">"
+ }
+ s += cursor + " " + choice + "\n"
+ }
+ return s
+ }
+ s := ""
+ switch m.Speed {
+ case "Slow mode":
+ s += paint("silver").Render("Select action for file: "+m.File) + "\n\n"
+ for i, choice := range m.Choices {
+ cursor := " "
+ if m.cursor == i {
+ cursor = ">"
+ }
+ s += cursor + " " + choice + "\n"
+ }
+ case "Fast mode":
+ s += paint("silver").Render("Select action:") + "\n\n"
+ for i, choice := range m.Choices {
+ cursor := " "
+ if m.cursor == i {
+ cursor = ">"
+ }
+ s += cursor + " " + choice + "\n"
+ }
+ }
+ return s + paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down")
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (m ModeSelector) View() string { | |
if len(m.Choices) == 2 { | |
s := paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
return s | |
} else { | |
s := "" | |
switch m.Speed { | |
case "Slow mode": | |
s += paint("silver").Render("Select action for file: "+m.File) + "\n\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
case "Fast mode": | |
s += paint("silver").Render("Select action:") + "\n\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
} | |
return s + paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down") | |
} | |
} | |
func (m ModeSelector) View() string { | |
if len(m.Choices) == 2 { | |
s := paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
return s | |
} | |
s := "" | |
switch m.Speed { | |
case "Slow mode": | |
s += paint("silver").Render("Select action for file: "+m.File) + "\n\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
case "Fast mode": | |
s += paint("silver").Render("Select action:") + "\n\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
} | |
return s + paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down") | |
} |
Tools
golangci-lint
[warning] 63-63: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block
(revive)
90-90: unnecessary trailing newline
(whitespace)
65-65: unnecessary leading newline
(whitespace)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 13
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (2)
- utils/tui/modelutils/file.go (1 hunks)
- utils/tui/modelutils/selectorutils.go (1 hunks)
Additional context used
golangci-lint
utils/tui/modelutils/selectorutils.go
[warning] 10-10: exported: exported function Contains should have comment or be unexported
(revive)
utils/tui/modelutils/file.go
[warning] 11-11: exported: exported type FilesSelector should have comment or be unexported
(revive)
[warning] 23-23: exported: exported function InitialModel should have comment or be unexported
(revive)
[warning] 52-52: exported: exported method FilesSelector.Init should have comment or be unexported
(revive)
[warning] 56-56: exported: exported method FilesSelector.Update should have comment or be unexported
(revive)
[warning] 112-112: exported: exported method FilesSelector.View should have comment or be unexported
(revive)
func Remove(slice []string, target string) []string { | ||
result := make([]string, 0, len(slice)) | ||
for _, item := range slice { | ||
if item != target { | ||
result = append(result, item) | ||
} | ||
} | ||
return result | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function Remove
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // Remove removes a specific string from a slice.
func Remove(slice []string, target string) []string {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func Remove(slice []string, target string) []string { | |
result := make([]string, 0, len(slice)) | |
for _, item := range slice { | |
if item != target { | |
result = append(result, item) | |
} | |
} | |
return result | |
} | |
// Remove removes a specific string from a slice. | |
func Remove(slice []string, target string) []string { | |
result := make([]string, 0, len(slice)) | |
for _, item := range slice { | |
if item != target { | |
result = append(result, item) | |
} | |
} | |
return result | |
} |
func IsDirectory(path string) (bool, error) { | ||
fileInfo, err := os.Stat(path) | ||
if err != nil { | ||
return false, err | ||
} | ||
return fileInfo.IsDir(), nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function IsDirectory
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // IsDirectory checks if a given path is a directory.
func IsDirectory(path string) (bool, error) {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func IsDirectory(path string) (bool, error) { | |
fileInfo, err := os.Stat(path) | |
if err != nil { | |
return false, err | |
} | |
return fileInfo.IsDir(), nil | |
} | |
// IsDirectory checks if a given path is a directory. | |
func IsDirectory(path string) (bool, error) { | |
fileInfo, err := os.Stat(path) | |
if err != nil { | |
return false, err | |
} | |
return fileInfo.IsDir(), nil | |
} |
func GetPathOfEntry(entry fs.DirEntry, baseDir string) (string, error) { | ||
_, err := entry.Info() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
absPath, err := filepath.Abs(filepath.Join(baseDir, entry.Name())) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return absPath, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function GetPathOfEntry
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // GetPathOfEntry gets the absolute path of an entry in a specified base directory.
func GetPathOfEntry(entry fs.DirEntry, baseDir string) (string, error) {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func GetPathOfEntry(entry fs.DirEntry, baseDir string) (string, error) { | |
_, err := entry.Info() | |
if err != nil { | |
return "", err | |
} | |
absPath, err := filepath.Abs(filepath.Join(baseDir, entry.Name())) | |
if err != nil { | |
return "", err | |
} | |
return absPath, nil | |
} | |
// GetPathOfEntry gets the absolute path of an entry in a specified base directory. | |
func GetPathOfEntry(entry fs.DirEntry, baseDir string) (string, error) { | |
_, err := entry.Info() | |
if err != nil { | |
return "", err | |
} | |
absPath, err := filepath.Abs(filepath.Join(baseDir, entry.Name())) | |
if err != nil { | |
return "", err | |
} | |
return absPath, nil | |
} |
func GetParentDirectory(directoryPath string) (string, error) { | ||
normalizedPath := filepath.Clean(directoryPath) | ||
|
||
if normalizedPath == "/" { | ||
return directoryPath, nil | ||
} | ||
|
||
parentDir := filepath.Dir(directoryPath) | ||
if parentDir == directoryPath { | ||
return "", fmt.Errorf("the given path '%s' is a root directory or invalid", directoryPath) | ||
} | ||
|
||
return parentDir, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function GetParentDirectory
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // GetParentDirectory gets the parent directory of a given path.
func GetParentDirectory(directoryPath string) (string, error) {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func GetParentDirectory(directoryPath string) (string, error) { | |
normalizedPath := filepath.Clean(directoryPath) | |
if normalizedPath == "/" { | |
return directoryPath, nil | |
} | |
parentDir := filepath.Dir(directoryPath) | |
if parentDir == directoryPath { | |
return "", fmt.Errorf("the given path '%s' is a root directory or invalid", directoryPath) | |
} | |
return parentDir, nil | |
} | |
// GetParentDirectory gets the parent directory of a given path. | |
func GetParentDirectory(directoryPath string) (string, error) { | |
normalizedPath := filepath.Clean(directoryPath) | |
if normalizedPath == "/" { | |
return directoryPath, nil | |
} | |
parentDir := filepath.Dir(directoryPath) | |
if parentDir == directoryPath { | |
return "", fmt.Errorf("the given path '%s' is a root directory or invalid", directoryPath) | |
} | |
return parentDir, nil | |
} |
func Contains(slice []string, str string) bool { | ||
for _, item := range slice { | ||
if item == str { | ||
return true | ||
} | ||
} | ||
return false | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function Contains
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // Contains checks if a slice contains a specific string.
func Contains(slice []string, str string) bool {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func Contains(slice []string, str string) bool { | |
for _, item := range slice { | |
if item == str { | |
return true | |
} | |
} | |
return false | |
} | |
// Contains checks if a slice contains a specific string. | |
func Contains(slice []string, str string) bool { | |
for _, item := range slice { | |
if item == str { | |
return true | |
} | |
} | |
return false | |
} |
Tools
golangci-lint
[warning] 10-10: exported: exported function Contains should have comment or be unexported
(revive)
utils/tui/modelutils/file.go
Outdated
func (m FilesSelector) Init() tea.Cmd { | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function Init
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // Init initializes the FilesSelector struct for the TUI.
func (m FilesSelector) Init() tea.Cmd {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (m FilesSelector) Init() tea.Cmd { | |
return nil | |
} | |
// Init initializes the FilesSelector struct for the TUI. | |
func (m FilesSelector) Init() tea.Cmd { | |
return nil | |
} |
Tools
golangci-lint
[warning] 52-52: exported: exported method FilesSelector.Init should have comment or be unexported
(revive)
utils/tui/modelutils/file.go
Outdated
type FilesSelector struct { | ||
CurrentDir string | ||
FilesAndDir []string | ||
SelectedFilesAndDir map[int]bool | ||
FilesPath []string | ||
cursor int | ||
scrollOffset int | ||
Done bool | ||
WindowHeight int | ||
Error error | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported struct FilesSelector
.
According to Go conventions, exported structs should have a comment explaining their purpose.
+ // FilesSelector represents the main application model for the TUI.
type FilesSelector struct {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
type FilesSelector struct { | |
CurrentDir string | |
FilesAndDir []string | |
SelectedFilesAndDir map[int]bool | |
FilesPath []string | |
cursor int | |
scrollOffset int | |
Done bool | |
WindowHeight int | |
Error error | |
} | |
// FilesSelector represents the main application model for the TUI. | |
type FilesSelector struct { | |
CurrentDir string | |
FilesAndDir []string | |
SelectedFilesAndDir map[int]bool | |
FilesPath []string | |
cursor int | |
scrollOffset int | |
Done bool | |
WindowHeight int | |
Error error | |
} |
Tools
golangci-lint
[warning] 11-11: exported: exported type FilesSelector should have comment or be unexported
(revive)
utils/tui/modelutils/file.go
Outdated
func paint(color string) lipgloss.Style { | ||
switch color { | ||
case "lime": | ||
lime := lipgloss.Color("#00FF00") | ||
return lipgloss.NewStyle().Foreground(lime) | ||
case "blue": | ||
blue := lipgloss.Color("#0000FF") | ||
return lipgloss.NewStyle().Foreground(blue) | ||
case "green": | ||
green := lipgloss.Color("#008000") | ||
return lipgloss.NewStyle().Foreground(green) | ||
case "red": | ||
red := lipgloss.Color("#FF0000") | ||
return lipgloss.NewStyle().Foreground(red) | ||
case "silver": | ||
silver := lipgloss.Color("#C0C0C0") | ||
return lipgloss.NewStyle().Foreground(silver) | ||
default: | ||
white := lipgloss.Color("#FFFFFF") | ||
return lipgloss.NewStyle().Foreground(white) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function paint
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // paint returns a lipgloss style based on the input color.
func paint(color string) lipgloss.Style {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func paint(color string) lipgloss.Style { | |
switch color { | |
case "lime": | |
lime := lipgloss.Color("#00FF00") | |
return lipgloss.NewStyle().Foreground(lime) | |
case "blue": | |
blue := lipgloss.Color("#0000FF") | |
return lipgloss.NewStyle().Foreground(blue) | |
case "green": | |
green := lipgloss.Color("#008000") | |
return lipgloss.NewStyle().Foreground(green) | |
case "red": | |
red := lipgloss.Color("#FF0000") | |
return lipgloss.NewStyle().Foreground(red) | |
case "silver": | |
silver := lipgloss.Color("#C0C0C0") | |
return lipgloss.NewStyle().Foreground(silver) | |
default: | |
white := lipgloss.Color("#FFFFFF") | |
return lipgloss.NewStyle().Foreground(white) | |
} | |
} | |
// paint returns a lipgloss style based on the input color. | |
func paint(color string) lipgloss.Style { | |
switch color { | |
case "lime": | |
lime := lipgloss.Color("#00FF00") | |
return lipgloss.NewStyle().Foreground(lime) | |
case "blue": | |
blue := lipgloss.Color("#0000FF") | |
return lipgloss.NewStyle().Foreground(blue) | |
case "green": | |
green := lipgloss.Color("#008000") | |
return lipgloss.NewStyle().Foreground(green) | |
case "red": | |
red := lipgloss.Color("#FF0000") | |
return lipgloss.NewStyle().Foreground(red) | |
case "silver": | |
silver := lipgloss.Color("#C0C0C0") | |
return lipgloss.NewStyle().Foreground(silver) | |
default: | |
white := lipgloss.Color("#FFFFFF") | |
return lipgloss.NewStyle().Foreground(white) | |
} | |
} |
utils/tui/modelutils/file.go
Outdated
func (m FilesSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | ||
switch msg := msg.(type) { | ||
case tea.KeyMsg: | ||
if m.Error != nil { | ||
return m, tea.Quit | ||
} | ||
switch msg.String() { | ||
case "ctrl+c", "q": | ||
return m, tea.Quit | ||
case "up": | ||
if m.cursor > 0 { | ||
m.cursor-- | ||
if m.cursor < m.scrollOffset { | ||
m.scrollOffset-- | ||
} | ||
} | ||
case "down": | ||
if m.cursor < len(m.FilesAndDir)-1 { | ||
m.cursor++ | ||
if m.cursor >= m.scrollOffset+m.WindowHeight { | ||
m.scrollOffset++ | ||
} | ||
} | ||
case "enter": | ||
checkDir, err := IsDirectory(m.FilesAndDir[m.cursor]) | ||
if err != nil { | ||
m.Error = fmt.Errorf("error checking directory: %w", err) | ||
return m, tea.Quit | ||
} | ||
if checkDir { | ||
err := moveToNextDir(&m, m.FilesAndDir[m.cursor]) | ||
if err != nil { | ||
m.Error = fmt.Errorf("error checking directory: %w", err) | ||
return m, tea.Quit | ||
} | ||
} else { | ||
if Contains(m.FilesPath, m.FilesAndDir[m.cursor]) { | ||
m.FilesPath = Remove(m.FilesPath, m.FilesAndDir[m.cursor]) | ||
} else { | ||
m.FilesPath = append(m.FilesPath, m.FilesAndDir[m.cursor]) | ||
} | ||
m.SelectedFilesAndDir[m.cursor] = !m.SelectedFilesAndDir[m.cursor] | ||
} | ||
case "esc": | ||
err := moveToPreviousDir(&m) | ||
if err != nil { | ||
m.Error = fmt.Errorf("error moving back: %w", err) | ||
return m, tea.Quit | ||
} | ||
case "x": | ||
m.Done = true | ||
} | ||
} | ||
return m, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function Update
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // Update updates the state of the FilesSelector struct based on user input.
func (m FilesSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (m FilesSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | |
switch msg := msg.(type) { | |
case tea.KeyMsg: | |
if m.Error != nil { | |
return m, tea.Quit | |
} | |
switch msg.String() { | |
case "ctrl+c", "q": | |
return m, tea.Quit | |
case "up": | |
if m.cursor > 0 { | |
m.cursor-- | |
if m.cursor < m.scrollOffset { | |
m.scrollOffset-- | |
} | |
} | |
case "down": | |
if m.cursor < len(m.FilesAndDir)-1 { | |
m.cursor++ | |
if m.cursor >= m.scrollOffset+m.WindowHeight { | |
m.scrollOffset++ | |
} | |
} | |
case "enter": | |
checkDir, err := IsDirectory(m.FilesAndDir[m.cursor]) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return m, tea.Quit | |
} | |
if checkDir { | |
err := moveToNextDir(&m, m.FilesAndDir[m.cursor]) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return m, tea.Quit | |
} | |
} else { | |
if Contains(m.FilesPath, m.FilesAndDir[m.cursor]) { | |
m.FilesPath = Remove(m.FilesPath, m.FilesAndDir[m.cursor]) | |
} else { | |
m.FilesPath = append(m.FilesPath, m.FilesAndDir[m.cursor]) | |
} | |
m.SelectedFilesAndDir[m.cursor] = !m.SelectedFilesAndDir[m.cursor] | |
} | |
case "esc": | |
err := moveToPreviousDir(&m) | |
if err != nil { | |
m.Error = fmt.Errorf("error moving back: %w", err) | |
return m, tea.Quit | |
} | |
case "x": | |
m.Done = true | |
} | |
} | |
return m, nil | |
} | |
// Update updates the state of the FilesSelector struct based on user input. | |
func (m FilesSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | |
switch msg := msg.(type) { | |
case tea.KeyMsg: | |
if m.Error != nil { | |
return m, tea.Quit | |
} | |
switch msg.String() { | |
case "ctrl+c", "q": | |
return m, tea.Quit | |
case "up": | |
if m.cursor > 0 { | |
m.cursor-- | |
if m.cursor < m.scrollOffset { | |
m.scrollOffset-- | |
} | |
} | |
case "down": | |
if m.cursor < len(m.FilesAndDir)-1 { | |
m.cursor++ | |
if m.cursor >= m.scrollOffset+m.WindowHeight { | |
m.scrollOffset++ | |
} | |
} | |
case "enter": | |
checkDir, err := IsDirectory(m.FilesAndDir[m.cursor]) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return m, tea.Quit | |
} | |
if checkDir { | |
err := moveToNextDir(&m, m.FilesAndDir[m.cursor]) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return m, tea.Quit | |
} | |
} else { | |
if Contains(m.FilesPath, m.FilesAndDir[m.cursor]) { | |
m.FilesPath = Remove(m.FilesPath, m.FilesAndDir[m.cursor]) | |
} else { | |
m.FilesPath = append(m.FilesPath, m.FilesAndDir[m.cursor]) | |
} | |
m.SelectedFilesAndDir[m.cursor] = !m.SelectedFilesAndDir[m.cursor] | |
} | |
case "esc": | |
err := moveToPreviousDir(&m) | |
if err != nil { | |
m.Error = fmt.Errorf("error moving back: %w", err) | |
return m, tea.Quit | |
} | |
case "x": | |
m.Done = true | |
} | |
} | |
return m, nil | |
} |
Tools
golangci-lint
[warning] 56-56: exported: exported method FilesSelector.Update should have comment or be unexported
(revive)
utils/tui/modelutils/file.go
Outdated
func (m FilesSelector) View() string { | ||
if m.Error != nil { | ||
return paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | ||
} | ||
|
||
s := paint("silver").Render("\n Select the files you want to modify...") + "\n" | ||
s += paint("silver").Render("\n Selected files till now:") + "\n" | ||
for i := 0; i < len(m.FilesPath); i++ { | ||
s += fmt.Sprintf(" %s\n", paint("green").Render(m.FilesPath[i])) | ||
} | ||
s += "\n" | ||
|
||
for i := m.scrollOffset; i < m.scrollOffset+m.WindowHeight && i < len(m.FilesAndDir); i++ { | ||
choice := m.FilesAndDir[i] | ||
checkDir, err := IsDirectory(choice) | ||
if err != nil { | ||
m.Error = fmt.Errorf("error checking directory: %w", err) | ||
return paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | ||
} | ||
if checkDir { | ||
choice = paint("blue").Render("❒ " + choice) | ||
} else if Contains(m.FilesPath, choice) { | ||
choice = paint("lime").Render("❒ " + choice) | ||
} else { | ||
choice = paint("silver").Render("❒ " + choice) | ||
} | ||
|
||
cursor := " " | ||
if m.cursor == i { | ||
cursor = paint("red").Render(" ➪") | ||
} | ||
|
||
s += fmt.Sprintf("%s %s\n", cursor, choice) | ||
} | ||
s += paint("silver").Render("\n 'q' to quit 'esc' to move to parent directory\n '↑' to go up 'x' to modify selected files\n '↓' to go down 'enter' to select pointed file/move to pointed sub folder") | ||
return s | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function View
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // View renders the view of the FilesSelector struct for the TUI.
func (m FilesSelector) View() string {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (m FilesSelector) View() string { | |
if m.Error != nil { | |
return paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | |
} | |
s := paint("silver").Render("\n Select the files you want to modify...") + "\n" | |
s += paint("silver").Render("\n Selected files till now:") + "\n" | |
for i := 0; i < len(m.FilesPath); i++ { | |
s += fmt.Sprintf(" %s\n", paint("green").Render(m.FilesPath[i])) | |
} | |
s += "\n" | |
for i := m.scrollOffset; i < m.scrollOffset+m.WindowHeight && i < len(m.FilesAndDir); i++ { | |
choice := m.FilesAndDir[i] | |
checkDir, err := IsDirectory(choice) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | |
} | |
if checkDir { | |
choice = paint("blue").Render("❒ " + choice) | |
} else if Contains(m.FilesPath, choice) { | |
choice = paint("lime").Render("❒ " + choice) | |
} else { | |
choice = paint("silver").Render("❒ " + choice) | |
} | |
cursor := " " | |
if m.cursor == i { | |
cursor = paint("red").Render(" ➪") | |
} | |
s += fmt.Sprintf("%s %s\n", cursor, choice) | |
} | |
s += paint("silver").Render("\n 'q' to quit 'esc' to move to parent directory\n '↑' to go up 'x' to modify selected files\n '↓' to go down 'enter' to select pointed file/move to pointed sub folder") | |
return s | |
} | |
// View renders the view of the FilesSelector struct for the TUI. | |
func (m FilesSelector) View() string { | |
if m.Error != nil { | |
return paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | |
} | |
s := paint("silver").Render("\n Select the files you want to modify...") + "\n" | |
s += paint("silver").Render("\n Selected files till now:") + "\n" | |
for i := 0; i < len(m.FilesPath); i++ { | |
s += fmt.Sprintf(" %s\n", paint("green").Render(m.FilesPath[i])) | |
} | |
s += "\n" | |
for i := m.scrollOffset; i < m.scrollOffset+m.WindowHeight && i < len(m.FilesAndDir); i++ { | |
choice := m.FilesAndDir[i] | |
checkDir, err := IsDirectory(choice) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | |
} | |
if checkDir { | |
choice = paint("blue").Render("❒ " + choice) | |
} else if Contains(m.FilesPath, choice) { | |
choice = paint("lime").Render("❒ " + choice) | |
} else { | |
choice = paint("silver").Render("❒ " + choice) | |
} | |
cursor := " " | |
if m.cursor == i { | |
cursor = paint("red").Render(" ➪") | |
} | |
s += fmt.Sprintf("%s %s\n", cursor, choice) | |
} | |
s += paint("silver").Render("\n 'q' to quit 'esc' to move to parent directory\n '↑' to go up 'x' to modify selected files\n '↓' to go down 'enter' to select pointed file/move to pointed sub folder") | |
return s | |
} |
Tools
golangci-lint
[warning] 112-112: exported: exported method FilesSelector.View should have comment or be unexported
(revive)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (5)
- main.go (1 hunks)
- utils/tui/model.go (1 hunks)
- utils/tui/modelutils/file.go (1 hunks)
- utils/tui/modelutils/option.go (1 hunks)
- utils/tui/modelutils/text.go (1 hunks)
Files skipped from review due to trivial changes (1)
- main.go
Files skipped from review as they are similar to previous changes (1)
- utils/tui/modelutils/file.go
Additional context used
golangci-lint
utils/tui/modelutils/option.go
[warning] 63-63: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block
(revive)
[warning] 5-5: exported: exported type ModeSelector should have comment or be unexported
(revive)
[warning] 14-14: exported: exported function NewModeSelector should have comment or be unexported
(revive)
[warning] 23-23: exported: exported method ModeSelector.Init should have comment or be unexported
(revive)
[warning] 27-27: exported: exported method ModeSelector.Update should have comment or be unexported
(revive)
[warning] 52-52: exported: exported method ModeSelector.View should have comment or be unexported
(revive)
90-90: unnecessary trailing newline
(whitespace)
65-65: unnecessary leading newline
(whitespace)
utils/tui/model.go
104-104: ineffectual assignment to counter
(ineffassign)
139-139: ineffectual assignment to counter
(ineffassign)
Additional comments not posted (9)
utils/tui/modelutils/text.go (4)
12-19
: LGTM!The
LabelInput
struct is well-defined.
21-28
: LGTM!The
NewLabelInput
function is well-defined.
30-32
: LGTM!The
Init
method is well-defined.
62-84
: LGTM!The
View
method is well-defined.utils/tui/model.go (5)
13-29
: LGTM!The
Model
struct is well-defined.
36-39
: LGTM!The
Init
method is well-defined.
167-187
: LGTM!The
View
method is well-defined.
189-222
: LGTM!The
applyChanges
method is well-defined.
224-239
: LGTM!The
AbsToRel
function is well-defined.
utils/tui/modelutils/option.go
Outdated
func NewModeSelector(choices []string, file string, speed string) ModeSelector { | ||
return ModeSelector{ | ||
File: file, | ||
Choices: choices, | ||
Selected: "", | ||
Speed: speed, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported NewModeSelector
function.
The NewModeSelector
function is exported and should have a comment for proper documentation.
+// NewModeSelector creates a new instance of ModeSelector with the given choices, file, and speed.
func NewModeSelector(choices []string, file string, speed string) ModeSelector {
return ModeSelector{
File: file,
Choices: choices,
Selected: "",
Speed: speed,
}
}
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func NewModeSelector(choices []string, file string, speed string) ModeSelector { | |
return ModeSelector{ | |
File: file, | |
Choices: choices, | |
Selected: "", | |
Speed: speed, | |
} | |
} | |
// NewModeSelector creates a new instance of ModeSelector with the given choices, file, and speed. | |
func NewModeSelector(choices []string, file string, speed string) ModeSelector { | |
return ModeSelector{ | |
File: file, | |
Choices: choices, | |
Selected: "", | |
Speed: speed, | |
} | |
} |
Tools
golangci-lint
[warning] 14-14: exported: exported function NewModeSelector should have comment or be unexported
(revive)
utils/tui/modelutils/option.go
Outdated
type ModeSelector struct { | ||
File string | ||
Choices []string | ||
cursor int | ||
Selected string | ||
Done bool | ||
Speed string | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported ModeSelector
struct.
The ModeSelector
struct is exported and should have a comment for proper documentation.
+// ModeSelector represents a mode selector in the TUI application.
type ModeSelector struct {
File string
Choices []string
cursor int
Selected string
Done bool
Speed string
}
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
type ModeSelector struct { | |
File string | |
Choices []string | |
cursor int | |
Selected string | |
Done bool | |
Speed string | |
} | |
// ModeSelector represents a mode selector in the TUI application. | |
type ModeSelector struct { | |
File string | |
Choices []string | |
cursor int | |
Selected string | |
Done bool | |
Speed string | |
} |
Tools
golangci-lint
[warning] 5-5: exported: exported type ModeSelector should have comment or be unexported
(revive)
utils/tui/modelutils/option.go
Outdated
func (m ModeSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | ||
switch msg := msg.(type) { | ||
case tea.KeyMsg: | ||
switch msg.String() { | ||
case "ctrl+c", "q": | ||
return m, tea.Quit | ||
|
||
case "up": | ||
if m.cursor > 0 { | ||
m.cursor-- | ||
} | ||
|
||
case "down": | ||
if m.cursor < len(m.Choices)-1 { | ||
m.cursor++ | ||
} | ||
|
||
case "enter": | ||
m.Selected = m.Choices[m.cursor] | ||
m.Done = true | ||
} | ||
} | ||
return m, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported Update
method.
The Update
method is exported and should have a comment for proper documentation.
+// Update processes incoming messages and updates the ModeSelector state accordingly.
func (m ModeSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q":
return m, tea.Quit
case "up":
if m.cursor > 0 {
m.cursor--
}
case "down":
if m.cursor < len(m.Choices)-1 {
m.cursor++
}
case "enter":
m.Selected = m.Choices[m.cursor]
m.Done = true
}
}
return m, nil
}
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (m ModeSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | |
switch msg := msg.(type) { | |
case tea.KeyMsg: | |
switch msg.String() { | |
case "ctrl+c", "q": | |
return m, tea.Quit | |
case "up": | |
if m.cursor > 0 { | |
m.cursor-- | |
} | |
case "down": | |
if m.cursor < len(m.Choices)-1 { | |
m.cursor++ | |
} | |
case "enter": | |
m.Selected = m.Choices[m.cursor] | |
m.Done = true | |
} | |
} | |
return m, nil | |
} | |
// Update processes incoming messages and updates the ModeSelector state accordingly. | |
func (m ModeSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | |
switch msg := msg.(type) { | |
case tea.KeyMsg: | |
switch msg.String() { | |
case "ctrl+c", "q": | |
return m, tea.Quit | |
case "up": | |
if m.cursor > 0 { | |
m.cursor-- | |
} | |
case "down": | |
if m.cursor < len(m.Choices)-1 { | |
m.cursor++ | |
} | |
case "enter": | |
m.Selected = m.Choices[m.cursor] | |
m.Done = true | |
} | |
} | |
return m, nil | |
} |
Tools
golangci-lint
[warning] 27-27: exported: exported method ModeSelector.Update should have comment or be unexported
(revive)
utils/tui/modelutils/option.go
Outdated
func (m ModeSelector) View() string { | ||
if len(m.Choices) == 2 { | ||
s := Paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n" | ||
for i, choice := range m.Choices { | ||
cursor := " " | ||
if m.cursor == i { | ||
cursor = ">" | ||
} | ||
s += cursor + " " + choice + "\n" | ||
} | ||
return s | ||
} else { | ||
s := "" | ||
switch m.Speed { | ||
|
||
case "Slow mode": | ||
s += Paint("silver").Render("Select action for file: "+m.File) + "\n\n" | ||
for i, choice := range m.Choices { | ||
cursor := " " | ||
if m.cursor == i { | ||
cursor = ">" | ||
} | ||
s += cursor + " " + choice + "\n" | ||
} | ||
|
||
case "Fast mode": | ||
s += Paint("silver").Render("Select action:") + "\n\n" | ||
for i, choice := range m.Choices { | ||
cursor := " " | ||
if m.cursor == i { | ||
cursor = ">" | ||
} | ||
s += cursor + " " + choice + "\n" | ||
} | ||
} | ||
return s + Paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down") | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported View
method and fix the indent-error-flow issue.
The View
method is exported and should have a comment for proper documentation. Additionally, the indent-error-flow issue should be fixed by removing the unnecessary else block.
+// View renders the view for the ModeSelector based on its current state.
func (m ModeSelector) View() string {
if len(m.Choices) == 2 {
s := Paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n"
for i, choice := range m.Choices {
cursor := " "
if m.cursor == i {
cursor = ">"
}
s += cursor + " " + choice + "\n"
}
return s
}
s := ""
switch m.Speed {
case "Slow mode":
s += Paint("silver").Render("Select action for file: "+m.File) + "\n\n"
for i, choice := range m.Choices {
cursor := " "
if m.cursor == i {
cursor = ">"
}
s += cursor + " " + choice + "\n"
}
case "Fast mode":
s += Paint("silver").Render("Select action:") + "\n\n"
for i, choice := range m.Choices {
cursor := " "
if m.cursor == i {
cursor = ">"
}
s += cursor + " " + choice + "\n"
}
}
return s + Paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down")
}
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (m ModeSelector) View() string { | |
if len(m.Choices) == 2 { | |
s := Paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
return s | |
} else { | |
s := "" | |
switch m.Speed { | |
case "Slow mode": | |
s += Paint("silver").Render("Select action for file: "+m.File) + "\n\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
case "Fast mode": | |
s += Paint("silver").Render("Select action:") + "\n\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
} | |
return s + Paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down") | |
} | |
} | |
// View renders the view for the ModeSelector based on its current state. | |
func (m ModeSelector) View() string { | |
if len(m.Choices) == 2 { | |
s := Paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
return s | |
} | |
s := "" | |
switch m.Speed { | |
case "Slow mode": | |
s += Paint("silver").Render("Select action for file: "+m.File) + "\n\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
case "Fast mode": | |
s += Paint("silver").Render("Select action:") + "\n\n" | |
for i, choice := range m.Choices { | |
cursor := " " | |
if m.cursor == i { | |
cursor = ">" | |
} | |
s += cursor + " " + choice + "\n" | |
} | |
} | |
return s + Paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down") | |
} |
Tools
golangci-lint
[warning] 63-63: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block
(revive)
[warning] 52-52: exported: exported method ModeSelector.View should have comment or be unexported
(revive)
90-90: unnecessary trailing newline
(whitespace)
65-65: unnecessary leading newline
(whitespace)
utils/tui/modelutils/text.go
Outdated
func (m LabelInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | ||
switch msg := msg.(type) { | ||
case tea.KeyMsg: | ||
switch msg.String() { | ||
case "ctrl+c", "q": | ||
return m, tea.Quit | ||
|
||
case "enter": | ||
if err := m.validateInput(); err != nil { | ||
m.Error = err | ||
return m, nil | ||
} | ||
m.Done = true | ||
|
||
case "backspace": | ||
if len(m.Input) > 0 { | ||
m.Input = m.Input[:len(m.Input)-1] | ||
} | ||
|
||
default: | ||
m.Input += msg.String() | ||
} | ||
case tickMsg: | ||
m.flash = !m.flash | ||
} | ||
return m, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure proper error handling in the Update
method.
The method validateInput()
is called within a conditional block when the "enter" key is pressed. If an error occurs, it's correctly assigned to m.Error
, but there should be a way to inform the user about the error, perhaps by flashing the screen or showing an error message directly in the UI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 14
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (3)
- utils/tui/model.go (1 hunks)
- utils/tui/modelutils/file.go (1 hunks)
- utils/tui/modelutils/text.go (1 hunks)
Additional context used
golangci-lint
utils/tui/modelutils/text.go
[warning] 12-12: exported: exported type LabelInput should have comment or be unexported
(revive)
[warning] 21-21: exported: exported function NewLabelInput should have comment or be unexported
(revive)
[warning] 30-30: exported: exported method LabelInput.Init should have comment or be unexported
(revive)
[warning] 34-34: exported: exported method LabelInput.Update should have comment or be unexported
(revive)
[warning] 63-63: exported: exported method LabelInput.View should have comment or be unexported
(revive)
[warning] 87-87: exported: exported function StartTicker should have comment or be unexported
(revive)
utils/tui/modelutils/file.go
[warning] 11-11: exported: exported type FilesSelector should have comment or be unexported
(revive)
[warning] 24-24: exported: exported function InitialModel should have comment or be unexported
(revive)
[warning] 53-53: exported: exported method FilesSelector.Init should have comment or be unexported
(revive)
utils/tui/model.go
104-104: ineffectual assignment to counter
(ineffassign)
139-139: ineffectual assignment to counter
(ineffassign)
Additional comments not posted (6)
utils/tui/modelutils/file.go (1)
53-55
: Add a comment for the exported methodInit
.According to Go conventions, exported methods should have a comment explaining their purpose.
+ // Init initializes the FilesSelector struct. func (m FilesSelector) Init() tea.Cmd {
Likely invalid or redundant comment.
Tools
golangci-lint
[warning] 53-53: exported: exported method FilesSelector.Init should have comment or be unexported
(revive)
utils/tui/model.go (5)
189-222
: Add a comment for the exported methodapplyChanges
.According to Go conventions, exported methods should have a comment explaining their purpose.
+ // applyChanges applies changes to selected files based on user inputs. func (m *Model) applyChanges() tea.Cmd {
Likely invalid or redundant comment.
36-39
: Add a comment for the exported methodInit
.According to Go conventions, exported methods should have a comment explaining their purpose.
+ // Init initializes the model. func (m Model) Init() tea.Cmd {
Likely invalid or redundant comment.
13-29
: Add a comment for the exported structModel
.According to Go conventions, exported structs should have a comment explaining their purpose.
+ // Model represents the main application model for the TUI. type Model struct {
Likely invalid or redundant comment.
31-34
: Add a comment for the exported structapplyChangesMsg
.According to Go conventions, exported structs should have a comment explaining their purpose.
+ // applyChangesMsg represents a message indicating that changes have been applied. type applyChangesMsg struct {
Likely invalid or redundant comment.
167-187
: Add a comment for the exported methodView
.According to Go conventions, exported methods should have a comment explaining their purpose.
+ // View renders the view based on the current state. func (m Model) View() string {
Likely invalid or redundant comment.
utils/tui/modelutils/text.go
Outdated
func (m LabelInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | ||
switch msg := msg.(type) { | ||
case tea.KeyMsg: | ||
switch msg.Type { | ||
case tea.KeyCtrlC: | ||
return m, tea.Quit | ||
|
||
case tea.KeyEnter: | ||
if err := m.validateInput(); err != nil { | ||
m.Error = err | ||
return m, nil | ||
} | ||
m.Done = true | ||
|
||
case tea.KeyBackspace: | ||
if len(m.Input) > 0 { | ||
m.Input = m.Input[:len(m.Input)-1] | ||
} | ||
|
||
case tea.KeyRunes: | ||
m.Input += msg.String() | ||
} | ||
|
||
case tickMsg: | ||
m.flash = !m.flash | ||
} | ||
return m, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported method Update
and ensure proper error handling.
According to Go conventions, exported methods should have a comment explaining their purpose. Additionally, ensure proper error handling by informing the user about the error.
+ // Update updates the LabelInput struct based on user input.
func (m LabelInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
To inform the user about the error, consider flashing the screen or showing an error message directly in the UI.
if err := m.validateInput(); err != nil {
m.Error = err
// Add code to inform the user about the error
return m, nil
}
Tools
golangci-lint
[warning] 34-34: exported: exported method LabelInput.Update should have comment or be unexported
(revive)
utils/tui/modelutils/text.go
Outdated
type LabelInput struct { | ||
File string | ||
Input string | ||
Done bool | ||
IsLabel bool // Added to distinguish between labels and line numbers | ||
flash bool | ||
Error error | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported struct LabelInput
.
According to Go conventions, exported structs should have a comment explaining their purpose.
+ // LabelInput represents the input model for label or line number input.
type LabelInput struct {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
type LabelInput struct { | |
File string | |
Input string | |
Done bool | |
IsLabel bool // Added to distinguish between labels and line numbers | |
flash bool | |
Error error | |
} | |
// LabelInput represents the input model for label or line number input. | |
type LabelInput struct { | |
File string | |
Input string | |
Done bool | |
IsLabel bool // Added to distinguish between labels and line numbers | |
flash bool | |
Error error | |
} |
Tools
golangci-lint
[warning] 12-12: exported: exported type LabelInput should have comment or be unexported
(revive)
utils/tui/modelutils/text.go
Outdated
func (m LabelInput) View() string { | ||
if m.Error != nil { | ||
return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | ||
} | ||
flash := "" | ||
if m.flash { | ||
flash = Paint("green").Render("▎") | ||
} | ||
|
||
s := Paint("silver").Render("Type below the section to modify. You can insert your start label\nand your end label using the syntax 'start';'end' or you can modify\n a single line by entering the line number or a range of lines using the syntax x-y") + "\n\n" | ||
if m.File != "" { | ||
s += Paint("green").Render(m.File+": ✏ "+m.Input) + flash + "\n" | ||
} else { | ||
s += Paint("green").Render("✏ "+m.Input) + flash + "\n" | ||
} | ||
|
||
if m.Error != nil { | ||
s += Paint("red").Render("\nError: "+m.Error.Error()) + "\n" | ||
} | ||
|
||
s += Paint("silver").Render("\n 'ctrl +c' to quit 'enter' to select the lines/labels indicated\n '↑' to go up\n '↓' to go down") | ||
return s | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported method View
.
According to Go conventions, exported methods should have a comment explaining their purpose.
+ // View renders the view for the LabelInput struct.
func (m LabelInput) View() string {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (m LabelInput) View() string { | |
if m.Error != nil { | |
return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | |
} | |
flash := "" | |
if m.flash { | |
flash = Paint("green").Render("▎") | |
} | |
s := Paint("silver").Render("Type below the section to modify. You can insert your start label\nand your end label using the syntax 'start';'end' or you can modify\n a single line by entering the line number or a range of lines using the syntax x-y") + "\n\n" | |
if m.File != "" { | |
s += Paint("green").Render(m.File+": ✏ "+m.Input) + flash + "\n" | |
} else { | |
s += Paint("green").Render("✏ "+m.Input) + flash + "\n" | |
} | |
if m.Error != nil { | |
s += Paint("red").Render("\nError: "+m.Error.Error()) + "\n" | |
} | |
s += Paint("silver").Render("\n 'ctrl +c' to quit 'enter' to select the lines/labels indicated\n '↑' to go up\n '↓' to go down") | |
return s | |
} | |
// View renders the view for the LabelInput struct. | |
func (m LabelInput) View() string { | |
if m.Error != nil { | |
return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | |
} | |
flash := "" | |
if m.flash { | |
flash = Paint("green").Render("▎") | |
} | |
s := Paint("silver").Render("Type below the section to modify. You can insert your start label\nand your end label using the syntax 'start';'end' or you can modify\n a single line by entering the line number or a range of lines using the syntax x-y") + "\n\n" | |
if m.File != "" { | |
s += Paint("green").Render(m.File+": ✏ "+m.Input) + flash + "\n" | |
} else { | |
s += Paint("green").Render("✏ "+m.Input) + flash + "\n" | |
} | |
if m.Error != nil { | |
s += Paint("red").Render("\nError: "+m.Error.Error()) + "\n" | |
} | |
s += Paint("silver").Render("\n 'ctrl +c' to quit 'enter' to select the lines/labels indicated\n '↑' to go up\n '↓' to go down") | |
return s | |
} |
Tools
golangci-lint
[warning] 63-63: exported: exported method LabelInput.View should have comment or be unexported
(revive)
utils/tui/modelutils/file.go
Outdated
func Paint(color string) lipgloss.Style { | ||
switch color { | ||
case "lime": | ||
lime := lipgloss.Color("#00FF00") | ||
return lipgloss.NewStyle().Foreground(lime) | ||
case "blue": | ||
blue := lipgloss.Color("#0000FF") | ||
return lipgloss.NewStyle().Foreground(blue) | ||
case "green": | ||
green := lipgloss.Color("#008000") | ||
return lipgloss.NewStyle().Foreground(green) | ||
case "red": | ||
red := lipgloss.Color("#FF0000") | ||
return lipgloss.NewStyle().Foreground(red) | ||
case "silver": | ||
silver := lipgloss.Color("#C0C0C0") | ||
return lipgloss.NewStyle().Foreground(silver) | ||
default: | ||
white := lipgloss.Color("#FFFFFF") | ||
return lipgloss.NewStyle().Foreground(white) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function Paint
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // Paint returns a lipgloss style based on the input color.
func Paint(color string) lipgloss.Style {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func Paint(color string) lipgloss.Style { | |
switch color { | |
case "lime": | |
lime := lipgloss.Color("#00FF00") | |
return lipgloss.NewStyle().Foreground(lime) | |
case "blue": | |
blue := lipgloss.Color("#0000FF") | |
return lipgloss.NewStyle().Foreground(blue) | |
case "green": | |
green := lipgloss.Color("#008000") | |
return lipgloss.NewStyle().Foreground(green) | |
case "red": | |
red := lipgloss.Color("#FF0000") | |
return lipgloss.NewStyle().Foreground(red) | |
case "silver": | |
silver := lipgloss.Color("#C0C0C0") | |
return lipgloss.NewStyle().Foreground(silver) | |
default: | |
white := lipgloss.Color("#FFFFFF") | |
return lipgloss.NewStyle().Foreground(white) | |
} | |
} | |
// Paint returns a lipgloss style based on the input color. | |
func Paint(color string) lipgloss.Style { | |
switch color { | |
case "lime": | |
lime := lipgloss.Color("#00FF00") | |
return lipgloss.NewStyle().Foreground(lime) | |
case "blue": | |
blue := lipgloss.Color("#0000FF") | |
return lipgloss.NewStyle().Foreground(blue) | |
case "green": | |
green := lipgloss.Color("#008000") | |
return lipgloss.NewStyle().Foreground(green) | |
case "red": | |
red := lipgloss.Color("#FF0000") | |
return lipgloss.NewStyle().Foreground(red) | |
case "silver": | |
silver := lipgloss.Color("#C0C0C0") | |
return lipgloss.NewStyle().Foreground(silver) | |
default: | |
white := lipgloss.Color("#FFFFFF") | |
return lipgloss.NewStyle().Foreground(white) | |
} | |
} |
utils/tui/modelutils/file.go
Outdated
func InitialModel(currentDir string, windowHeight int) FilesSelector { | ||
var filesAndDir []string | ||
selectedFilesAndDir := make(map[int]bool) | ||
|
||
entries, err := os.ReadDir(currentDir) | ||
if err != nil { | ||
return FilesSelector{Error: fmt.Errorf("error reading directory: %w", err)} | ||
} | ||
|
||
for _, entry := range entries { | ||
entryPath, err := GetPathOfEntry(entry, currentDir) | ||
if err != nil { | ||
return FilesSelector{Error: fmt.Errorf("error getting path of entry: %w", err)} | ||
} | ||
filesAndDir = append(filesAndDir, entryPath) | ||
} | ||
|
||
for i := 0; i < len(filesAndDir); i++ { | ||
selectedFilesAndDir[i] = false | ||
} | ||
|
||
return FilesSelector{ | ||
CurrentDir: currentDir, | ||
FilesAndDir: filesAndDir, | ||
SelectedFilesAndDir: selectedFilesAndDir, | ||
WindowHeight: windowHeight, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function InitialModel
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // InitialModel initializes the FilesSelector struct.
func InitialModel(currentDir string, windowHeight int) FilesSelector {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func InitialModel(currentDir string, windowHeight int) FilesSelector { | |
var filesAndDir []string | |
selectedFilesAndDir := make(map[int]bool) | |
entries, err := os.ReadDir(currentDir) | |
if err != nil { | |
return FilesSelector{Error: fmt.Errorf("error reading directory: %w", err)} | |
} | |
for _, entry := range entries { | |
entryPath, err := GetPathOfEntry(entry, currentDir) | |
if err != nil { | |
return FilesSelector{Error: fmt.Errorf("error getting path of entry: %w", err)} | |
} | |
filesAndDir = append(filesAndDir, entryPath) | |
} | |
for i := 0; i < len(filesAndDir); i++ { | |
selectedFilesAndDir[i] = false | |
} | |
return FilesSelector{ | |
CurrentDir: currentDir, | |
FilesAndDir: filesAndDir, | |
SelectedFilesAndDir: selectedFilesAndDir, | |
WindowHeight: windowHeight, | |
} | |
} | |
// InitialModel initializes the FilesSelector struct. | |
func InitialModel(currentDir string, windowHeight int) FilesSelector { | |
var filesAndDir []string | |
selectedFilesAndDir := make(map[int]bool) | |
entries, err := os.ReadDir(currentDir) | |
if (err != nil) { | |
return FilesSelector{Error: fmt.Errorf("error reading directory: %w", err)} | |
} | |
for _, entry := range entries { | |
entryPath, err := GetPathOfEntry(entry, currentDir) | |
if err != nil { | |
return FilesSelector{Error: fmt.Errorf("error getting path of entry: %w", err)} | |
} | |
filesAndDir = append(filesAndDir, entryPath) | |
} | |
for i := 0; i < len(filesAndDir); i++ { | |
selectedFilesAndDir[i] = false | |
} | |
return FilesSelector{ | |
CurrentDir: currentDir, | |
FilesAndDir: filesAndDir, | |
SelectedFilesAndDir: selectedFilesAndDir, | |
WindowHeight: windowHeight, | |
} | |
} |
Tools
golangci-lint
[warning] 24-24: exported: exported function InitialModel should have comment or be unexported
(revive)
utils/tui/modelutils/file.go
Outdated
func (m FilesSelector) View() string { | ||
if m.Error != nil { | ||
return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | ||
} | ||
|
||
s := Paint("silver").Render("\n Select the files you want to modify...") + "\n" | ||
s += Paint("silver").Render("\n Selected files till now:") + "\n" | ||
if m.NoFileSelected { | ||
s += Paint("red").Render("\n No file selected. Please select at least one file or quit.") + "\n" | ||
} | ||
for i := 0; i < len(m.FilesPath); i++ { | ||
s += fmt.Sprintf(" %s\n", Paint("green").Render(m.FilesPath[i])) | ||
} | ||
s += "\n" | ||
|
||
for i := m.scrollOffset; i < m.scrollOffset+m.WindowHeight && i < len(m.FilesAndDir); i++ { | ||
choice := m.FilesAndDir[i] | ||
checkDir, err := IsDirectory(choice) | ||
if err != nil { | ||
m.Error = fmt.Errorf("error checking directory: %w", err) | ||
return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | ||
} | ||
if checkDir { | ||
choice = Paint("blue").Render("❒ " + choice) | ||
} else if Contains(m.FilesPath, choice) { | ||
choice = Paint("lime").Render("❒ " + choice) | ||
} else { | ||
choice = Paint("silver").Render("❒ " + choice) | ||
} | ||
|
||
cursor := " " | ||
if m.cursor == i { | ||
cursor = Paint("red").Render(" ➪") | ||
} | ||
|
||
s += fmt.Sprintf("%s %s\n", cursor, choice) | ||
} | ||
s += Paint("silver").Render("\n 'q' to quit 'esc' to move to parent directory\n '↑' to go up 'x' to modify selected files\n '↓' to go down 'enter' to select pointed file/move to pointed sub folder") | ||
return s | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported method View
.
According to Go conventions, exported methods should have a comment explaining their purpose.
+ // View renders the view of the FilesSelector struct for the TUI.
func (m FilesSelector) View() string {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (m FilesSelector) View() string { | |
if m.Error != nil { | |
return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | |
} | |
s := Paint("silver").Render("\n Select the files you want to modify...") + "\n" | |
s += Paint("silver").Render("\n Selected files till now:") + "\n" | |
if m.NoFileSelected { | |
s += Paint("red").Render("\n No file selected. Please select at least one file or quit.") + "\n" | |
} | |
for i := 0; i < len(m.FilesPath); i++ { | |
s += fmt.Sprintf(" %s\n", Paint("green").Render(m.FilesPath[i])) | |
} | |
s += "\n" | |
for i := m.scrollOffset; i < m.scrollOffset+m.WindowHeight && i < len(m.FilesAndDir); i++ { | |
choice := m.FilesAndDir[i] | |
checkDir, err := IsDirectory(choice) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | |
} | |
if checkDir { | |
choice = Paint("blue").Render("❒ " + choice) | |
} else if Contains(m.FilesPath, choice) { | |
choice = Paint("lime").Render("❒ " + choice) | |
} else { | |
choice = Paint("silver").Render("❒ " + choice) | |
} | |
cursor := " " | |
if m.cursor == i { | |
cursor = Paint("red").Render(" ➪") | |
} | |
s += fmt.Sprintf("%s %s\n", cursor, choice) | |
} | |
s += Paint("silver").Render("\n 'q' to quit 'esc' to move to parent directory\n '↑' to go up 'x' to modify selected files\n '↓' to go down 'enter' to select pointed file/move to pointed sub folder") | |
return s | |
} | |
// View renders the view of the FilesSelector struct for the TUI. | |
func (m FilesSelector) View() string { | |
if m.Error != nil { | |
return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | |
} | |
s := Paint("silver").Render("\n Select the files you want to modify...") + "\n" | |
s += Paint("silver").Render("\n Selected files till now:") + "\n" | |
if m.NoFileSelected { | |
s += Paint("red").Render("\n No file selected. Please select at least one file or quit.") + "\n" | |
} | |
for i := 0; i < len(m.FilesPath); i++ { | |
s += fmt.Sprintf(" %s\n", Paint("green").Render(m.FilesPath[i])) | |
} | |
s += "\n" | |
for i := m.scrollOffset; i < m.scrollOffset+m.WindowHeight && i < len(m.FilesAndDir); i++ { | |
choice := m.FilesAndDir[i] | |
checkDir, err := IsDirectory(choice) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) | |
} | |
if checkDir { | |
choice = Paint("blue").Render("❒ " + choice) | |
} else if Contains(m.FilesPath, choice) { | |
choice = Paint("lime").Render("❒ " + choice) | |
} else { | |
choice = Paint("silver").Render("❒ " + choice) | |
} | |
cursor := " " | |
if m.cursor == i { | |
cursor = Paint("red").Render(" ➪") | |
} | |
s += fmt.Sprintf("%s %s\n", cursor, choice) | |
} | |
s += Paint("silver").Render("\n 'q' to quit 'esc' to move to parent directory\n '↑' to go up 'x' to modify selected files\n '↓' to go down 'enter' to select pointed file/move to pointed sub folder") | |
return s | |
} |
utils/tui/modelutils/file.go
Outdated
type FilesSelector struct { | ||
CurrentDir string | ||
FilesAndDir []string | ||
SelectedFilesAndDir map[int]bool | ||
FilesPath []string | ||
cursor int | ||
scrollOffset int | ||
Done bool | ||
WindowHeight int | ||
Error error | ||
NoFileSelected bool | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported struct FilesSelector
.
According to Go conventions, exported structs should have a comment explaining their purpose.
+ // FilesSelector represents the main application model for the TUI.
type FilesSelector struct {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
type FilesSelector struct { | |
CurrentDir string | |
FilesAndDir []string | |
SelectedFilesAndDir map[int]bool | |
FilesPath []string | |
cursor int | |
scrollOffset int | |
Done bool | |
WindowHeight int | |
Error error | |
NoFileSelected bool | |
} | |
// FilesSelector represents the main application model for the TUI. | |
type FilesSelector struct { | |
CurrentDir string | |
FilesAndDir []string | |
SelectedFilesAndDir map[int]bool | |
FilesPath []string | |
cursor int | |
scrollOffset int | |
Done bool | |
WindowHeight int | |
Error error | |
NoFileSelected bool | |
} |
Tools
golangci-lint
[warning] 11-11: exported: exported type FilesSelector should have comment or be unexported
(revive)
utils/tui/modelutils/file.go
Outdated
func (m FilesSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | ||
switch msg := msg.(type) { | ||
case tea.KeyMsg: | ||
if m.Error != nil { | ||
return m, tea.Quit | ||
} | ||
switch msg.String() { | ||
case "ctrl+c", "q": | ||
return m, tea.Quit | ||
case "up": | ||
if m.cursor > 0 { | ||
m.cursor-- | ||
if m.cursor < m.scrollOffset { | ||
m.scrollOffset-- | ||
} | ||
} | ||
case "down": | ||
if m.cursor < len(m.FilesAndDir)-1 { | ||
m.cursor++ | ||
if m.cursor >= m.scrollOffset+m.WindowHeight { | ||
m.scrollOffset++ | ||
} | ||
} | ||
case "enter": | ||
m.NoFileSelected = false | ||
checkDir, err := IsDirectory(m.FilesAndDir[m.cursor]) | ||
if err != nil { | ||
m.Error = fmt.Errorf("error checking directory: %w", err) | ||
return m, tea.Quit | ||
} | ||
if checkDir { | ||
err := moveToNextDir(&m, m.FilesAndDir[m.cursor]) | ||
if err != nil { | ||
m.Error = fmt.Errorf("error checking directory: %w", err) | ||
return m, tea.Quit | ||
} | ||
} else { | ||
if Contains(m.FilesPath, m.FilesAndDir[m.cursor]) { | ||
m.FilesPath = Remove(m.FilesPath, m.FilesAndDir[m.cursor]) | ||
} else { | ||
m.FilesPath = append(m.FilesPath, m.FilesAndDir[m.cursor]) | ||
} | ||
m.SelectedFilesAndDir[m.cursor] = !m.SelectedFilesAndDir[m.cursor] | ||
} | ||
case "esc": | ||
err := moveToPreviousDir(&m) | ||
if err != nil { | ||
m.Error = fmt.Errorf("error moving back: %w", err) | ||
return m, tea.Quit | ||
} | ||
case "x": | ||
if len(m.FilesPath) == 0 { | ||
m.NoFileSelected = true | ||
} else { | ||
m.Done = true | ||
} | ||
} | ||
} | ||
return m, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported method Update
.
According to Go conventions, exported methods should have a comment explaining their purpose.
+ // Update updates the state of the FilesSelector struct based on user input.
func (m FilesSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (m FilesSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | |
switch msg := msg.(type) { | |
case tea.KeyMsg: | |
if m.Error != nil { | |
return m, tea.Quit | |
} | |
switch msg.String() { | |
case "ctrl+c", "q": | |
return m, tea.Quit | |
case "up": | |
if m.cursor > 0 { | |
m.cursor-- | |
if m.cursor < m.scrollOffset { | |
m.scrollOffset-- | |
} | |
} | |
case "down": | |
if m.cursor < len(m.FilesAndDir)-1 { | |
m.cursor++ | |
if m.cursor >= m.scrollOffset+m.WindowHeight { | |
m.scrollOffset++ | |
} | |
} | |
case "enter": | |
m.NoFileSelected = false | |
checkDir, err := IsDirectory(m.FilesAndDir[m.cursor]) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return m, tea.Quit | |
} | |
if checkDir { | |
err := moveToNextDir(&m, m.FilesAndDir[m.cursor]) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return m, tea.Quit | |
} | |
} else { | |
if Contains(m.FilesPath, m.FilesAndDir[m.cursor]) { | |
m.FilesPath = Remove(m.FilesPath, m.FilesAndDir[m.cursor]) | |
} else { | |
m.FilesPath = append(m.FilesPath, m.FilesAndDir[m.cursor]) | |
} | |
m.SelectedFilesAndDir[m.cursor] = !m.SelectedFilesAndDir[m.cursor] | |
} | |
case "esc": | |
err := moveToPreviousDir(&m) | |
if err != nil { | |
m.Error = fmt.Errorf("error moving back: %w", err) | |
return m, tea.Quit | |
} | |
case "x": | |
if len(m.FilesPath) == 0 { | |
m.NoFileSelected = true | |
} else { | |
m.Done = true | |
} | |
} | |
} | |
return m, nil | |
// Update updates the state of the FilesSelector struct based on user input. | |
func (m FilesSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | |
switch msg := msg.(type) { | |
case tea.KeyMsg: | |
if m.Error != nil { | |
return m, tea.Quit | |
} | |
switch msg.String() { | |
case "ctrl+c", "q": | |
return m, tea.Quit | |
case "up": | |
if m.cursor > 0 { | |
m.cursor-- | |
if m.cursor < m.scrollOffset { | |
m.scrollOffset-- | |
} | |
} | |
case "down": | |
if m.cursor < len(m.FilesAndDir)-1 { | |
m.cursor++ | |
if m.cursor >= m.scrollOffset+m.WindowHeight { | |
m.scrollOffset++ | |
} | |
} | |
case "enter": | |
m.NoFileSelected = false | |
checkDir, err := IsDirectory(m.FilesAndDir[m.cursor]) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return m, tea.Quit | |
} | |
if checkDir { | |
err := moveToNextDir(&m, m.FilesAndDir[m.cursor]) | |
if err != nil { | |
m.Error = fmt.Errorf("error checking directory: %w", err) | |
return m, tea.Quit | |
} | |
} else { | |
if Contains(m.FilesPath, m.FilesAndDir[m.cursor]) { | |
m.FilesPath = Remove(m.FilesPath, m.FilesAndDir[m.cursor]) | |
} else { | |
m.FilesPath = append(m.FilesPath, m.FilesAndDir[m.cursor]) | |
} | |
m.SelectedFilesAndDir[m.cursor] = !m.SelectedFilesAndDir[m.cursor] | |
} | |
case "esc": | |
err := moveToPreviousDir(&m) | |
if err != nil { | |
m.Error = fmt.Errorf("error moving back: %w", err) | |
return m, tea.Quit | |
} | |
case "x": | |
if len(m.FilesPath) == 0 { | |
m.NoFileSelected = true | |
} else { | |
m.Done = true | |
} | |
} | |
} | |
return m, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- utils/modfile/modfile.go (1 hunks)
Additional context used
golangci-lint
utils/modfile/modfile.go
60-60: Error return value of
file.Close
is not checked(errcheck)
103-103: Error return value of
tmpFile.Close
is not checked(errcheck)
108-108: Error return value of
tmpFile.Close
is not checked(errcheck)
109-109: Error return value of
os.Remove
is not checked(errcheck)
116-116: Error return value of
tmpFile.Close
is not checked(errcheck)
117-117: Error return value of
os.Remove
is not checked(errcheck)
123-123: Error return value of
tmpFile.Close
is not checked(errcheck)
124-124: Error return value of
os.Remove
is not checked(errcheck)
130-130: Error return value of
os.Remove
is not checked(errcheck)
141-141: Error return value of
os.Remove
is not checked(errcheck)
41-41: unnecessary trailing newline
(whitespace)
198-198: unnecessary leading newline
(whitespace)
230-230: unnecessary leading newline
(whitespace)
241-241: unnecessary trailing newline
(whitespace)
Additional comments not posted (6)
utils/modfile/modfile.go (6)
16-25
: LGTM! Struct definition is well-defined.The
Config
struct is well-defined and follows Go conventions.
147-152
: LGTM! Function is straightforward and correct.The
shouldProcessLine
function is straightforward and appears correct.
257-276
: LGTM! Function is straightforward and correct.The
createBackup
function is straightforward and appears correct.
278-283
: LGTM! Function is straightforward and correct.The
restoreBackup
function is straightforward and appears correct.
285-308
: LGTM! Function is straightforward and correct.The
findLines
function is straightforward and appears correct.
387-419
: LGTM! Variable definition is well-defined.The
CommentChars
variable is well-defined and follows Go conventions.
utils/modfile/modfile.go
Outdated
func ChangeFile(conf Config) error { | ||
var file *os.File | ||
var err error | ||
var isStdin bool | ||
|
||
if conf.Filename == "" { | ||
// Read from stdin | ||
file = os.Stdin | ||
isStdin = true | ||
} else { | ||
// Open the file | ||
file, err = os.Open(conf.Filename) | ||
if err != nil { | ||
return err | ||
} | ||
defer file.Close() | ||
} | ||
|
||
char, err := selectCommentChars(conf.Filename, conf.Lang) | ||
if err != nil { | ||
return err | ||
} | ||
modFunc, err := setModFunc(conf.Action) | ||
if err != nil { | ||
return err | ||
} | ||
lines := [2]int{0, 0} | ||
if conf.LineNum != "" { | ||
lines, err = findLines(conf.LineNum) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
if conf.DryRun { | ||
err := printChanges(file, lines, conf.StartLabel, conf.EndLabel, char, modFunc) | ||
if err != nil { | ||
return fmt.Errorf("failed to process the file: %s", err) | ||
} | ||
} else { | ||
if isStdin { | ||
err := printOutput(file, lines, conf.StartLabel, conf.EndLabel, char, modFunc) | ||
if err != nil { | ||
return fmt.Errorf("failed to process the file: %s", err) | ||
} | ||
} else { | ||
// Create a backup of the original file | ||
backupFilename := conf.Filename + ".bak" | ||
if err := createBackup(conf.Filename, backupFilename); err != nil { | ||
return err | ||
} | ||
|
||
// Create a temporary file | ||
tmpFilename := conf.Filename + ".tmp" | ||
tmpFile, err := os.Create(tmpFilename) | ||
if err != nil { | ||
restoreBackup(conf.Filename, backupFilename) | ||
return err | ||
} | ||
defer tmpFile.Close() | ||
|
||
_, err = file.Seek(0, io.SeekStart) | ||
if err != nil { | ||
restoreBackup(conf.Filename, backupFilename) | ||
tmpFile.Close() | ||
os.Remove(tmpFilename) | ||
return err | ||
} | ||
|
||
err = writeChanges(file, tmpFile, lines, conf.StartLabel, conf.EndLabel, char, modFunc) | ||
if err != nil { | ||
restoreBackup(conf.Filename, backupFilename) | ||
tmpFile.Close() | ||
os.Remove(tmpFilename) | ||
return err | ||
} | ||
|
||
if err := file.Close(); err != nil { | ||
restoreBackup(conf.Filename, backupFilename) | ||
tmpFile.Close() | ||
os.Remove(tmpFilename) | ||
return err | ||
} | ||
|
||
// Close the temporary file before renaming | ||
if err := tmpFile.Close(); err != nil { | ||
os.Remove(tmpFilename) | ||
return err | ||
} | ||
|
||
// Rename temporary file to original file | ||
if err := os.Rename(tmpFilename, conf.Filename); err != nil { | ||
restoreBackup(conf.Filename, backupFilename) | ||
return err | ||
} | ||
|
||
// Remove backup file after successful processing | ||
os.Remove(backupFilename) | ||
} | ||
} | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider refactoring the ChangeFile
function for better readability and maintainability.
The function is lengthy and could be broken down into smaller helper functions.
func ChangeFile(conf Config) error {
file, isStdin, err := openFile(conf.Filename)
if err != nil {
return err
}
defer func() {
if err := file.Close(); err != nil {
log.Printf("failed to close file: %v", err)
}
}()
char, err := selectCommentChars(conf.Filename, conf.Lang)
if err != nil {
return err
}
modFunc, err := setModFunc(conf.Action)
if err != nil {
return err
}
lines, err := getLines(conf.LineNum)
if err != nil {
return err
}
if conf.DryRun {
return printChanges(file, lines, conf.StartLabel, conf.EndLabel, char, modFunc)
}
if isStdin {
return printOutput(file, lines, conf.StartLabel, conf.EndLabel, char, modFunc)
}
return processFile(file, conf.Filename, lines, conf.StartLabel, conf.EndLabel, char, modFunc)
}
Tools
golangci-lint
60-60: Error return value of
file.Close
is not checked(errcheck)
103-103: Error return value of
tmpFile.Close
is not checked(errcheck)
108-108: Error return value of
tmpFile.Close
is not checked(errcheck)
109-109: Error return value of
os.Remove
is not checked(errcheck)
116-116: Error return value of
tmpFile.Close
is not checked(errcheck)
117-117: Error return value of
os.Remove
is not checked(errcheck)
123-123: Error return value of
tmpFile.Close
is not checked(errcheck)
124-124: Error return value of
os.Remove
is not checked(errcheck)
130-130: Error return value of
os.Remove
is not checked(errcheck)
141-141: Error return value of
os.Remove
is not checked(errcheck)
utils/modfile/modfile.go
Outdated
func selectCommentChars(filename, lang string) (string, error) { | ||
if lang != "" { | ||
lang = strings.ToLower(lang) | ||
commentChars, ok := CommentChars[lang] | ||
if !ok { | ||
return "", fmt.Errorf("unsupported language: %s", lang) | ||
} | ||
return commentChars, nil | ||
} | ||
|
||
if filename != "" { | ||
extension := filepath.Ext(filename) | ||
switch extension { | ||
case ".go": | ||
return CommentChars["golang"], nil | ||
case ".js": | ||
return CommentChars["js"], nil | ||
case ".sh", ".bash": | ||
return CommentChars["bash"], nil | ||
case ".cpp", ".cc", ".h", ".c": | ||
return CommentChars["c"], nil | ||
case ".java": | ||
return CommentChars["java"], nil | ||
case ".py": | ||
return CommentChars["python"], nil | ||
case ".rb": | ||
return CommentChars["ruby"], nil | ||
case ".pl": | ||
return CommentChars["perl"], nil | ||
case ".php": | ||
return CommentChars["php"], nil | ||
case ".swift": | ||
return CommentChars["swift"], nil | ||
case ".kt", ".kts": | ||
return CommentChars["kotlin"], nil | ||
case ".R": | ||
return CommentChars["r"], nil | ||
case ".hs": | ||
return CommentChars["haskell"], nil | ||
case ".sql": | ||
return CommentChars["sql"], nil | ||
case ".rs": | ||
return CommentChars["rust"], nil | ||
case ".scala": | ||
return CommentChars["scala"], nil | ||
case ".dart": | ||
return CommentChars["dart"], nil | ||
case ".mm": | ||
return CommentChars["objective-c"], nil | ||
case ".m": | ||
return CommentChars["matlab"], nil | ||
case ".lua": | ||
return CommentChars["lua"], nil | ||
case ".erl": | ||
return CommentChars["erlang"], nil | ||
case ".ex", ".exs": | ||
return CommentChars["elixir"], nil | ||
case ".ts": | ||
return CommentChars["ts"], nil | ||
case ".vhdl", ".vhd": | ||
return CommentChars["vhdl"], nil | ||
case ".v", ".sv": | ||
return CommentChars["verilog"], nil | ||
case ".slang": | ||
return CommentChars["slangroom"], nil | ||
case ".zen": | ||
return CommentChars["zenroom"], nil | ||
case ".html": | ||
return CommentChars["html"], nil | ||
default: | ||
return "", fmt.Errorf("unsupported file extension: %s", extension) | ||
} | ||
} | ||
|
||
return "", fmt.Errorf("language not specified and no filename provided") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider refactoring the selectCommentChars
function for better readability and maintainability.
The function is lengthy and could be broken down into smaller helper functions.
func selectCommentChars(filename, lang string) (string, error) {
if lang != "" {
return getCommentCharsByLang(lang)
}
if filename != "" {
return getCommentCharsByExtension(filepath.Ext(filename))
}
return "", fmt.Errorf("language not specified and no filename provided")
}
func getCommentCharsByLang(lang string) (string, error) {
lang = strings.ToLower(lang)
commentChars, ok := CommentChars[lang]
if !ok {
return "", fmt.Errorf("unsupported language: %s", lang)
}
return commentChars, nil
}
func getCommentCharsByExtension(extension string) (string, error) {
switch extension {
case ".go":
return CommentChars["golang"], nil
case ".js":
return CommentChars["js"], nil
// Add remaining cases here
default:
return "", fmt.Errorf("unsupported file extension: %s", extension)
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 25
Outside diff range and nitpick comments (1)
utils/tui/modelutils/option.go (1)
Line range hint
266-281
:
Add a comment for the exported functionAbsToRel
.The
AbsToRel
function is exported and should have a comment for proper documentation.+// AbsToRel converts an absolute path to a relative path. func AbsToRel(absPath string) (string, error) {
Tools
golangci-lint
93-93: unnecessary trailing newline
(whitespace)
68-68: unnecessary leading newline
(whitespace)
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (5)
- cmd/root.go (1 hunks)
- utils/modfile/modfile.go (1 hunks)
- utils/tui/model.go (1 hunks)
- utils/tui/modelutils/option.go (1 hunks)
- utils/tui/modelutils/text.go (1 hunks)
Additional context used
golangci-lint
utils/tui/modelutils/option.go
93-93: unnecessary trailing newline
(whitespace)
68-68: unnecessary leading newline
(whitespace)
utils/tui/modelutils/text.go
[warning] 12-12: exported: exported type LabelInput should have comment or be unexported
(revive)
[warning] 22-22: exported: exported function NewLabelInput should have comment or be unexported
(revive)
[warning] 31-31: exported: exported method LabelInput.Init should have comment or be unexported
(revive)
[warning] 35-35: exported: exported method LabelInput.Update should have comment or be unexported
(revive)
utils/tui/model.go
109-109: unnecessary trailing newline
(whitespace)
121-121: unnecessary trailing newline
(whitespace)
utils/modfile/modfile.go
60-60: Error return value of
file.Close
is not checked(errcheck)
103-103: Error return value of
tmpFile.Close
is not checked(errcheck)
108-108: Error return value of
tmpFile.Close
is not checked(errcheck)
109-109: Error return value of
os.Remove
is not checked(errcheck)
116-116: Error return value of
tmpFile.Close
is not checked(errcheck)
117-117: Error return value of
os.Remove
is not checked(errcheck)
123-123: Error return value of
tmpFile.Close
is not checked(errcheck)
124-124: Error return value of
os.Remove
is not checked(errcheck)
130-130: Error return value of
os.Remove
is not checked(errcheck)
141-141: Error return value of
os.Remove
is not checked(errcheck)
41-41: unnecessary trailing newline
(whitespace)
198-198: unnecessary leading newline
(whitespace)
230-230: unnecessary leading newline
(whitespace)
241-241: unnecessary trailing newline
(whitespace)
Additional comments not posted (4)
utils/tui/modelutils/option.go (1)
15-22
: Add a comment for the exportedNewModeSelector
function.The
NewModeSelector
function is exported and should have a comment for proper documentation.+// NewModeSelector creates a new instance of ModeSelector with the given choices, file, and speed. func NewModeSelector(choices []string, file string, speed string) ModeSelector {
Likely invalid or redundant comment.
utils/modfile/modfile.go (3)
147-152
: LGTM!The function is simple and correct.
257-276
: LGTM!The function is simple and correct.
278-283
: LGTM!The function is simple and correct.
utils/modfile/modfile.go
Outdated
var file *os.File | ||
var err error | ||
var isStdin bool | ||
|
||
if conf.Filename == "" { | ||
// Read from stdin | ||
file = os.Stdin | ||
isStdin = true | ||
} else { | ||
// Open the file | ||
file, err = os.Open(conf.Filename) | ||
if err != nil { | ||
return err | ||
} | ||
defer file.Close() | ||
} | ||
|
||
char, err := selectCommentChars(conf.Filename, conf.Lang) | ||
if err != nil { | ||
return err | ||
} | ||
modFunc, err := setModFunc(conf.Action) | ||
if err != nil { | ||
return err | ||
} | ||
lines := [2]int{0, 0} | ||
if conf.LineNum != "" { | ||
lines, err = findLines(conf.LineNum) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
if conf.DryRun { | ||
err := printChanges(file, lines, conf.StartLabel, conf.EndLabel, char, modFunc) | ||
if err != nil { | ||
return fmt.Errorf("failed to process the file: %s", err) | ||
} | ||
} else { | ||
if isStdin { | ||
err := printOutput(file, lines, conf.StartLabel, conf.EndLabel, char, modFunc) | ||
if err != nil { | ||
return fmt.Errorf("failed to process the file: %s", err) | ||
} | ||
} else { | ||
// Create a backup of the original file | ||
backupFilename := conf.Filename + ".bak" | ||
if err := createBackup(conf.Filename, backupFilename); err != nil { | ||
return err | ||
} | ||
|
||
// Create a temporary file | ||
tmpFilename := conf.Filename + ".tmp" | ||
tmpFile, err := os.Create(tmpFilename) | ||
if err != nil { | ||
restoreBackup(conf.Filename, backupFilename) | ||
return err | ||
} | ||
defer tmpFile.Close() | ||
|
||
_, err = file.Seek(0, io.SeekStart) | ||
if err != nil { | ||
restoreBackup(conf.Filename, backupFilename) | ||
tmpFile.Close() | ||
os.Remove(tmpFilename) | ||
return err | ||
} | ||
|
||
err = writeChanges(file, tmpFile, lines, conf.StartLabel, conf.EndLabel, char, modFunc) | ||
if err != nil { | ||
restoreBackup(conf.Filename, backupFilename) | ||
tmpFile.Close() | ||
os.Remove(tmpFilename) | ||
return err | ||
} | ||
|
||
if err := file.Close(); err != nil { | ||
restoreBackup(conf.Filename, backupFilename) | ||
tmpFile.Close() | ||
os.Remove(tmpFilename) | ||
return err | ||
} | ||
|
||
// Close the temporary file before renaming | ||
if err := tmpFile.Close(); err != nil { | ||
os.Remove(tmpFilename) | ||
return err | ||
} | ||
|
||
// Rename temporary file to original file | ||
if err := os.Rename(tmpFilename, conf.Filename); err != nil { | ||
restoreBackup(conf.Filename, backupFilename) | ||
return err | ||
} | ||
|
||
// Remove backup file after successful processing | ||
os.Remove(backupFilename) | ||
} | ||
} | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor the ChangeFile
function for better readability and maintainability.
The function is lengthy and could be broken down into smaller helper functions.
func ChangeFile(conf Config) error {
file, isStdin, err := openFile(conf.Filename)
if err != nil {
return err
}
defer func() {
if err := file.Close(); err != nil {
log.Printf("failed to close file: %v", err)
}
}()
char, err := selectCommentChars(conf.Filename, conf.Lang)
if err != nil {
return err
}
modFunc, err := setModFunc(conf.Action)
if err != nil {
return err
}
lines, err := getLines(conf.LineNum)
if err != nil {
return err
}
if conf.DryRun {
return printChanges(file, lines, conf.StartLabel, conf.EndLabel, char, modFunc)
}
if isStdin {
return printOutput(file, lines, conf.StartLabel, conf.EndLabel, char, modFunc)
}
return processFile(file, conf.Filename, lines, conf.StartLabel, conf.EndLabel, char, modFunc)
}
Tools
golangci-lint
60-60: Error return value of
file.Close
is not checked(errcheck)
103-103: Error return value of
tmpFile.Close
is not checked(errcheck)
108-108: Error return value of
tmpFile.Close
is not checked(errcheck)
109-109: Error return value of
os.Remove
is not checked(errcheck)
116-116: Error return value of
tmpFile.Close
is not checked(errcheck)
117-117: Error return value of
os.Remove
is not checked(errcheck)
123-123: Error return value of
tmpFile.Close
is not checked(errcheck)
124-124: Error return value of
os.Remove
is not checked(errcheck)
130-130: Error return value of
os.Remove
is not checked(errcheck)
141-141: Error return value of
os.Remove
is not checked(errcheck)
utils/modfile/modfile.go
Outdated
func selectCommentChars(filename, lang string) (string, error) { | ||
if lang != "" { | ||
lang = strings.ToLower(lang) | ||
commentChars, ok := CommentChars[lang] | ||
if !ok { | ||
return "", fmt.Errorf("unsupported language: %s", lang) | ||
} | ||
return commentChars, nil | ||
} | ||
|
||
if filename != "" { | ||
extension := filepath.Ext(filename) | ||
switch extension { | ||
case ".go": | ||
return CommentChars["golang"], nil | ||
case ".js": | ||
return CommentChars["js"], nil | ||
case ".sh", ".bash": | ||
return CommentChars["bash"], nil | ||
case ".cpp", ".cc", ".h", ".c", ".cs": | ||
return CommentChars["c"], nil | ||
case ".java": | ||
return CommentChars["java"], nil | ||
case ".py": | ||
return CommentChars["python"], nil | ||
case ".rb": | ||
return CommentChars["ruby"], nil | ||
case ".pl": | ||
return CommentChars["perl"], nil | ||
case ".php": | ||
return CommentChars["php"], nil | ||
case ".swift": | ||
return CommentChars["swift"], nil | ||
case ".kt", ".kts": | ||
return CommentChars["kotlin"], nil | ||
case ".R": | ||
return CommentChars["r"], nil | ||
case ".hs": | ||
return CommentChars["haskell"], nil | ||
case ".sql": | ||
return CommentChars["sql"], nil | ||
case ".rs": | ||
return CommentChars["rust"], nil | ||
case ".scala": | ||
return CommentChars["scala"], nil | ||
case ".dart": | ||
return CommentChars["dart"], nil | ||
case ".mm": | ||
return CommentChars["objective-c"], nil | ||
case ".m": | ||
return CommentChars["matlab"], nil | ||
case ".lua": | ||
return CommentChars["lua"], nil | ||
case ".erl": | ||
return CommentChars["erlang"], nil | ||
case ".ex", ".exs": | ||
return CommentChars["elixir"], nil | ||
case ".ts": | ||
return CommentChars["ts"], nil | ||
case ".vhdl", ".vhd": | ||
return CommentChars["vhdl"], nil | ||
case ".v", ".sv": | ||
return CommentChars["verilog"], nil | ||
case ".slang": | ||
return CommentChars["slangroom"], nil | ||
case ".zen": | ||
return CommentChars["zenroom"], nil | ||
case ".html": | ||
return CommentChars["html"], nil | ||
default: | ||
return "", fmt.Errorf("unsupported file extension: %s", extension) | ||
} | ||
} | ||
|
||
return "", fmt.Errorf("language not specified and no filename provided") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider refactoring the selectCommentChars
function for better readability and maintainability.
The function is lengthy and could be broken down into smaller helper functions.
func selectCommentChars(filename, lang string) (string, error) {
if lang != "" {
return getCommentCharsByLang(lang)
}
if filename != "" {
return getCommentCharsByExtension(filepath.Ext(filename))
}
return "", fmt.Errorf("language not specified and no filename provided")
}
func getCommentCharsByLang(lang string) (string, error) {
lang = strings.ToLower(lang)
commentChars, ok := CommentChars[lang]
if !ok {
return "", fmt.Errorf("unsupported language: %s", lang)
}
return commentChars, nil
}
func getCommentCharsByExtension(extension string) (string, error) {
switch extension {
case ".go":
return CommentChars["golang"], nil
case ".js":
return CommentChars["js"], nil
// Add remaining cases here
default:
return "", fmt.Errorf("unsupported file extension: %s", extension)
}
}
utils/modfile/modfile.go
Outdated
func printOutput(input *os.File, lineNum [2]int, startLabel, endLabel, commentChars string, modFunc func(string, string) string) error { | ||
scanner := bufio.NewScanner(input) | ||
currentLine := 1 | ||
inSection := false | ||
|
||
for scanner.Scan() { | ||
|
||
lineContent := scanner.Text() | ||
|
||
if strings.Contains(lineContent, endLabel) { | ||
inSection = false | ||
} | ||
|
||
if shouldProcessLine(currentLine, lineNum, startLabel, endLabel, inSection) { | ||
lineContent = modFunc(lineContent, commentChars) | ||
|
||
} | ||
|
||
if strings.Contains(lineContent, startLabel) { | ||
inSection = true | ||
} | ||
fmt.Println(lineContent) | ||
currentLine++ | ||
} | ||
|
||
if lineNum[1] > currentLine && startLabel == "" && endLabel == "" { | ||
return errors.New("line number is out of range") | ||
} | ||
|
||
return scanner.Err() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplify the logic for processing lines in printOutput
.
The logic for processing lines can be simplified by combining conditions. Remove the unnecessary leading and trailing newlines.
- scanner := bufio.NewScanner(input)
- currentLine := 1
- inSection := false
-
- for scanner.Scan() {
- lineContent := scanner.Text()
- if strings.Contains(lineContent, endLabel) {
- inSection = false
- }
-
- if shouldProcessLine(currentLine, lineNum, startLabel, endLabel, inSection) {
- lineContent = modFunc(lineContent, commentChars)
- }
-
- if strings.Contains(lineContent, startLabel) {
- inSection = true
- }
- fmt.Println(lineContent)
- currentLine++
- }
-
- if lineNum[1] > currentLine && startLabel == "" && endLabel == "" {
- return errors.New("line number is out of range")
- }
-
- return scanner.Err()
+ scanner := bufio.NewScanner(input)
+ currentLine := 1
+ inSection := false
+
+ for scanner.Scan() {
+ lineContent := scanner.Text()
+ if strings.Contains(lineContent, endLabel) {
+ inSection = false
+ }
+
+ if shouldProcessLine(currentLine, lineNum, startLabel, endLabel, inSection) {
+ lineContent = modFunc(lineContent, commentChars)
+ }
+
+ if strings.Contains(lineContent, startLabel) {
+ inSection = true
+ }
+ fmt.Println(lineContent)
+ currentLine++
+ }
+
+ if lineNum[1] > currentLine && startLabel == "" && endLabel == "" {
+ return errors.New("line number is out of range")
+ }
+
+ return scanner.Err()
Committable suggestion was skipped due to low confidence.
Tools
golangci-lint
230-230: unnecessary leading newline
(whitespace)
241-241: unnecessary trailing newline
(whitespace)
utils/modfile/modfile.go
Outdated
func findLines(lineStr string) ([2]int, error) { | ||
if strings.Contains(lineStr, "-") { | ||
parts := strings.Split(lineStr, "-") | ||
if len(parts) != 2 { | ||
return [2]int{0, 0}, fmt.Errorf("invalid range format. Use 'start-end'") | ||
} | ||
startLine, err := strconv.Atoi(parts[0]) | ||
if err != nil || startLine <= 0 { | ||
return [2]int{0, 0}, fmt.Errorf("invalid start line number") | ||
} | ||
endLine, err := strconv.Atoi(parts[1]) | ||
if err != nil || endLine < startLine { | ||
return [2]int{0, 0}, fmt.Errorf("invalid end line number") | ||
} | ||
return [2]int{startLine, endLine}, nil | ||
} else { | ||
startLine, err := strconv.Atoi(lineStr) | ||
if err != nil || startLine <= 0 { | ||
return [2]int{0, 0}, fmt.Errorf("please provide a valid positive integer for the line number or a range") | ||
} | ||
endLine := startLine | ||
return [2]int{startLine, endLine}, nil | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplify the findLines
function and improve error messages.
The function can be simplified and the error messages can be more specific.
func findLines(lineStr string) ([2]int, error) {
parts := strings.Split(lineStr, "-")
if len(parts) == 1 {
startLine, err := strconv.Atoi(parts[0])
if err != nil || startLine <= 0 {
return [2]int{0, 0}, fmt.Errorf("please provide a valid positive integer for the line number")
}
return [2]int{startLine, startLine}, nil
}
if len(parts) == 2 {
startLine, err := strconv.Atoi(parts[0])
if err != nil || startLine <= 0 {
return [2]int{0, 0}, fmt.Errorf("invalid start line number")
}
endLine, err := strconv.Atoi(parts[1])
if err != nil || endLine < startLine {
return [2]int{0, 0}, fmt.Errorf("invalid end line number")
}
return [2]int{startLine, endLine}, nil
}
return [2]int{0, 0}, fmt.Errorf("invalid range format. Use 'start-end'")
}
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func findLines(lineStr string) ([2]int, error) { | |
if strings.Contains(lineStr, "-") { | |
parts := strings.Split(lineStr, "-") | |
if len(parts) != 2 { | |
return [2]int{0, 0}, fmt.Errorf("invalid range format. Use 'start-end'") | |
} | |
startLine, err := strconv.Atoi(parts[0]) | |
if err != nil || startLine <= 0 { | |
return [2]int{0, 0}, fmt.Errorf("invalid start line number") | |
} | |
endLine, err := strconv.Atoi(parts[1]) | |
if err != nil || endLine < startLine { | |
return [2]int{0, 0}, fmt.Errorf("invalid end line number") | |
} | |
return [2]int{startLine, endLine}, nil | |
} else { | |
startLine, err := strconv.Atoi(lineStr) | |
if err != nil || startLine <= 0 { | |
return [2]int{0, 0}, fmt.Errorf("please provide a valid positive integer for the line number or a range") | |
} | |
endLine := startLine | |
return [2]int{startLine, endLine}, nil | |
} | |
} | |
func findLines(lineStr string) ([2]int, error) { | |
parts := strings.Split(lineStr, "-") | |
if len(parts) == 1 { | |
startLine, err := strconv.Atoi(parts[0]) | |
if err != nil || startLine <= 0 { | |
return [2]int{0, 0}, fmt.Errorf("please provide a valid positive integer for the line number") | |
} | |
return [2]int{startLine, startLine}, nil | |
} | |
if len(parts) == 2 { | |
startLine, err := strconv.Atoi(parts[0]) | |
if err != nil || startLine <= 0 { | |
return [2]int{0, 0}, fmt.Errorf("invalid start line number") | |
} | |
endLine, err := strconv.Atoi(parts[1]) | |
if err != nil || endLine < startLine { | |
return [2]int{0, 0}, fmt.Errorf("invalid end line number") | |
} | |
return [2]int{startLine, endLine}, nil | |
} | |
return [2]int{0, 0}, fmt.Errorf("invalid range format. Use 'start-end'") | |
} |
utils/modfile/modfile.go
Outdated
func printChanges(inputFile *os.File, lineNum [2]int, startLabel, endLabel, commentChars string, modFunc func(string, string) string) error { | ||
scanner := bufio.NewScanner(inputFile) | ||
currentLine := 1 | ||
inSection := false | ||
|
||
for scanner.Scan() { | ||
|
||
lineContent := scanner.Text() | ||
|
||
if strings.Contains(lineContent, endLabel) { | ||
inSection = false | ||
} | ||
|
||
if shouldProcessLine(currentLine, lineNum, startLabel, endLabel, inSection) { | ||
modified := modFunc(lineContent, commentChars) | ||
fmt.Printf("%d: %s -> %s\n", currentLine, lineContent, modified) | ||
} | ||
|
||
if strings.Contains(lineContent, startLabel) { | ||
inSection = true | ||
} | ||
|
||
currentLine++ | ||
} | ||
|
||
if lineNum[1] > currentLine && startLabel == "" && endLabel == "" { | ||
return errors.New("line number is out of range") | ||
} | ||
|
||
return scanner.Err() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplify the logic for processing lines in printChanges
.
The logic for processing lines can be simplified by combining conditions. Remove the unnecessary leading newline.
- scanner := bufio.NewScanner(inputFile)
- currentLine := 1
- inSection := false
-
- for scanner.Scan() {
- lineContent := scanner.Text()
- if strings.Contains(lineContent, endLabel) {
- inSection = false
- }
-
- if shouldProcessLine(currentLine, lineNum, startLabel, endLabel, inSection) {
- modified := modFunc(lineContent, commentChars)
- fmt.Printf("%d: %s -> %s\n", currentLine, lineContent, modified)
- }
-
- if strings.Contains(lineContent, startLabel) {
- inSection = true
- }
-
- currentLine++
- }
-
- if lineNum[1] > currentLine && startLabel == "" && endLabel == "" {
- return errors.New("line number is out of range")
- }
-
- return scanner.Err()
+ scanner := bufio.NewScanner(inputFile)
+ currentLine := 1
+ inSection := false
+
+ for scanner.Scan() {
+ lineContent := scanner.Text()
+ if strings.Contains(lineContent, endLabel) {
+ inSection = false
+ }
+
+ if shouldProcessLine(currentLine, lineNum, startLabel, endLabel, inSection) {
+ modified := modFunc(lineContent, commentChars)
+ fmt.Printf("%d: %s -> %s\n", currentLine, lineContent, modified)
+ }
+
+ if strings.Contains(lineContent, startLabel) {
+ inSection = true
+ }
+
+ currentLine++
+ }
+
+ if lineNum[1] > currentLine && startLabel == "" && endLabel == "" {
+ return errors.New("line number is out of range")
+ }
+
+ return scanner.Err()
Committable suggestion was skipped due to low confidence.
Tools
golangci-lint
198-198: unnecessary leading newline
(whitespace)
cmd/root.go
Outdated
func customUsageFunc(cmd *cobra.Command) error { | ||
fmt.Println(cmd.Short) | ||
fmt.Println("Usage:") | ||
fmt.Printf(" %s\n", cmd.UseLine()) | ||
fmt.Println() | ||
fmt.Println("Flags:") | ||
cmd.Flags().VisitAll(func(flag *pflag.Flag) { | ||
if flag.Name == "action" { | ||
fmt.Printf(" -%s, --%s: %s (default: %s)\n", flag.Shorthand, flag.Name, flag.Usage, flag.DefValue) | ||
} else { | ||
fmt.Printf(" -%s, --%s: %s\n", flag.Shorthand, flag.Name, flag.Usage) | ||
} | ||
}) | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the customUsageFunc
function.
The customUsageFunc
function provides custom usage information.
+// customUsageFunc provides custom usage information.
func customUsageFunc(cmd *cobra.Command) error {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func customUsageFunc(cmd *cobra.Command) error { | |
fmt.Println(cmd.Short) | |
fmt.Println("Usage:") | |
fmt.Printf(" %s\n", cmd.UseLine()) | |
fmt.Println() | |
fmt.Println("Flags:") | |
cmd.Flags().VisitAll(func(flag *pflag.Flag) { | |
if flag.Name == "action" { | |
fmt.Printf(" -%s, --%s: %s (default: %s)\n", flag.Shorthand, flag.Name, flag.Usage, flag.DefValue) | |
} else { | |
fmt.Printf(" -%s, --%s: %s\n", flag.Shorthand, flag.Name, flag.Usage) | |
} | |
}) | |
return nil | |
} | |
// customUsageFunc provides custom usage information. | |
func customUsageFunc(cmd *cobra.Command) error { | |
fmt.Println(cmd.Short) | |
fmt.Println("Usage:") | |
fmt.Printf(" %s\n", cmd.UseLine()) | |
fmt.Println() | |
fmt.Println("Flags:") | |
cmd.Flags().VisitAll(func(flag *pflag.Flag) { | |
if flag.Name == "action" { | |
fmt.Printf(" -%s, --%s: %s (default: %s)\n", flag.Shorthand, flag.Name, flag.Usage, flag.DefValue) | |
} else { | |
fmt.Printf(" -%s, --%s: %s\n", flag.Shorthand, flag.Name, flag.Usage) | |
} | |
}) | |
return nil | |
} |
cmd/root.go
Outdated
func noFlagsGiven(cmd *cobra.Command) bool { | ||
hasFlags := false | ||
cmd.Flags().VisitAll(func(f *pflag.Flag) { | ||
if f.Changed { | ||
hasFlags = true | ||
} | ||
}) | ||
return !hasFlags | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the noFlagsGiven
function.
The noFlagsGiven
function checks if any flags were provided.
+// noFlagsGiven checks if any flags were provided.
func noFlagsGiven(cmd *cobra.Command) bool {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func noFlagsGiven(cmd *cobra.Command) bool { | |
hasFlags := false | |
cmd.Flags().VisitAll(func(f *pflag.Flag) { | |
if f.Changed { | |
hasFlags = true | |
} | |
}) | |
return !hasFlags | |
} | |
// noFlagsGiven checks if any flags were provided. | |
func noFlagsGiven(cmd *cobra.Command) bool { | |
hasFlags := false | |
cmd.Flags().VisitAll(func(f *pflag.Flag) { | |
if f.Changed { | |
hasFlags = true | |
} | |
}) | |
return !hasFlags | |
} |
cmd/root.go
Outdated
func customHelpFunc(cmd *cobra.Command, args []string) { | ||
fmt.Println("Tgcom CLI Application") | ||
fmt.Println() | ||
fmt.Println(cmd.Long) | ||
fmt.Println() | ||
fmt.Println("Usage:") | ||
fmt.Println(" tgcom [flags]") | ||
fmt.Println() | ||
fmt.Println("Flags:") | ||
cmd.Flags().VisitAll(func(flag *pflag.Flag) { | ||
if flag.Name == "action" { | ||
fmt.Printf(" -%s, --%s: %s (default: %s)\n", flag.Shorthand, flag.Name, flag.Usage, flag.DefValue) | ||
} else { | ||
fmt.Printf(" -%s, --%s: %s\n", flag.Shorthand, flag.Name, flag.Usage) | ||
} | ||
}) | ||
fmt.Println() | ||
fmt.Println("Supported Languages:") | ||
for lang := range modfile.CommentChars { | ||
fmt.Println(lang) | ||
} | ||
fmt.Println() | ||
fmt.Println("Examples:") | ||
fmt.Println(" # Toggle comments on lines 1-5 in example.go") | ||
fmt.Println(" tgcom -f example.go -l 1-5 -a toggle") | ||
fmt.Println() | ||
fmt.Println(" # Dry run: show the changes without modifying the file") | ||
fmt.Println(" tgcom -f example.go -s START -e END -a toggle -d") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the customHelpFunc
function.
The customHelpFunc
function provides custom help information.
+// customHelpFunc provides custom help information.
func customHelpFunc(cmd *cobra.Command, args []string) {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func customHelpFunc(cmd *cobra.Command, args []string) { | |
fmt.Println("Tgcom CLI Application") | |
fmt.Println() | |
fmt.Println(cmd.Long) | |
fmt.Println() | |
fmt.Println("Usage:") | |
fmt.Println(" tgcom [flags]") | |
fmt.Println() | |
fmt.Println("Flags:") | |
cmd.Flags().VisitAll(func(flag *pflag.Flag) { | |
if flag.Name == "action" { | |
fmt.Printf(" -%s, --%s: %s (default: %s)\n", flag.Shorthand, flag.Name, flag.Usage, flag.DefValue) | |
} else { | |
fmt.Printf(" -%s, --%s: %s\n", flag.Shorthand, flag.Name, flag.Usage) | |
} | |
}) | |
fmt.Println() | |
fmt.Println("Supported Languages:") | |
for lang := range modfile.CommentChars { | |
fmt.Println(lang) | |
} | |
fmt.Println() | |
fmt.Println("Examples:") | |
fmt.Println(" # Toggle comments on lines 1-5 in example.go") | |
fmt.Println(" tgcom -f example.go -l 1-5 -a toggle") | |
fmt.Println() | |
fmt.Println(" # Dry run: show the changes without modifying the file") | |
fmt.Println(" tgcom -f example.go -s START -e END -a toggle -d") | |
} | |
// customHelpFunc provides custom help information. | |
func customHelpFunc(cmd *cobra.Command, args []string) { | |
fmt.Println("Tgcom CLI Application") | |
fmt.Println() | |
fmt.Println(cmd.Long) | |
fmt.Println() | |
fmt.Println("Usage:") | |
fmt.Println(" tgcom [flags]") | |
fmt.Println() | |
fmt.Println("Flags:") | |
cmd.Flags().VisitAll(func(flag *pflag.Flag) { | |
if flag.Name == "action" { | |
fmt.Printf(" -%s, --%s: %s (default: %s)\n", flag.Shorthand, flag.Name, flag.Usage, flag.DefValue) | |
} else { | |
fmt.Printf(" -%s, --%s: %s\n", flag.Shorthand, flag.Name, flag.Usage) | |
} | |
}) | |
fmt.Println() | |
fmt.Println("Supported Languages:") | |
for lang := range modfile.CommentChars { | |
fmt.Println(lang) | |
} | |
fmt.Println() | |
fmt.Println("Examples:") | |
fmt.Println(" # Toggle comments on lines 1-5 in example.go") | |
fmt.Println(" tgcom -f example.go -l 1-5 -a toggle") | |
fmt.Println() | |
fmt.Println(" # Dry run: show the changes without modifying the file") | |
fmt.Println(" tgcom -f example.go -s START -e END -a toggle -d") | |
} |
cmd/root.go
Outdated
func init() { | ||
rootCmd.SetHelpFunc(customHelpFunc) | ||
rootCmd.SetUsageFunc(customUsageFunc) | ||
|
||
rootCmd.PersistentFlags().StringVarP(&FileToRead, "file", "f", "", "pass argument to the flag and will modify the file content") | ||
rootCmd.PersistentFlags().StringVarP(&inputFlag.LineNum, "line", "l", "", "pass argument to line flag and will modify the line in the specified range") | ||
rootCmd.PersistentFlags().BoolVarP(&inputFlag.DryRun, "dry-run", "d", false, "pass argument to dry-run flag and will print the result") | ||
rootCmd.PersistentFlags().StringVarP(&inputFlag.Action, "action", "a", "toggle", "pass argument to action to comment/uncomment/toggle some lines") | ||
rootCmd.PersistentFlags().StringVarP(&inputFlag.StartLabel, "start-label", "s", "", "pass argument to start-label to modify lines after start-label") | ||
rootCmd.PersistentFlags().StringVarP(&inputFlag.EndLabel, "end-label", "e", "", "pass argument to end-label to modify lines up to end-label") | ||
rootCmd.PersistentFlags().StringVarP(&inputFlag.Lang, "language", "L", "", "pass argument to language to specify the language of the input code") | ||
rootCmd.PersistentFlags().StringVarP(&remotePath, "remote", "w", "", "pass remote user, host, and directory in the format user@host:/path/to/directory") | ||
rootCmd.PersistentFlags().BoolVarP(&Tui, "tui", "t", false, "run the terminal user interface") | ||
// Mark flags based on command name | ||
rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { | ||
if cmd.Name() != "server" { | ||
cmd.MarkFlagsRequiredTogether("start-label", "end-label") | ||
cmd.MarkFlagsMutuallyExclusive("line", "start-label") | ||
cmd.MarkFlagsMutuallyExclusive("line", "end-label") | ||
cmd.MarkFlagsOneRequired("file", "language", "remote", "tui") | ||
cmd.MarkFlagsMutuallyExclusive("file", "language") | ||
} | ||
return nil | ||
} | ||
|
||
// Register server command | ||
rootCmd.AddCommand(serverCmd) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the init
function.
The init
function sets help and usage functions, registers flags, and adds the server command.
+// init sets help and usage functions, registers flags, and adds the server command.
func init() {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func init() { | |
rootCmd.SetHelpFunc(customHelpFunc) | |
rootCmd.SetUsageFunc(customUsageFunc) | |
rootCmd.PersistentFlags().StringVarP(&FileToRead, "file", "f", "", "pass argument to the flag and will modify the file content") | |
rootCmd.PersistentFlags().StringVarP(&inputFlag.LineNum, "line", "l", "", "pass argument to line flag and will modify the line in the specified range") | |
rootCmd.PersistentFlags().BoolVarP(&inputFlag.DryRun, "dry-run", "d", false, "pass argument to dry-run flag and will print the result") | |
rootCmd.PersistentFlags().StringVarP(&inputFlag.Action, "action", "a", "toggle", "pass argument to action to comment/uncomment/toggle some lines") | |
rootCmd.PersistentFlags().StringVarP(&inputFlag.StartLabel, "start-label", "s", "", "pass argument to start-label to modify lines after start-label") | |
rootCmd.PersistentFlags().StringVarP(&inputFlag.EndLabel, "end-label", "e", "", "pass argument to end-label to modify lines up to end-label") | |
rootCmd.PersistentFlags().StringVarP(&inputFlag.Lang, "language", "L", "", "pass argument to language to specify the language of the input code") | |
rootCmd.PersistentFlags().StringVarP(&remotePath, "remote", "w", "", "pass remote user, host, and directory in the format user@host:/path/to/directory") | |
rootCmd.PersistentFlags().BoolVarP(&Tui, "tui", "t", false, "run the terminal user interface") | |
// Mark flags based on command name | |
rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { | |
if cmd.Name() != "server" { | |
cmd.MarkFlagsRequiredTogether("start-label", "end-label") | |
cmd.MarkFlagsMutuallyExclusive("line", "start-label") | |
cmd.MarkFlagsMutuallyExclusive("line", "end-label") | |
cmd.MarkFlagsOneRequired("file", "language", "remote", "tui") | |
cmd.MarkFlagsMutuallyExclusive("file", "language") | |
} | |
return nil | |
} | |
// Register server command | |
rootCmd.AddCommand(serverCmd) | |
} | |
// init sets help and usage functions, registers flags, and adds the server command. | |
func init() { | |
rootCmd.SetHelpFunc(customHelpFunc) | |
rootCmd.SetUsageFunc(customUsageFunc) | |
rootCmd.PersistentFlags().StringVarP(&FileToRead, "file", "f", "", "pass argument to the flag and will modify the file content") | |
rootCmd.PersistentFlags().StringVarP(&inputFlag.LineNum, "line", "l", "", "pass argument to line flag and will modify the line in the specified range") | |
rootCmd.PersistentFlags().BoolVarP(&inputFlag.DryRun, "dry-run", "d", false, "pass argument to dry-run flag and will print the result") | |
rootCmd.PersistentFlags().StringVarP(&inputFlag.Action, "action", "a", "toggle", "pass argument to action to comment/uncomment/toggle some lines") | |
rootCmd.PersistentFlags().StringVarP(&inputFlag.StartLabel, "start-label", "s", "", "pass argument to start-label to modify lines after start-label") | |
rootCmd.PersistentFlags().StringVarP(&inputFlag.EndLabel, "end-label", "e", "", "pass argument to end-label to modify lines up to end-label") | |
rootCmd.PersistentFlags().StringVarP(&inputFlag.Lang, "language", "L", "", "pass argument to language to specify the language of the input code") | |
rootCmd.PersistentFlags().StringVarP(&remotePath, "remote", "w", "", "pass remote user, host, and directory in the format user@host:/path/to/directory") | |
rootCmd.PersistentFlags().BoolVarP(&Tui, "tui", "t", false, "run the terminal user interface") | |
// Mark flags based on command name | |
rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { | |
if cmd.Name() != "server" { | |
cmd.MarkFlagsRequiredTogether("start-label", "end-label") | |
cmd.MarkFlagsMutuallyExclusive("line", "start-label") | |
cmd.MarkFlagsMutuallyExclusive("line", "end-label") | |
cmd.MarkFlagsOneRequired("file", "language", "remote", "tui") | |
cmd.MarkFlagsMutuallyExclusive("file", "language") | |
} | |
return nil | |
} | |
// Register server command | |
rootCmd.AddCommand(serverCmd) | |
} |
cmd/root.go
Outdated
func ReadFlags(cmd *cobra.Command) { | ||
if Tui { | ||
currentDir, err := os.Getwd() | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Error getting current working directory: %v\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
// Initialize your model with the current directory | ||
model := tui.Model{ | ||
State: "FileSelection", | ||
FilesSelector: modelutils.InitialModel(currentDir, 20), | ||
} | ||
clearScreen() | ||
// Bubble Tea program | ||
p := tea.NewProgram(model) | ||
|
||
// Start the program | ||
if _, err := p.Run(); err != nil { | ||
os.Exit(1) | ||
} | ||
clearScreen() | ||
} else { | ||
|
||
if strings.Contains(FileToRead, ",") { | ||
if cmd.Flags().Changed("line") { | ||
fmt.Println("Warning: when passing multiple files to flag -f, don't use -l flag") | ||
} | ||
if cmd.Flags().Changed("start-label") && cmd.Flags().Changed("end-label") { | ||
fileInfo := strings.Split(FileToRead, ",") | ||
for i := 0; i < len(fileInfo); i++ { | ||
inputFlag.Filename = fileInfo[i] | ||
if err := modfile.ChangeFile(inputFlag); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
} else { | ||
fileInfo := strings.Split(FileToRead, ",") | ||
for i := 0; i < len(fileInfo); i++ { | ||
if strings.Contains(fileInfo[i], ":") { | ||
parts := strings.Split(fileInfo[i], ":") | ||
if len(parts) != 2 { | ||
log.Fatalf("invalid syntax. Use 'File:lines'") | ||
} | ||
inputFlag.Filename = parts[0] | ||
inputFlag.LineNum = parts[1] | ||
if err := modfile.ChangeFile(inputFlag); err != nil { | ||
log.Fatal(err) | ||
} | ||
} else { | ||
log.Fatalf("invalid syntax. Use 'File:lines'") | ||
} | ||
} | ||
} | ||
} else { | ||
if cmd.Flags().Changed("line") || cmd.Flags().Changed("start-label") && cmd.Flags().Changed("end-label") { | ||
inputFlag.Filename = FileToRead | ||
if err := modfile.ChangeFile(inputFlag); err != nil { | ||
log.Fatal(err) | ||
} | ||
} else { | ||
log.Fatalf("Not specified what you want to modify: add -l flag or -s and -e flags") | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the ReadFlags
function.
The ReadFlags
function reads and processes the flags provided by the user.
+// ReadFlags reads and processes the flags provided by the user.
func ReadFlags(cmd *cobra.Command) {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func ReadFlags(cmd *cobra.Command) { | |
if Tui { | |
currentDir, err := os.Getwd() | |
if err != nil { | |
fmt.Fprintf(os.Stderr, "Error getting current working directory: %v\n", err) | |
os.Exit(1) | |
} | |
// Initialize your model with the current directory | |
model := tui.Model{ | |
State: "FileSelection", | |
FilesSelector: modelutils.InitialModel(currentDir, 20), | |
} | |
clearScreen() | |
// Bubble Tea program | |
p := tea.NewProgram(model) | |
// Start the program | |
if _, err := p.Run(); err != nil { | |
os.Exit(1) | |
} | |
clearScreen() | |
} else { | |
if strings.Contains(FileToRead, ",") { | |
if cmd.Flags().Changed("line") { | |
fmt.Println("Warning: when passing multiple files to flag -f, don't use -l flag") | |
} | |
if cmd.Flags().Changed("start-label") && cmd.Flags().Changed("end-label") { | |
fileInfo := strings.Split(FileToRead, ",") | |
for i := 0; i < len(fileInfo); i++ { | |
inputFlag.Filename = fileInfo[i] | |
if err := modfile.ChangeFile(inputFlag); err != nil { | |
log.Fatal(err) | |
} | |
} | |
} else { | |
fileInfo := strings.Split(FileToRead, ",") | |
for i := 0; i < len(fileInfo); i++ { | |
if strings.Contains(fileInfo[i], ":") { | |
parts := strings.Split(fileInfo[i], ":") | |
if len(parts) != 2 { | |
log.Fatalf("invalid syntax. Use 'File:lines'") | |
} | |
inputFlag.Filename = parts[0] | |
inputFlag.LineNum = parts[1] | |
if err := modfile.ChangeFile(inputFlag); err != nil { | |
log.Fatal(err) | |
} | |
} else { | |
log.Fatalf("invalid syntax. Use 'File:lines'") | |
} | |
} | |
} | |
} else { | |
if cmd.Flags().Changed("line") || cmd.Flags().Changed("start-label") && cmd.Flags().Changed("end-label") { | |
inputFlag.Filename = FileToRead | |
if err := modfile.ChangeFile(inputFlag); err != nil { | |
log.Fatal(err) | |
} | |
} else { | |
log.Fatalf("Not specified what you want to modify: add -l flag or -s and -e flags") | |
} | |
} | |
} | |
} | |
// ReadFlags reads and processes the flags provided by the user. | |
func ReadFlags(cmd *cobra.Command) { | |
if Tui { | |
currentDir, err := os.Getwd() | |
if err != nil { | |
fmt.Fprintf(os.Stderr, "Error getting current working directory: %v\n", err) | |
os.Exit(1) | |
} | |
// Initialize your model with the current directory | |
model := tui.Model{ | |
State: "FileSelection", | |
FilesSelector: modelutils.InitialModel(currentDir, 20), | |
} | |
clearScreen() | |
// Bubble Tea program | |
p := tea.NewProgram(model) | |
// Start the program | |
if _, err := p.Run(); err != nil { | |
os.Exit(1) | |
} | |
clearScreen() | |
} else { | |
if strings.Contains(FileToRead, ",") { | |
if cmd.Flags().Changed("line") { | |
fmt.Println("Warning: when passing multiple files to flag -f, don't use -l flag") | |
} | |
if cmd.Flags().Changed("start-label") && cmd.Flags().Changed("end-label") { | |
fileInfo := strings.Split(FileToRead, ",") | |
for i := 0; i < len(fileInfo); i++ { | |
inputFlag.Filename = fileInfo[i] | |
if err := modfile.ChangeFile(inputFlag); err != nil { | |
log.Fatal(err) | |
} | |
} | |
} else { | |
fileInfo := strings.Split(FileToRead, ",") | |
for i := 0; i < len(fileInfo); i++ { | |
if strings.Contains(fileInfo[i], ":") { | |
parts := strings.Split(fileInfo[i], ":") | |
if len(parts) != 2 { | |
log.Fatalf("invalid syntax. Use 'File:lines'") | |
} | |
inputFlag.Filename = parts[0] | |
inputFlag.LineNum = parts[1] | |
if err := modfile.ChangeFile(inputFlag); err != nil { | |
log.Fatal(err) | |
} | |
} else { | |
log.Fatalf("invalid syntax. Use 'File:lines'") | |
} | |
} | |
} | |
} else { | |
if cmd.Flags().Changed("line") || cmd.Flags().Changed("start-label") && cmd.Flags().Changed("end-label") { | |
inputFlag.Filename = FileToRead | |
if err := modfile.ChangeFile(inputFlag); err != nil { | |
log.Fatal(err) | |
} | |
} else { | |
log.Fatalf("Not specified what you want to modify: add -l flag or -s and -e flags") | |
} | |
} | |
} | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
go.sum
is excluded by!**/*.sum
Files selected for processing (3)
- go.mod (1 hunks)
- utils/tui/modelutils/option_test.go (1 hunks)
- utils/tui/modelutils/text_test.go (1 hunks)
Files skipped from review due to trivial changes (1)
- utils/tui/modelutils/option_test.go
Additional comments not posted (22)
go.mod (15)
6-6
: Approved: Dependencygithub.com/adrg/xdg v0.4.0
.This dependency is used for XDG Base Directory Specification support and the version
v0.4.0
is the latest stable version.
7-7
: Approved: Dependencygithub.com/charmbracelet/bubbletea v0.26.4
.This dependency is used for building rich terminal user interfaces and the version
v0.26.4
is the latest stable version.
8-8
: Approved: Dependencygithub.com/charmbracelet/lipgloss v0.10.0
.This dependency is used for styling terminal user interfaces and the version
v0.10.0
is the latest stable version.
10-10
: Approved: Dependencygithub.com/charmbracelet/wish v1.4.0
.This dependency is used for SSH server functionalities and the version
v1.4.0
is the latest stable version.
11-11
: Approved: Dependencygithub.com/creack/pty v1.1.21
.This dependency is used for pseudo-terminal functionalities and the version
v1.1.21
is the latest stable version.
12-12
: Approved: Dependencygithub.com/spf13/cobra v1.8.0
.This dependency is used for creating powerful modern CLI applications and the version
v1.8.0
is the latest stable version.
13-13
: Approved: Dependencygithub.com/spf13/pflag v1.0.5
.This dependency is used for POSIX/GNU-style flag parsing and the version
v1.0.5
is the latest stable version.
14-14
: Approved: Dependencygithub.com/stretchr/testify v1.9.0
.This dependency is used for writing unit tests and the version
v1.9.0
is the latest stable version.
15-15
: Approved: Dependencygolang.org/x/term v0.21.0
.This dependency is used for terminal manipulation and the version
v0.21.0
is the latest stable version.
20-20
: Approved: Dependencygithub.com/aymanbagabas/go-osc52/v2 v2.0.1
.This dependency is used for OSC52 escape sequences and the version
v2.0.1
is the latest stable version.
21-21
: Approved: Dependencygithub.com/charmbracelet/keygen v0.5.0
.This dependency is used for generating SSH keys and the version
v0.5.0
is the latest stable version.
22-22
: Approved: Dependencygithub.com/charmbracelet/log v0.4.0
.This dependency is used for logging and the version
v0.4.0
is the latest stable version.
23-23
: Approved: Dependencygithub.com/charmbracelet/x/ansi v0.1.2
.This dependency is used for ANSI escape sequences and the version
v0.1.2
is the latest stable version.
9-9
: Verify: Dependencygithub.com/charmbracelet/ssh v0.0.0-20240604154955-a40c6a0d028f
.The version
v0.0.0-20240604154955-a40c6a0d028f
is a pseudo-version indicating a specific commit. Verify the commit to ensure it is stable.Verification successful
Verified: Dependency
github.com/charmbracelet/ssh v0.0.0-20240604154955-a40c6a0d028f
The commit
a40c6a0d028f6cca7a08d5b513e1640de8025106
exists and is the currentHEAD
of the master branch, indicating it is stable.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the commit for `github.com/charmbracelet/ssh`. # Test: Check the commit details. Expect: Commit exists and is stable. git ls-remote https://github.com/charmbracelet/ssh.git | grep a40c6a0d028fLength of output: 181
19-19
: Verify: Dependencygithub.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
.The version
v0.0.0-20200514113438-38f4b401e2be
is a pseudo-version indicating a specific commit. Verify the commit to ensure it is stable.Verification successful
Verified: Dependency
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
.The commit
38f4b401e2be5955e3e00b843d96e3c406f5094d
exists and is the HEAD of themaster
branch, confirming its stability and appropriateness.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the commit for `github.com/anmitsu/go-shlex`. # Test: Check the commit details. Expect: Commit exists and is stable. git ls-remote https://github.com/anmitsu/go-shlex.git | grep 38f4b401e2beLength of output: 180
utils/tui/modelutils/text_test.go (7)
13-16
: Approved: TestsetInput
.The function correctly sets the input for
LabelInput
.
17-29
: Approved: TeststripANSI
.The function correctly removes ANSI color codes and trims whitespace.
31-55
: Approved: TestTestNewLabelInput
.The test correctly checks the initialization of
LabelInput
.
57-61
: Approved: TestTestInitLabelInput
.The test correctly checks the initialization command of
LabelInput
.
62-148
: Approved: TestTestUpdateLabelInput
.The test correctly checks the update functionality of
LabelInput
with various messages.
150-191
: Approved: TestTestViewLabelInput
.The test correctly checks the view functionality of
LabelInput
.
194-249
: Approved: TestTestValidateInput
.The test correctly checks the validation of input for
LabelInput
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (3)
- utils/tui/modelutils/file_test.go (1 hunks)
- utils/tui/modelutils/selectorutils.go (1 hunks)
- utils/tui/modelutils/selectorutils_test.go (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- utils/tui/modelutils/selectorutils.go
Additional comments not posted (7)
utils/tui/modelutils/selectorutils_test.go (5)
12-22
: LGTM! Well-structured test cases forIsDirectory
.The test covers both existing and non-existing paths, ensuring robust validation.
24-63
: LGTM! Comprehensive test cases forGetParentDirectory
.The test covers valid directories, root directories, and Windows-specific scenarios, ensuring thorough validation.
66-93
: LGTM! Well-structured test cases forGetPathOfEntry
.The test covers both existing and non-existing entries, ensuring robust validation.
95-117
: LGTM! Well-structured test cases formoveToNextDir
.The test covers both valid and non-existing directories, ensuring robust validation.
119-149
: LGTM! Comprehensive test cases formoveToPreviousDir
.The test covers valid directories and root directories, ensuring thorough validation.
utils/tui/modelutils/file_test.go (2)
12-131
: LGTM! Well-structured and comprehensive test cases forFilesSelector
.The test covers a wide range of scenarios, ensuring robust validation of the
FilesSelector
struct.
133-215
: LGTM! Well-structured and comprehensive test cases forFilesSelector
view rendering.The test covers a wide range of scenarios, ensuring robust validation of the view rendering of the
FilesSelector
struct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (2)
- utils/tui/model.go (1 hunks)
- utils/tui/modelutils/file_test.go (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- utils/tui/modelutils/file_test.go
Additional context used
golangci-lint
utils/tui/model.go
[warning] 190-190: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block
(revive)
83-83: unnecessary leading newline
(whitespace)
121-121: unnecessary trailing newline
(whitespace)
133-133: unnecessary trailing newline
(whitespace)
194-194: unnecessary trailing newline
(whitespace)
Additional comments not posted (5)
utils/tui/model.go (5)
1-11
: LGTM!The package declaration and imports are appropriate and necessary for the functionality provided in the file.
13-29
: LGTM!The
Model
struct is well-defined and includes necessary fields for managing the application's state, file paths, actions, labels, and error handling.
38-41
: LGTM!The
Init
method correctly initializes theFilesSelector
model.
227-247
: LGTM!The
View
method correctly handles different states to render the appropriate view.
284-299
: Add a comment for the exported functionAbsToRel
.According to Go conventions, exported functions should have a comment explaining their purpose.
+ // AbsToRel converts an absolute path to a relative path. func AbsToRel(absPath string) (string, error) {
Likely invalid or redundant comment.
utils/tui/model.go
Outdated
// applyChangesMsg represents a message indicating that changes have been applied. | ||
type applyChangesMsg struct { | ||
err error | ||
} | ||
|
||
var counter int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider moving the counter
variable inside the Model
struct.
The applyChangesMsg
type is appropriate for handling the application of changes. However, defining the counter
variable globally may lead to issues with concurrency and state management. Consider moving it inside the Model
struct.
- var counter int
+ // Counter for tracking file processing
+ Counter int
Committable suggestion was skipped due to low confidence.
utils/tui/model.go
Outdated
m.State = "LabelInput" | ||
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[0])) | ||
counter = 0 | ||
} else { | ||
counter++ | ||
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[counter]), m.SpeedSelector.Selected) | ||
|
||
} | ||
} | ||
return m, cmd | ||
case "Fast mode": | ||
newActionSelector, cmd := m.ActionSelector.Update(msg) | ||
m.ActionSelector = newActionSelector.(modelutils.ModeSelector) | ||
if m.ActionSelector.Back { | ||
if len(m.Files) == 1 { | ||
m.State = "FileSelection" | ||
m.FilesSelector.Done = false | ||
} else { | ||
m.SpeedSelector.Done = false | ||
m.SpeedSelector.Selected = "" | ||
m.State = "ModeSelection" | ||
} | ||
} | ||
if m.ActionSelector.Done { | ||
for i := 0; i < len(m.Files); i++ { | ||
m.Actions = append(m.Actions, m.ActionSelector.Selected) | ||
} | ||
m.State = "LabelInput" | ||
m.LabelInput = modelutils.NewLabelInput("") | ||
} | ||
return m, cmd | ||
} | ||
|
||
case "LabelInput": | ||
switch m.SpeedSelector.Selected { | ||
case "Slow mode": | ||
newLabelInput, cmd := m.LabelInput.Update(msg) | ||
m.LabelInput = newLabelInput.(modelutils.LabelInput) | ||
if m.LabelInput.Back { | ||
if len(m.Labels) == 0 { | ||
counter = len(m.Files) - 1 | ||
m.ActionSelector.Done = false | ||
m.ActionSelector.Selected = "" | ||
m.Actions = m.Actions[:len(m.Actions)-1] | ||
m.State = "ActionSelection" | ||
} else { | ||
counter-- | ||
m.LabelInput.Done = false | ||
m.Labels = m.Labels[:len(m.Labels)-1] | ||
m.LabelType = m.LabelType[:len(m.LabelType)-1] | ||
m.State = "LabelInput" | ||
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[counter])) | ||
} | ||
} | ||
if m.LabelInput.Done { | ||
if m.LabelInput.Error != nil { | ||
m.Error = m.LabelInput.Error | ||
return m, tea.Quit | ||
} | ||
m.Labels = append(m.Labels, m.LabelInput.Input) | ||
m.LabelType = append(m.LabelType, m.LabelInput.IsLabel) | ||
if len(m.Labels) == len(m.Files) { | ||
m.State = "ApplyChanges" | ||
return m, m.applyChanges() | ||
} else { | ||
counter++ | ||
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[counter])) | ||
|
||
} | ||
} | ||
return m, cmd | ||
case "Fast mode": | ||
newLabelInput, cmd := m.LabelInput.Update(msg) | ||
m.LabelInput = newLabelInput.(modelutils.LabelInput) | ||
if m.LabelInput.Back { | ||
m.ActionSelector.Done = false | ||
m.ActionSelector.Selected = "" | ||
m.Actions = nil | ||
m.State = "ActionSelection" | ||
} | ||
if m.LabelInput.Done { | ||
for i := 0; i < len(m.Files); i++ { | ||
m.Labels = append(m.Labels, m.LabelInput.Input) | ||
m.LabelType = append(m.LabelType, m.LabelInput.IsLabel) | ||
} | ||
m.State = "ApplyChanges" | ||
return m, m.applyChanges() | ||
} | ||
return m, cmd | ||
} | ||
|
||
case "ApplyChanges": | ||
return m, m.applyChanges() | ||
|
||
case "Final": | ||
return m, nil | ||
} | ||
|
||
return m, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Address inefficiencies and unnecessary assignments in the Update
method.
There are some inefficiencies and unnecessary assignments in the Update
function. Additionally, according to Go conventions, exported methods should have a comment explaining their purpose.
+ // Update updates the model based on messages.
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if m.Error != nil {
// If an error occurred, display the error and quit
return m, tea.Quit
}
switch msg := msg.(type) {
case applyChangesMsg:
if msg.err != nil {
m.Error = msg.err
}
m.State = "Final"
return m, nil
case tea.KeyMsg:
if m.State == "Final" {
return m, tea.Quit
}
}
switch m.State {
case "FileSelection":
newFilesSelector, cmd := m.FilesSelector.Update(msg)
m.FilesSelector = newFilesSelector.(modelutils.FilesSelector)
if m.FilesSelector.Done {
if m.FilesSelector.Error != nil {
m.Error = m.FilesSelector.Error
return m, tea.Quit
}
m.Files = m.FilesSelector.FilesPath
if len(m.Files) == 1 {
m.SpeedSelector = modelutils.ModeSelector{
File: m.Files[0],
Choices: []string{"Fast mode", "Slow mode"},
Selected: "Fast mode",
Speed: "",
}
m.State = "ActionSelection"
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[0]), m.SpeedSelector.Selected)
} else {
m.State = "ModeSelection"
m.SpeedSelector = modelutils.NewModeSelector([]string{"Fast mode", "Slow mode"}, "", "")
}
}
return m, cmd
case "ModeSelection":
newSpeedSelector, cmd := m.SpeedSelector.Update(msg)
m.SpeedSelector = newSpeedSelector.(modelutils.ModeSelector)
if m.SpeedSelector.Back {
m.State = "FileSelection"
m.FilesSelector.Done = false
}
if m.SpeedSelector.Done {
m.State = "ActionSelection"
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[0]), m.SpeedSelector.Selected)
}
return m, cmd
case "ActionSelection":
switch m.SpeedSelector.Selected {
case "Slow mode":
newActionSelector, cmd := m.ActionSelector.Update(msg)
m.ActionSelector = newActionSelector.(modelutils.ModeSelector)
if m.ActionSelector.Back {
if len(m.Actions) == 0 {
m.SpeedSelector.Done = false
m.SpeedSelector.Selected = ""
m.State = "ModeSelection"
} else {
m.Counter--
m.ActionSelector.Done = false
m.Actions = m.Actions[:len(m.Actions)-1]
m.State = "ActionSelection"
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[m.Counter]), m.SpeedSelector.Selected)
}
}
if m.ActionSelector.Done {
m.Actions = append(m.Actions, m.ActionSelector.Selected)
if len(m.Actions) == len(m.Files) {
m.State = "LabelInput"
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[0]))
m.Counter = 0
} else {
m.Counter++
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[m.Counter]), m.SpeedSelector.Selected)
}
}
return m, cmd
case "Fast mode":
newActionSelector, cmd := m.ActionSelector.Update(msg)
m.ActionSelector = newActionSelector.(modelutils.ModeSelector)
if m.ActionSelector.Back {
if len(m.Files) == 1 {
m.State = "FileSelection"
m.FilesSelector.Done = false
} else {
m.SpeedSelector.Done = false
m.SpeedSelector.Selected = ""
m.State = "ModeSelection"
}
}
if m.ActionSelector.Done {
for i := 0; i < len(m.Files); i++ {
m.Actions = append(m.Actions, m.ActionSelector.Selected)
}
m.State = "LabelInput"
m.LabelInput = modelutils.NewLabelInput("")
}
return m, cmd
}
case "LabelInput":
switch m.SpeedSelector.Selected {
case "Slow mode":
newLabelInput, cmd := m.LabelInput.Update(msg)
m.LabelInput = newLabelInput.(modelutils.LabelInput)
if m.LabelInput.Back {
if len(m.Labels) == 0 {
m.Counter = len(m.Files) - 1
m.ActionSelector.Done = false
m.ActionSelector.Selected = ""
m.Actions = m.Actions[:len(m.Actions)-1]
m.State = "ActionSelection"
} else {
m.Counter--
m.LabelInput.Done = false
m.Labels = m.Labels[:len(m.Labels)-1]
m.LabelType = m.LabelType[:len(m.LabelType)-1]
m.State = "LabelInput"
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[m.Counter]))
}
}
if m.LabelInput.Done {
if m.LabelInput.Error != nil {
m.Error = m.LabelInput.Error
return m, tea.Quit
}
m.Labels = append(m.Labels, m.LabelInput.Input)
m.LabelType = append(m.LabelType, m.LabelInput.IsLabel)
if len(m.Labels) == len(m.Files) {
m.State = "ApplyChanges"
return m, m.applyChanges()
} else {
m.Counter++
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[m.Counter]))
}
}
return m, cmd
case "Fast mode":
newLabelInput, cmd := m.LabelInput.Update(msg)
m.LabelInput = newLabelInput.(modelutils.LabelInput)
if m.LabelInput.Back {
m.ActionSelector.Done = false
m.ActionSelector.Selected = ""
m.Actions = nil
m.State = "ActionSelection"
}
if m.LabelInput.Done {
for i := 0; i < len(m.Files); i++ {
m.Labels = append(m.Labels, m.LabelInput.Input)
m.LabelType = append(m.LabelType, m.LabelInput.IsLabel)
}
m.State = "ApplyChanges"
return m, m.applyChanges()
}
return m, cmd
}
case "ApplyChanges":
return m, m.applyChanges()
case "Final":
return m, nil
}
return m, nil
}
Committable suggestion was skipped due to low confidence.
Tools
golangci-lint
[warning] 190-190: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block
(revive)
83-83: unnecessary leading newline
(whitespace)
121-121: unnecessary trailing newline
(whitespace)
133-133: unnecessary trailing newline
(whitespace)
194-194: unnecessary trailing newline
(whitespace)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- utils/tui/model_test.go (1 hunks)
Additional comments not posted (27)
utils/tui/model_test.go (27)
14-19
: Good test coverage for initialization.The test ensures that the
Init
method of theModel
struct works correctly.
30-49
: Good transition test from FileSelection to ModeSelection.The test verifies that the
Model
transitions correctly fromFileSelection
toModeSelection
state.
50-67
: Good transition test from FileSelection to ActionSelection.The test verifies that the
Model
transitions correctly fromFileSelection
toActionSelection
state.
68-80
: Good test for handling no file selection.The test ensures that the
Model
remains inFileSelection
state when no file is selected.
81-94
: Good transition test from ModeSelection to ActionSelection.The test verifies that the
Model
transitions correctly fromModeSelection
toActionSelection
state.
95-108
: Good test for handling ActionSelection state.The test ensures that the
Model
remains inActionSelection
state when the action is selected again.
109-122
: Good transition test from ActionSelection to LabelInput (fast mode).The test verifies that the
Model
transitions correctly fromActionSelection
toLabelInput
state in fast mode.
123-138
: Good transition test from ActionSelection to LabelInput (slow mode).The test verifies that the
Model
transitions correctly fromActionSelection
toLabelInput
state in slow mode.
139-154
: Good test for handling LabelInput state.The test ensures that the
Model
remains inLabelInput
state when the label input is updated.
155-172
: Good transition test from ModeSelection to FileSelection.The test verifies that the
Model
transitions correctly fromModeSelection
toFileSelection
state.
173-189
: Good transition test from ActionSelection to FileSelection.The test verifies that the
Model
transitions correctly fromActionSelection
toFileSelection
state.
190-205
: Good transition test from ActionSelection to ModeSelection (fast mode).The test verifies that the
Model
transitions correctly fromActionSelection
toModeSelection
state in fast mode.
206-220
: Good transition test from ActionSelection to ModeSelection (slow mode).The test verifies that the
Model
transitions correctly fromActionSelection
toModeSelection
state in slow mode.
221-236
: Good test for handling ActionSelection state.The test ensures that the
Model
remains inActionSelection
state when the action is selected again.
239-252
: Good transition test from LabelInput to ActionSelection (fast mode).The test verifies that the
Model
transitions correctly fromLabelInput
toActionSelection
state in fast mode.
253-270
: Good transition test from LabelInput to ActionSelection (slow mode).The test verifies that the
Model
transitions correctly fromLabelInput
toActionSelection
state in slow mode.
271-286
: Good test for handling LabelInput state.The test ensures that the
Model
remains inLabelInput
state when the label input is updated.
352-361
: Good test for successful changes.The test verifies that the
applyChanges
method works correctly when changes are applied successfully.
362-370
: Good test for handling multiple files.The test ensures that the
applyChanges
method works correctly when changes are applied to multiple files.
371-380
: Good test for error handling.The test verifies that the
applyChanges
method handles errors correctly when applying changes.
424-429
: Good test for FileSelection view.The test verifies that the
View
method renders the correct view for theFileSelection
state.
430-434
: Good test for ModeSelection view.The test ensures that the
View
method renders the correct view for theModeSelection
state.
435-444
: Good test for ActionSelection view.The test verifies that the
View
method renders the correct view for theActionSelection
state.
445-447
: Good test for LabelInput view.The test ensures that the
View
method renders the correct view for theLabelInput
state.
448-450
: Good test for Final view with error.The test verifies that the
View
method renders the correct view for theFinal
state when an error occurs.
451-455
: Good test for Final view without error.The test ensures that the
View
method renders the correct view for theFinal
state when no error occurs.
468-483
: Good utility function for creating temporary files.The function handles file creation, writing, and cleanup correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (3)
- utils/commenter/commenter.go (1 hunks)
- utils/server/server.go (1 hunks)
- utils/tui/model.go (1 hunks)
Additional context used
golangci-lint
utils/server/server.go
[warning] 34-34: exported: exported function StartServer should have comment or be unexported
(revive)
utils/tui/model.go
[warning] 183-183: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block
(revive)
81-81: unnecessary leading newline
(whitespace)
118-118: unnecessary trailing newline
(whitespace)
128-128: unnecessary trailing newline
(whitespace)
186-186: unnecessary trailing newline
(whitespace)
Additional comments not posted (4)
utils/commenter/commenter.go (1)
8-15
: LGTM!The function implementation looks correct and efficient.
utils/tui/model.go (3)
36-39
: LGTM!The function implementation looks correct and efficient.
219-239
: LGTM!The function implementation looks correct and efficient.
102-131
: Address inefficiencies and unnecessary assignments in theUpdate
method.There are some inefficiencies and unnecessary assignments in the
Update
function.- counter := 1 - newActionSelector, cmd := m.ActionSelector.Update(msg) - m.ActionSelector = newActionSelector.(modelutils.ModeSelector) - if m.ActionSelector.Done { - m.Actions = append(m.Actions, m.ActionSelector.Selected) - if len(m.Actions) == len(m.Files) { - m.State = "LabelInput" - m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[0])) - } else { - m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[counter]), m.SpeedSelector.Selected) - counter++ - } - } + newActionSelector, cmd := m.ActionSelector.Update(msg) + m.ActionSelector = newActionSelector.(modelutils.ModeSelector) + if m.ActionSelector.Done { + m.Actions = append(m.Actions, m.ActionSelector.Selected) + if len(m.Actions) == len(m.Files) { + m.State = "LabelInput" + m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[0])) + } else { + m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[len(m.Actions)]), m.SpeedSelector.Selected) + } + }Likely invalid or redundant comment.
Tools
golangci-lint
118-118: unnecessary trailing newline
(whitespace)
128-128: unnecessary trailing newline
(whitespace)
utils/commenter/commenter.go
Outdated
// ToggleComments toggles comments on or off for the given line based on its current state. | ||
func ToggleComments(line string, char string) string { | ||
trimmedLine := strings.TrimSpace(line) | ||
|
||
//just for html | ||
if char == "<!-- -->" && strings.HasPrefix(trimmedLine, "<!--") && strings.HasSuffix(trimmedLine, "-->") { | ||
return Uncomment(line, char) | ||
} else if char == "<!-- -->" { | ||
return Comment(line, char) | ||
} | ||
|
||
if strings.HasPrefix(trimmedLine, char) { | ||
return Uncomment(line, char) | ||
} | ||
return Comment(line, char) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplify the handling of HTML comments.
The special handling for HTML comments can be improved for readability.
- if char == "<!-- -->" && strings.HasPrefix(trimmedLine, "<!--") && strings.HasSuffix(trimmedLine, "-->") {
- return Uncomment(line, char)
- } else if char == "<!-- -->" {
- return Comment(line, char)
- }
+ if char == "<!-- -->" {
+ if strings.HasPrefix(trimmedLine, "<!--") && strings.HasSuffix(trimmedLine, "-->") {
+ return Uncomment(line, char)
+ }
+ return Comment(line, char)
+ }
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// ToggleComments toggles comments on or off for the given line based on its current state. | |
func ToggleComments(line string, char string) string { | |
trimmedLine := strings.TrimSpace(line) | |
//just for html | |
if char == "<!-- -->" && strings.HasPrefix(trimmedLine, "<!--") && strings.HasSuffix(trimmedLine, "-->") { | |
return Uncomment(line, char) | |
} else if char == "<!-- -->" { | |
return Comment(line, char) | |
} | |
if strings.HasPrefix(trimmedLine, char) { | |
return Uncomment(line, char) | |
} | |
return Comment(line, char) | |
} | |
// ToggleComments toggles comments on or off for the given line based on its current state. | |
func ToggleComments(line string, char string) string { | |
trimmedLine := strings.TrimSpace(line) | |
//just for html | |
if char == "<!-- -->" { | |
if strings.HasPrefix(trimmedLine, "<!--") && strings.HasSuffix(trimmedLine, "-->") { | |
return Uncomment(line, char) | |
} | |
return Comment(line, char) | |
} | |
if strings.HasPrefix(trimmedLine, char) { | |
return Uncomment(line, char) | |
} | |
return Comment(line, char) | |
} |
utils/commenter/commenter.go
Outdated
// Uncomment removes a comment character or string from the beginning of the given line, if present. | ||
func Uncomment(line string, char string) string { | ||
trimmedLine := strings.TrimSpace(line) | ||
|
||
//just for html | ||
if char == "<!-- -->" && strings.HasPrefix(trimmedLine, "<!--") && strings.HasSuffix(trimmedLine, "-->") { | ||
line = strings.Replace(line, "<!-- ", "", 1) | ||
line = strings.Replace(line, "<!--", "", 1) | ||
line = strings.Replace(line, " "+"-->", "", 1) | ||
line = strings.Replace(line, "-->", "", 1) | ||
|
||
return line | ||
} | ||
|
||
if strings.HasPrefix(trimmedLine, char) { | ||
// Check for both `//` and `// ` prefixes. | ||
if strings.HasPrefix(trimmedLine, char+" ") { | ||
return strings.Replace(line, char+" ", "", 1) | ||
} | ||
return strings.Replace(line, char, "", 1) | ||
} | ||
return line | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplify the handling of HTML comments.
The detailed handling for HTML comments can be simplified for better readability and maintainability.
- if char == "<!-- -->" && strings.HasPrefix(trimmedLine, "<!--") && strings.HasSuffix(trimmedLine, "-->") {
- line = strings.Replace(line, "<!-- ", "", 1)
- line = strings.Replace(line, "<!--", "", 1)
- line = strings.Replace(line, " "+"-->", "", 1)
- line = strings.Replace(line, "-->", "", 1)
- return line
- }
+ if char == "<!-- -->" && strings.HasPrefix(trimmedLine, "<!--") && strings.HasSuffix(trimmedLine, "-->") {
+ line = strings.TrimPrefix(line, "<!-- ")
+ line = strings.TrimSuffix(line, " -->")
+ return line
+ }
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// Uncomment removes a comment character or string from the beginning of the given line, if present. | |
func Uncomment(line string, char string) string { | |
trimmedLine := strings.TrimSpace(line) | |
//just for html | |
if char == "<!-- -->" && strings.HasPrefix(trimmedLine, "<!--") && strings.HasSuffix(trimmedLine, "-->") { | |
line = strings.Replace(line, "<!-- ", "", 1) | |
line = strings.Replace(line, "<!--", "", 1) | |
line = strings.Replace(line, " "+"-->", "", 1) | |
line = strings.Replace(line, "-->", "", 1) | |
return line | |
} | |
if strings.HasPrefix(trimmedLine, char) { | |
// Check for both `//` and `// ` prefixes. | |
if strings.HasPrefix(trimmedLine, char+" ") { | |
return strings.Replace(line, char+" ", "", 1) | |
} | |
return strings.Replace(line, char, "", 1) | |
} | |
return line | |
} | |
// Uncomment removes a comment character or string from the beginning of the given line, if present. | |
func Uncomment(line string, char string) string { | |
trimmedLine := strings.TrimSpace(line) | |
//just for html | |
if char == "<!-- -->" && strings.HasPrefix(trimmedLine, "<!--") && strings.HasSuffix(trimmedLine, "-->") { | |
line = strings.TrimPrefix(line, "<!-- ") | |
line = strings.TrimSuffix(line, " -->") | |
return line | |
} | |
if strings.HasPrefix(trimmedLine, char) { | |
// Check for both `//` and `// ` prefixes. | |
if strings.HasPrefix(trimmedLine, char+" ") { | |
return strings.Replace(line, char+" ", "", 1) | |
} | |
return strings.Replace(line, char, "", 1) | |
} | |
return line | |
} |
func(next ssh.Handler) ssh.Handler { | ||
return func(s ssh.Session) { | ||
command := s.Command() | ||
if len(command) < 2 { | ||
wish.Println(s, "Usage tgcom <directory>") | ||
next(s) | ||
return | ||
} | ||
dir = command[1] | ||
next(s) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve readability of command handling logic.
The command handling logic can be improved for better readability and maintainability.
- func(next ssh.Handler) ssh.Handler {
- return func(s ssh.Session) {
- command := s.Command()
- if len(command) < 2 {
- wish.Println(s, "Usage tgcom <directory>")
- next(s)
- return
- }
- dir = command[1]
- next(s)
- }
- },
+ func(next ssh.Handler) ssh.Handler {
+ return func(s ssh.Session) {
+ command := s.Command()
+ if len(command) < 2 {
+ wish.Println(s, "Usage tgcom <directory>")
+ next(s)
+ return
+ }
+ dir = command[1]
+ next(s)
+ }
+ },
Committable suggestion was skipped due to low confidence.
func StartServer() { | ||
withHostKey := wish.WithHostKeyPath(pathHostKey) | ||
if pem, ok := os.LookupEnv(envHostKey); ok { | ||
withHostKey = wish.WithHostKeyPEM([]byte(pem)) | ||
} | ||
srv, err := wish.NewServer( | ||
wish.WithAddress(":2222"), | ||
wish.WithMiddleware( | ||
bm.Middleware(func(s ssh.Session) (tea.Model, []tea.ProgramOption) { | ||
pty, _, _ := s.Pty() | ||
// Initialize the file selector model with the directory argument | ||
model := tui.Model{ | ||
State: "FileSelection", | ||
FilesSelector: modelutils.InitialModel(dir, pty.Window.Height-5), // Initialize the FilesSelector model with window height | ||
} | ||
if model.Error != nil { | ||
wish.Println(s, model.Error.Error()) | ||
return nil, nil | ||
} | ||
return model, teaOptions | ||
}), | ||
func(next ssh.Handler) ssh.Handler { | ||
return func(s ssh.Session) { | ||
command := s.Command() | ||
if len(command) < 2 { | ||
wish.Println(s, "Usage tgcom <directory>") | ||
next(s) | ||
return | ||
} | ||
dir = command[1] | ||
next(s) | ||
} | ||
}, | ||
activeterm.Middleware(), | ||
lm.Middleware(), | ||
), | ||
|
||
withHostKey, | ||
) | ||
if err != nil { | ||
log.Fatalf("could not create server: %s", err) | ||
} | ||
done := make(chan os.Signal, 1) | ||
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) | ||
|
||
log.Printf("starting server: %s", srv.Addr) | ||
go func() { | ||
if err := srv.ListenAndServe(); err != nil { | ||
log.Fatalf("server returned an error: %s", err) | ||
} | ||
}() | ||
|
||
<-done | ||
log.Println("stopping server...") | ||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | ||
defer cancel() | ||
if err := srv.Shutdown(ctx); err != nil { | ||
log.Fatalf("could not shutdown server gracefully: %s", err) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function StartServer
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // StartServer initializes and starts an SSH server with directory browsing capabilities and command handling.
func StartServer() {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func StartServer() { | |
withHostKey := wish.WithHostKeyPath(pathHostKey) | |
if pem, ok := os.LookupEnv(envHostKey); ok { | |
withHostKey = wish.WithHostKeyPEM([]byte(pem)) | |
} | |
srv, err := wish.NewServer( | |
wish.WithAddress(":2222"), | |
wish.WithMiddleware( | |
bm.Middleware(func(s ssh.Session) (tea.Model, []tea.ProgramOption) { | |
pty, _, _ := s.Pty() | |
// Initialize the file selector model with the directory argument | |
model := tui.Model{ | |
State: "FileSelection", | |
FilesSelector: modelutils.InitialModel(dir, pty.Window.Height-5), // Initialize the FilesSelector model with window height | |
} | |
if model.Error != nil { | |
wish.Println(s, model.Error.Error()) | |
return nil, nil | |
} | |
return model, teaOptions | |
}), | |
func(next ssh.Handler) ssh.Handler { | |
return func(s ssh.Session) { | |
command := s.Command() | |
if len(command) < 2 { | |
wish.Println(s, "Usage tgcom <directory>") | |
next(s) | |
return | |
} | |
dir = command[1] | |
next(s) | |
} | |
}, | |
activeterm.Middleware(), | |
lm.Middleware(), | |
), | |
withHostKey, | |
) | |
if err != nil { | |
log.Fatalf("could not create server: %s", err) | |
} | |
done := make(chan os.Signal, 1) | |
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) | |
log.Printf("starting server: %s", srv.Addr) | |
go func() { | |
if err := srv.ListenAndServe(); err != nil { | |
log.Fatalf("server returned an error: %s", err) | |
} | |
}() | |
<-done | |
log.Println("stopping server...") | |
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | |
defer cancel() | |
if err := srv.Shutdown(ctx); err != nil { | |
log.Fatalf("could not shutdown server gracefully: %s", err) | |
} | |
} | |
// StartServer initializes and starts an SSH server with directory browsing capabilities and command handling. | |
func StartServer() { | |
withHostKey := wish.WithHostKeyPath(pathHostKey) | |
if pem, ok := os.LookupEnv(envHostKey); ok { | |
withHostKey = wish.WithHostKeyPEM([]byte(pem)) | |
} | |
srv, err := wish.NewServer( | |
wish.WithAddress(":2222"), | |
wish.WithMiddleware( | |
bm.Middleware(func(s ssh.Session) (tea.Model, []tea.ProgramOption) { | |
pty, _, _ := s.Pty() | |
// Initialize the file selector model with the directory argument | |
model := tui.Model{ | |
State: "FileSelection", | |
FilesSelector: modelutils.InitialModel(dir, pty.Window.Height-5), // Initialize the FilesSelector model with window height | |
} | |
if model.Error != nil { | |
wish.Println(s, model.Error.Error()) | |
return nil, nil | |
} | |
return model, teaOptions | |
}), | |
func(next ssh.Handler) ssh.Handler { | |
return func(s ssh.Session) { | |
command := s.Command() | |
if len(command) < 2 { | |
wish.Println(s, "Usage tgcom <directory>") | |
next(s) | |
return | |
} | |
dir = command[1] | |
next(s) | |
} | |
}, | |
activeterm.Middleware(), | |
lm.Middleware(), | |
), | |
withHostKey, | |
) | |
if err != nil { | |
log.Fatalf("could not create server: %s", err) | |
} | |
done := make(chan os.Signal, 1) | |
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) | |
log.Printf("starting server: %s", srv.Addr) | |
go func() { | |
if err := srv.ListenAndServe(); err != nil { | |
log.Fatalf("server returned an error: %s", err) | |
} | |
}() | |
<-done | |
log.Println("stopping server...") | |
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | |
defer cancel() | |
if err := srv.Shutdown(ctx); err != nil { | |
log.Fatalf("could not shutdown server gracefully: %s", err) | |
} | |
} |
Tools
golangci-lint
[warning] 34-34: exported: exported function StartServer should have comment or be unexported
(revive)
utils/tui/model.go
Outdated
// Helper function to convert absolute path to relative path | ||
func AbsToRel(absPath string) (string, error) { | ||
// Get the current working directory | ||
currentDir, err := filepath.Abs(".") | ||
if err != nil { | ||
return "", fmt.Errorf("failed to get the current directory: %w", err) | ||
} | ||
|
||
// Convert the absolute path to a relative path | ||
relPath, err := filepath.Rel(currentDir, absPath) | ||
if err != nil { | ||
return "", fmt.Errorf("failed to convert to relative path: %w", err) | ||
} | ||
|
||
return relPath, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function AbsToRel
.
According to Go conventions, exported functions should have a comment explaining their purpose.
+ // AbsToRel converts an absolute path to a relative path.
func AbsToRel(absPath string) (string, error) {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// Helper function to convert absolute path to relative path | |
func AbsToRel(absPath string) (string, error) { | |
// Get the current working directory | |
currentDir, err := filepath.Abs(".") | |
if err != nil { | |
return "", fmt.Errorf("failed to get the current directory: %w", err) | |
} | |
// Convert the absolute path to a relative path | |
relPath, err := filepath.Rel(currentDir, absPath) | |
if err != nil { | |
return "", fmt.Errorf("failed to convert to relative path: %w", err) | |
} | |
return relPath, nil | |
} | |
// AbsToRel converts an absolute path to a relative path. | |
func AbsToRel(absPath string) (string, error) { | |
// Get the current working directory | |
currentDir, err := filepath.Abs(".") | |
if err != nil { | |
return "", fmt.Errorf("failed to get the current directory: %w", err) | |
} | |
// Convert the absolute path to a relative path | |
relPath, err := filepath.Rel(currentDir, absPath) | |
if err != nil { | |
return "", fmt.Errorf("failed to convert to relative path: %w", err) | |
} | |
return relPath, nil | |
} |
utils/tui/model.go
Outdated
// applyChanges applies changes to selected files based on user inputs | ||
func (m *Model) applyChanges() tea.Cmd { | ||
return func() tea.Msg { | ||
for i := 0; i < len(m.Files); i++ { | ||
currentFilePath, err := AbsToRel(m.Files[i]) | ||
if err != nil { | ||
return applyChangesMsg{err: fmt.Errorf("failed to convert to relative path: %w", err)} | ||
} | ||
if !m.LabelType[i] { | ||
conf := modfile.Config{ | ||
Filename: currentFilePath, | ||
LineNum: m.Labels[i], | ||
Action: m.Actions[i], | ||
} | ||
err = modfile.ChangeFile(conf) | ||
} else { | ||
parts := strings.Split(m.Labels[i], ";") | ||
conf := modfile.Config{ | ||
Filename: currentFilePath, | ||
StartLabel: parts[0], | ||
EndLabel: parts[1], | ||
Action: m.Actions[i], | ||
} | ||
err = modfile.ChangeFile(conf) | ||
} | ||
|
||
if err != nil { | ||
return applyChangesMsg{err: fmt.Errorf("failed to apply changes to file %s: %w", m.Files[i], err)} | ||
} | ||
} | ||
|
||
return applyChangesMsg{err: nil} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optimize the applyChanges
method.
The method is well-structured but can be optimized by removing unnecessary else blocks.
func (m *Model) applyChanges() tea.Cmd {
return func() tea.Msg {
for i := 0; i < len(m.Files); i++ {
currentFilePath, err := AbsToRel(m.Files[i])
if err != nil {
return applyChangesMsg{err: fmt.Errorf("failed to convert to relative path: %w", err)}
}
if !m.LabelType[i] {
conf := modfile.Config{
Filename: currentFilePath,
LineNum: m.Labels[i],
Action: m.Actions[i],
}
err = modfile.ChangeFile(conf)
} else {
parts := strings.Split(m.Labels[i], ";")
conf := modfile.Config{
Filename: currentFilePath,
StartLabel: parts[0],
EndLabel: parts[1],
Action: m.Actions[i],
}
err = modfile.ChangeFile(conf)
}
if err != nil {
return applyChangesMsg{err: fmt.Errorf("failed to apply changes to file %s: %w", m.Files[i], err)}
}
}
return applyChangesMsg{err: nil}
}
}
Committable suggestion was skipped due to low confidence.
utils/tui/model.go
Outdated
} | ||
} | ||
if m.ActionSelector.Done { | ||
m.Actions = append(m.Actions, m.ActionSelector.Selected) | ||
if len(m.Actions) == len(m.Files) { | ||
m.State = "LabelInput" | ||
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[0])) | ||
} else { | ||
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[len(m.Actions)]), m.SpeedSelector.Selected) | ||
|
||
} | ||
} | ||
return m, cmd | ||
case "Fast mode": | ||
newActionSelector, cmd := m.ActionSelector.Update(msg) | ||
m.ActionSelector = newActionSelector.(modelutils.ModeSelector) | ||
if m.ActionSelector.Back { | ||
if len(m.Files) == 1 { | ||
m.State = "FileSelection" | ||
m.FilesSelector.Done = false | ||
} else { | ||
m.SpeedSelector.Done = false | ||
m.SpeedSelector.Selected = "" | ||
m.State = "ModeSelection" | ||
} | ||
} | ||
if m.ActionSelector.Done { | ||
for i := 0; i < len(m.Files); i++ { | ||
m.Actions = append(m.Actions, m.ActionSelector.Selected) | ||
} | ||
m.State = "LabelInput" | ||
m.LabelInput = modelutils.NewLabelInput("") | ||
} | ||
return m, cmd | ||
} | ||
|
||
case "LabelInput": | ||
switch m.SpeedSelector.Selected { | ||
case "Slow mode": | ||
newLabelInput, cmd := m.LabelInput.Update(msg) | ||
m.LabelInput = newLabelInput.(modelutils.LabelInput) | ||
if m.LabelInput.Back { | ||
if len(m.Labels) == 0 { | ||
m.ActionSelector.Done = false | ||
m.ActionSelector.Selected = "" | ||
m.Actions = m.Actions[:len(m.Actions)-1] | ||
m.State = "ActionSelection" | ||
} else { | ||
m.LabelInput.Done = false | ||
m.Labels = m.Labels[:len(m.Labels)-1] | ||
m.LabelType = m.LabelType[:len(m.LabelType)-1] | ||
m.State = "LabelInput" | ||
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[len(m.Labels)])) | ||
} | ||
} | ||
if m.LabelInput.Done { | ||
if m.LabelInput.Error != nil { | ||
m.Error = m.LabelInput.Error | ||
return m, tea.Quit | ||
} | ||
m.Labels = append(m.Labels, m.LabelInput.Input) | ||
m.LabelType = append(m.LabelType, m.LabelInput.IsLabel) | ||
if len(m.Labels) == len(m.Files) { | ||
m.State = "ApplyChanges" | ||
return m, m.applyChanges() | ||
} else { | ||
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[len(m.Labels)])) | ||
|
||
} | ||
} | ||
return m, cmd | ||
case "Fast mode": | ||
newLabelInput, cmd := m.LabelInput.Update(msg) | ||
m.LabelInput = newLabelInput.(modelutils.LabelInput) | ||
if m.LabelInput.Back { | ||
m.ActionSelector.Done = false | ||
m.ActionSelector.Selected = "" | ||
m.Actions = nil | ||
m.State = "ActionSelection" | ||
} | ||
if m.LabelInput.Done { | ||
for i := 0; i < len(m.Files); i++ { | ||
m.Labels = append(m.Labels, m.LabelInput.Input) | ||
m.LabelType = append(m.LabelType, m.LabelInput.IsLabel) | ||
} | ||
m.State = "ApplyChanges" | ||
return m, m.applyChanges() | ||
} | ||
return m, cmd | ||
} | ||
|
||
case "ApplyChanges": | ||
return m, m.applyChanges() | ||
|
||
case "Final": | ||
return m, nil | ||
} | ||
|
||
return m, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment for the exported function Update
.
According to Go conventions, exported methods should have a comment explaining their purpose.
+ // Update updates the model based on messages.
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// Update updates the model based on messages | |
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | |
if m.Error != nil { | |
// If an error occurred, display the error and quit | |
return m, tea.Quit | |
} | |
switch msg := msg.(type) { | |
case applyChangesMsg: | |
if msg.err != nil { | |
m.Error = msg.err | |
} | |
m.State = "Final" | |
return m, nil | |
case tea.KeyMsg: | |
if m.State == "Final" { | |
return m, tea.Quit | |
} | |
} | |
switch m.State { | |
case "FileSelection": | |
newFilesSelector, cmd := m.FilesSelector.Update(msg) | |
m.FilesSelector = newFilesSelector.(modelutils.FilesSelector) | |
if m.FilesSelector.Done { | |
if m.FilesSelector.Error != nil { | |
m.Error = m.FilesSelector.Error | |
return m, tea.Quit | |
} | |
m.Files = m.FilesSelector.FilesPath | |
if len(m.Files) == 1 { | |
m.SpeedSelector = modelutils.ModeSelector{ | |
File: m.Files[0], | |
Choices: []string{"Fast mode", "Slow mode"}, | |
Selected: "Fast mode", | |
Speed: "", | |
} | |
m.State = "ActionSelection" | |
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[0]), m.SpeedSelector.Selected) | |
} else { | |
m.State = "ModeSelection" | |
m.SpeedSelector = modelutils.NewModeSelector([]string{"Fast mode", "Slow mode"}, "", "") | |
} | |
} | |
return m, cmd | |
case "ModeSelection": | |
newSpeedSelector, cmd := m.SpeedSelector.Update(msg) | |
m.SpeedSelector = newSpeedSelector.(modelutils.ModeSelector) | |
if m.SpeedSelector.Back { | |
m.State = "FileSelection" | |
m.FilesSelector.Done = false | |
} | |
if m.SpeedSelector.Done { | |
m.State = "ActionSelection" | |
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[0]), m.SpeedSelector.Selected) | |
} | |
return m, cmd | |
case "ActionSelection": | |
switch m.SpeedSelector.Selected { | |
case "Slow mode": | |
newActionSelector, cmd := m.ActionSelector.Update(msg) | |
m.ActionSelector = newActionSelector.(modelutils.ModeSelector) | |
if m.ActionSelector.Back { | |
if len(m.Actions) == 0 { | |
m.SpeedSelector.Done = false | |
m.SpeedSelector.Selected = "" | |
m.State = "ModeSelection" | |
} else { | |
m.ActionSelector.Done = false | |
m.Actions = m.Actions[:len(m.Actions)-1] | |
m.State = "ActionSelection" | |
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[len(m.Actions)]), m.SpeedSelector.Selected) | |
} | |
} | |
if m.ActionSelector.Done { | |
m.Actions = append(m.Actions, m.ActionSelector.Selected) | |
if len(m.Actions) == len(m.Files) { | |
m.State = "LabelInput" | |
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[0])) | |
} else { | |
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[len(m.Actions)]), m.SpeedSelector.Selected) | |
} | |
} | |
return m, cmd | |
case "Fast mode": | |
newActionSelector, cmd := m.ActionSelector.Update(msg) | |
m.ActionSelector = newActionSelector.(modelutils.ModeSelector) | |
if m.ActionSelector.Back { | |
if len(m.Files) == 1 { | |
m.State = "FileSelection" | |
m.FilesSelector.Done = false | |
} else { | |
m.SpeedSelector.Done = false | |
m.SpeedSelector.Selected = "" | |
m.State = "ModeSelection" | |
} | |
} | |
if m.ActionSelector.Done { | |
for i := 0; i < len(m.Files); i++ { | |
m.Actions = append(m.Actions, m.ActionSelector.Selected) | |
} | |
m.State = "LabelInput" | |
m.LabelInput = modelutils.NewLabelInput("") | |
} | |
return m, cmd | |
} | |
case "LabelInput": | |
switch m.SpeedSelector.Selected { | |
case "Slow mode": | |
newLabelInput, cmd := m.LabelInput.Update(msg) | |
m.LabelInput = newLabelInput.(modelutils.LabelInput) | |
if m.LabelInput.Back { | |
if len(m.Labels) == 0 { | |
m.ActionSelector.Done = false | |
m.ActionSelector.Selected = "" | |
m.Actions = m.Actions[:len(m.Actions)-1] | |
m.State = "ActionSelection" | |
} else { | |
m.LabelInput.Done = false | |
m.Labels = m.Labels[:len(m.Labels)-1] | |
m.LabelType = m.LabelType[:len(m.LabelType)-1] | |
m.State = "LabelInput" | |
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[len(m.Labels)])) | |
} | |
} | |
if m.LabelInput.Done { | |
if m.LabelInput.Error != nil { | |
m.Error = m.LabelInput.Error | |
return m, tea.Quit | |
} | |
m.Labels = append(m.Labels, m.LabelInput.Input) | |
m.LabelType = append(m.LabelType, m.LabelInput.IsLabel) | |
if len(m.Labels) == len(m.Files) { | |
m.State = "ApplyChanges" | |
return m, m.applyChanges() | |
} else { | |
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[len(m.Labels)])) | |
} | |
} | |
return m, cmd | |
case "Fast mode": | |
newLabelInput, cmd := m.LabelInput.Update(msg) | |
m.LabelInput = newLabelInput.(modelutils.LabelInput) | |
if m.LabelInput.Back { | |
m.ActionSelector.Done = false | |
m.ActionSelector.Selected = "" | |
m.Actions = nil | |
m.State = "ActionSelection" | |
} | |
if m.LabelInput.Done { | |
for i := 0; i < len(m.Files); i++ { | |
m.Labels = append(m.Labels, m.LabelInput.Input) | |
m.LabelType = append(m.LabelType, m.LabelInput.IsLabel) | |
} | |
m.State = "ApplyChanges" | |
return m, m.applyChanges() | |
} | |
return m, cmd | |
} | |
case "ApplyChanges": | |
return m, m.applyChanges() | |
case "Final": | |
return m, nil | |
} | |
return m, nil | |
} | |
// Update updates the model based on messages. | |
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { | |
if m.Error != nil { | |
// If an error occurred, display the error and quit | |
return m, tea.Quit | |
} | |
switch msg := msg.(type) { | |
case applyChangesMsg: | |
if msg.err != nil { | |
m.Error = msg.err | |
} | |
m.State = "Final" | |
return m, nil | |
case tea.KeyMsg: | |
if m.State == "Final" { | |
return m, tea.Quit | |
} | |
} | |
switch m.State { | |
case "FileSelection": | |
newFilesSelector, cmd := m.FilesSelector.Update(msg) | |
m.FilesSelector = newFilesSelector.(modelutils.FilesSelector) | |
if m.FilesSelector.Done { | |
if m.FilesSelector.Error != nil { | |
m.Error = m.FilesSelector.Error | |
return m, tea.Quit | |
} | |
m.Files = m.FilesSelector.FilesPath | |
if len(m.Files) == 1 { | |
m.SpeedSelector = modelutils.ModeSelector{ | |
File: m.Files[0], | |
Choices: []string{"Fast mode", "Slow mode"}, | |
Selected: "Fast mode", | |
Speed: "", | |
} | |
m.State = "ActionSelection" | |
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[0]), m.SpeedSelector.Selected) | |
} else { | |
m.State = "ModeSelection" | |
m.SpeedSelector = modelutils.NewModeSelector([]string{"Fast mode", "Slow mode"}, "", "") | |
} | |
} | |
return m, cmd | |
case "ModeSelection": | |
newSpeedSelector, cmd := m.SpeedSelector.Update(msg) | |
m.SpeedSelector = newSpeedSelector.(modelutils.ModeSelector) | |
if m.SpeedSelector.Back { | |
m.State = "FileSelection" | |
m.FilesSelector.Done = false | |
} | |
if m.SpeedSelector.Done { | |
m.State = "ActionSelection" | |
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[0]), m.SpeedSelector.Selected) | |
} | |
return m, cmd | |
case "ActionSelection": | |
switch m.SpeedSelector.Selected { | |
case "Slow mode": | |
newActionSelector, cmd := m.ActionSelector.Update(msg) | |
m.ActionSelector = newActionSelector.(modelutils.ModeSelector) | |
if m.ActionSelector.Back { | |
if len(m.Actions) == 0 { | |
m.SpeedSelector.Done = false | |
m.SpeedSelector.Selected = "" | |
m.State = "ModeSelection" | |
} else { | |
m.ActionSelector.Done = false | |
m.Actions = m.Actions[:len(m.Actions)-1] | |
m.State = "ActionSelection" | |
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[len(m.Actions)]), m.SpeedSelector.Selected) | |
} | |
} | |
if m.ActionSelector.Done { | |
m.Actions = append(m.Actions, m.ActionSelector.Selected) | |
if len(m.Actions) == len(m.Files) { | |
m.State = "LabelInput" | |
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[0])) | |
} else { | |
m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[len(m.Actions)]), m.SpeedSelector.Selected) | |
} | |
} | |
return m, cmd | |
case "Fast mode": | |
newActionSelector, cmd := m.ActionSelector.Update(msg) | |
m.ActionSelector = newActionSelector.(modelutils.ModeSelector) | |
if m.ActionSelector.Back { | |
if len(m.Files) == 1 { | |
m.State = "FileSelection" | |
m.FilesSelector.Done = false | |
} else { | |
m.SpeedSelector.Done = false | |
m.SpeedSelector.Selected = "" | |
m.State = "ModeSelection" | |
} | |
} | |
if m.ActionSelector.Done { | |
for i := 0; i < len(m.Files); i++ { | |
m.Actions = append(m.Actions, m.ActionSelector.Selected) | |
} | |
m.State = "LabelInput" | |
m.LabelInput = modelutils.NewLabelInput("") | |
} | |
return m, cmd | |
} | |
case "LabelInput": | |
switch m.SpeedSelector.Selected { | |
case "Slow mode": | |
newLabelInput, cmd := m.LabelInput.Update(msg) | |
m.LabelInput = newLabelInput.(modelutils.LabelInput) | |
if m.LabelInput.Back { | |
if len(m.Labels) == 0 { | |
m.ActionSelector.Done = false | |
m.ActionSelector.Selected = "" | |
m.Actions = m.Actions[:len(m.Actions)-1] | |
m.State = "ActionSelection" | |
} else { | |
m.LabelInput.Done = false | |
m.Labels = m.Labels[:len(m.Labels)-1] | |
m.LabelType = m.LabelType[:len(m.LabelType)-1] | |
m.State = "LabelInput" | |
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[len(m.Labels)])) | |
} | |
} | |
if m.LabelInput.Done { | |
if m.LabelInput.Error != nil { | |
m.Error = m.LabelInput.Error | |
return m, tea.Quit | |
} | |
m.Labels = append(m.Labels, m.LabelInput.Input) | |
m.LabelType = append(m.LabelType, m.LabelInput.IsLabel) | |
if len(m.Labels) == len(m.Files) { | |
m.State = "ApplyChanges" | |
return m, m.applyChanges() | |
} else { | |
m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[len(m.Labels)])) | |
} | |
} | |
return m, cmd | |
case "Fast mode": | |
newLabelInput, cmd := m.LabelInput.Update(msg) | |
m.LabelInput = newLabelInput.(modelutils.LabelInput) | |
if m.LabelInput.Back { | |
m.ActionSelector.Done = false | |
m.ActionSelector.Selected = "" | |
m.Actions = nil | |
m.State = "ActionSelection" | |
} | |
if m.LabelInput.Done { | |
for i := 0; i < len(m.Files); i++ { | |
m.Labels = append(m.Labels, m.LabelInput.Input) | |
m.LabelType = append(m.LabelType, m.LabelInput.IsLabel) | |
} | |
m.State = "ApplyChanges" | |
return m, m.applyChanges() | |
} | |
return m, cmd | |
} | |
case "ApplyChanges": | |
return m, m.applyChanges() | |
case "Final": | |
return m, nil | |
} | |
return m, nil | |
} |
Tools
golangci-lint
[warning] 183-183: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block
(revive)
81-81: unnecessary leading newline
(whitespace)
118-118: unnecessary trailing newline
(whitespace)
128-128: unnecessary trailing newline
(whitespace)
186-186: unnecessary trailing newline
(whitespace)
Summary by CodeRabbit
New Features
tgcom
, a command-line tool for commenting and uncommenting code in various languages.tgcom
.Enhancements
Bug Fixes
Tests