Skip to content

Conversation

@SauravBhowmick
Copy link
Member

@SauravBhowmick SauravBhowmick commented Nov 10, 2025

Added search history in general and custom way.

Summary by CodeRabbit

  • New Features
    • History search: list previously executed commands with case-insensitive, multi-word searching, numbered results, and simple inline highlighting; shows friendly messages when no matches or history is empty.
    • Interactive search (isearch): iterative prompt to filter recent commands, shows up to 10 matches with indication of more, supports numeric selection to copy/show a command, quitting, and basic input validation.

@github-actions
Copy link
Contributor

🚀 Hi @SauravBhowmick!

Thank you for contributing to MyCMD. A maintainer will review your PR shortly. 🎉

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

Walkthrough

Added two new commands—SearchHistoryCommand (non-interactive history view/search with bracket highlighting) and InteractiveSearchCommand (interactive reverse-chronological search and selection)—and injected a shared Scanner into ShellContext from App.

Changes

Cohort / File(s) Summary
Command Registration & Scanner wiring
src/main/java/com/mycmd/App.java
Added SEARCHHISTORY and ISEARCH identifiers, registered SearchHistoryCommand and InteractiveSearchCommand, and called context.setScanner(sc) to inject the shared Scanner into ShellContext.
Interactive Search Command
src/main/java/com/mycmd/commands/InteractiveSearchCommand.java
New class implementing an interactive prompt: reads history via ShellContext, reuses shared Scanner, performs case-insensitive reverse-chronological search, displays up to 10 matches, indicates if more exist, supports numeric selection to show/copy a command, and accepts q/quit to exit.
Search History Command
src/main/java/com/mycmd/commands/SearchHistoryCommand.java
New non-interactive command: prints full history or filters by a joined search term (case-insensitive), shows numbered lines, highlights matched terms by surrounding them with square brackets, and exposes description/usage methods.
ShellContext Scanner API
src/main/java/com/mycmd/ShellContext.java
Added setScanner(Scanner) and getScanner(); setScanner enforces single initialization and non-null input; getScanner() throws if scanner not initialized, centralizing access to the shared Scanner.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant App
    participant Context as ShellContext
    participant ISearch as InteractiveSearchCommand
    participant Search as SearchHistoryCommand
    participant Scanner as SystemScanner

    Note over App,Scanner: App startup — create Scanner and inject into context
    App->>Scanner: new Scanner(System.in)
    App->>Context: setScanner(sc)

    User->>App: invoke "isearch" or "searchhistory [term]"
    alt isearch flow
        App->>ISearch: execute(args, context)
        ISearch->>Context: getHistory()
        Context-->>ISearch: history[]
        ISearch->>Context: getScanner()
        Context-->>ISearch: Scanner
        loop interactive loop
            ISearch->>User: prompt "search term (q to quit)"
            User-->>ISearch: term
            ISearch->>ISearch: filter history (reverse-chronological, case-insensitive)
            ISearch->>User: display up to 10 matches (show count, more indicator)
            User-->>ISearch: select index / q
            alt valid selection
                ISearch->>User: show selected command
            else invalid selection
                ISearch->>User: show error message
            end
        end
    else searchhistory flow
        App->>Search: execute(args, context)
        Search->>Context: getHistory()
        Context-->>Search: history[]
        Search->>Search: if args -> filter history (case-insensitive)
        Search->>User: print full history or matched list (with bracket highlights)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Inspect interactive loop for correct quitting, input parsing, numeric selection bounds, and Scanner reuse in InteractiveSearchCommand.
  • Verify case-insensitive matching, multi-word search handling, and bracket highlighting edge cases in SearchHistoryCommand.
  • Check ShellContext.setScanner defensive behavior and correct placement of context.setScanner(sc) in App.java.

Poem

🐇
I hop through lines both new and old,
Sniff for matches, bright and bold.
A prompt, a pick, a little cheer,
I fetch the command you wanted near.
Carrots for hits — hip-hop hooray! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Added search history for commands used' directly reflects the main purpose of the pull request: adding functionality to search command history through two new commands (SearchHistoryCommand and InteractiveSearchCommand).
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d7355f5 and 8a836d5.

⛔ Files ignored due to path filters (1)
  • icons/mycmd.ico is excluded by !**/*.ico
📒 Files selected for processing (1)
  • src/main/java/com/mycmd/ShellContext.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/mycmd/ShellContext.java

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/main/java/com/mycmd/commands/InteractiveSearchCommand.java (1)

99-112: Consider simplifying the reverse operation.

The current implementation works correctly, but the nested collectors can be simplified for better readability.

Apply this diff for a more concise approach:

     private List<String> searchHistory(List<String> history, String searchTerm) {
         String lowerSearch = searchTerm.toLowerCase();
         
-        // Search in reverse order (most recent first)
-        return history.stream()
+        List<String> matches = history.stream()
             .filter(cmd -> cmd.toLowerCase().contains(lowerSearch))
-            .collect(Collectors.collectingAndThen(
-                Collectors.toList(),
-                list -> {
-                    java.util.Collections.reverse(list);
-                    return list;
-                }
-            ));
+            .collect(Collectors.toList());
+        
+        // Reverse to show most recent first
+        java.util.Collections.reverse(matches);
+        return matches;
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7067638 and 9c85717.

📒 Files selected for processing (3)
  • src/main/java/com/mycmd/App.java (2 hunks)
  • src/main/java/com/mycmd/commands/InteractiveSearchCommand.java (1 hunks)
  • src/main/java/com/mycmd/commands/SearchHistoryCommand.java (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: ⚙️ Java CI Build
src/main/java/com/mycmd/commands/SearchHistoryCommand.java

[error] 101-101: method does not override or implement a method from a supertype


[error] 106-106: method does not override or implement a method from a supertype

🔇 Additional comments (5)
src/main/java/com/mycmd/App.java (2)

156-157: LGTM! Command identifiers follow the established pattern.

The new command identifiers are properly defined and follow the naming conventions used throughout the codebase.


235-236: LGTM! Command registration is consistent.

The registration of the new commands follows the existing pattern and correctly maps the command identifiers to their implementations.

src/main/java/com/mycmd/commands/SearchHistoryCommand.java (2)

17-51: LGTM! Well-structured search implementation.

The execute method handles edge cases appropriately, provides clear user feedback, and implements case-insensitive searching correctly.


77-99: LGTM! Effective highlighting implementation.

The highlighting logic correctly handles all occurrences of the search term with case-insensitive matching. The bracket-based highlighting is simple and works across all terminals.

src/main/java/com/mycmd/commands/InteractiveSearchCommand.java (1)

34-92: LGTM! Well-designed interactive search flow.

The interactive loop provides a good user experience with clear prompts, appropriate error handling, and intuitive navigation. The limit of 10 results keeps the output manageable.

@github-actions
Copy link
Contributor

🚀 Hi @SauravBhowmick!

Thank you for contributing to MyCMD. A maintainer will review your PR shortly. 🎉

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (1)
src/main/java/com/mycmd/commands/SearchHistoryCommand.java (1)

73-99: Correct implementation with room for enhancement.

The case-insensitive highlighting logic correctly identifies and marks all occurrences of the search term. Using StringBuilder for string concatenation is efficient and appropriate here.

As noted in the comment on line 75, consider enhancing the highlighting with ANSI escape codes for color output in terminals that support it:

// Example ANSI highlighting (optional enhancement):
private String highlightTerm(String text, String term) {
    String HIGHLIGHT = "\u001B[33m";  // Yellow
    String RESET = "\u001B[0m";
    // ... rest of logic using ANSI codes instead of brackets
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c85717 and 951672e.

📒 Files selected for processing (1)
  • src/main/java/com/mycmd/commands/SearchHistoryCommand.java (1 hunks)
🔇 Additional comments (5)
src/main/java/com/mycmd/commands/SearchHistoryCommand.java (5)

1-14: LGTM! Clean structure and clear documentation.

The package structure, imports, and class documentation are well-organized. The Javadoc clearly explains the command's purpose and usage patterns.


53-71: Nice formatting logic!

The dynamic width calculation based on the number of entries ensures clean, aligned output regardless of history size. The optional highlighting integration is well-designed.


101-104: Previous issue resolved! Method now correctly implements the interface.

The method name has been corrected from getDescription() to description() to properly override the Command interface method. The description is clear and concise.


106-113: Previous issue resolved! Excellent usage documentation.

The method name has been corrected from getUsage() to usage() to properly override the Command interface method. The usage examples are comprehensive and clearly demonstrate the command's capabilities, including the multi-word search feature.


16-51: No changes needed — the code is safe as written.

The code already handles null safety correctly:

  1. getHistory() contract: The method in ShellContext returns new ArrayList<>(history), which is always non-null (even if history is empty). The method explicitly returns a defensive copy.

  2. context parameter: As a method implementing the Command interface, the framework guarantees non-null invocation context (standard framework pattern).

  3. Existing safety check: Line 20's if (history.isEmpty()) properly handles the empty case without risk of NPE.

The Java 17 project correctly uses .toList() (supported since Java 16), which is the idiomatic modern approach.

@anshumanjadiya1102
Copy link
Member

Hey @SauravBhowmick ,

In InteractiveSearchCommand.java around line 29, the code instantiates a new Scanner(System.in) which conflicts with the Scanner created in App.java

@SauravBhowmick
Copy link
Member Author

Ok will check and resolve it

@github-actions
Copy link
Contributor

🚀 Hi @SauravBhowmick!

Thank you for contributing to MyCMD. A maintainer will review your PR shortly. 🎉

@github-actions
Copy link
Contributor

🚀 Hi @SauravBhowmick!

Thank you for contributing to MyCMD. A maintainer will review your PR shortly. 🎉

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/java/com/mycmd/commands/InteractiveSearchCommand.java (1)

101-114: Consider simplifying the reverse collection logic.

The searchHistory method works correctly, filtering case-insensitively and returning results in reverse-chronological order. However, the collectingAndThen with Collections.reverse is verbose.

Consider this more concise alternative:

 private List<String> searchHistory(List<String> history, String searchTerm) {
     String lowerSearch = searchTerm.toLowerCase();
-
-    // Search in reverse order (most recent first)
-    return history.stream()
-            .filter(cmd -> cmd.toLowerCase().contains(lowerSearch))
-            .collect(Collectors.collectingAndThen(
-                    Collectors.toList(),
-                    list -> {
-                        java.util.Collections.reverse(list);
-                        return list;
-                    }
-            ));
+    
+    // Search in reverse order (most recent first)
+    List<String> matches = new java.util.ArrayList<>();
+    for (int i = history.size() - 1; i >= 0; i--) {
+        if (history.get(i).toLowerCase().contains(lowerSearch)) {
+            matches.add(history.get(i));
+        }
+    }
+    return matches;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 951672e and f0025c4.

📒 Files selected for processing (1)
  • src/main/java/com/mycmd/commands/InteractiveSearchCommand.java (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: ⚙️ Java CI Build
src/main/java/com/mycmd/commands/InteractiveSearchCommand.java

[error] 30-34: cannot find symbol: method getScanner() referenced on variable context of type com.mycmd.ShellContext. Compilation failure during Maven build.

🔇 Additional comments (4)
src/main/java/com/mycmd/commands/InteractiveSearchCommand.java (4)

1-8: LGTM!

Package declaration and imports are clean and appropriate for the command's functionality.


9-27: LGTM!

The class documentation is clear, and the empty history guard clause provides good user feedback.


32-95: Verify that displaying (not executing) the selected command is the intended behavior.

The interactive loop logic is well-structured with proper input validation and error handling. However, Line 84 displays the selected command but doesn't execute it. The message tells users to "type it at the prompt" manually.

Verify this matches your requirements—typical interactive history search tools (like bash Ctrl+R) execute or place the command in the input buffer for immediate use. If auto-execution is desired, you'll need to handle command execution here or return the selected command to the main shell loop.


116-126: LGTM!

The description() and usage() methods provide clear, concise documentation for users.

@github-actions
Copy link
Contributor

🚀 Hi @SauravBhowmick!

Thank you for contributing to MyCMD. A maintainer will review your PR shortly. 🎉

@github-actions
Copy link
Contributor

🚀 Hi @SauravBhowmick!

Thank you for contributing to MyCMD. A maintainer will review your PR shortly. 🎉

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/mycmd/ShellContext.java (1)

14-32: Missing Scanner field declaration causes build failure.

The code references scanner at lines 32, 43, 53, and 56, but the field is never declared. This is causing all four pipeline compilation errors.

Add the Scanner field declaration after line 16:

     @Setter @NonNull private File currentDir;
     private List<String> history;
     private Map<String, String> aliases;
+    private Scanner scanner;
 
     private static final String ALIAS_FILE = ".mycmd_aliases";
🧹 Nitpick comments (1)
src/main/java/com/mycmd/ShellContext.java (1)

42-44: Consider adding validation to enforce single-initialization contract.

The Javadoc states this "should only be called once," but there's no runtime enforcement. Additionally, accepting a null Scanner would break getScanner's contract.

Apply this diff to add guards:

     public void setScanner(Scanner scanner) {
+        if (this.scanner != null) {
+            throw new IllegalStateException("Scanner already initialized");
+        }
+        if (scanner == null) {
+            throw new IllegalArgumentException("Scanner cannot be null");
+        }
         this.scanner = scanner;
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0025c4 and d7355f5.

📒 Files selected for processing (2)
  • src/main/java/com/mycmd/App.java (3 hunks)
  • src/main/java/com/mycmd/ShellContext.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/mycmd/App.java
🧰 Additional context used
🪛 GitHub Actions: ⚙️ Java CI Build
src/main/java/com/mycmd/ShellContext.java

[error] 32-32: cannot find symbol: variable scanner


[error] 43-43: cannot find symbol: variable scanner


[error] 53-53: cannot find symbol: variable scanner


[error] 56-56: cannot find symbol: variable scanner

🔇 Additional comments (1)
src/main/java/com/mycmd/ShellContext.java (1)

52-57: Good defensive programming and addresses reviewer concern.

The null check with IllegalStateException properly enforces initialization order. This centralized Scanner access pattern directly addresses the reviewer's concern about InteractiveSearchCommand.java creating its own Scanner instance that conflicts with App.java's Scanner.

@github-actions
Copy link
Contributor

🚀 Hi @SauravBhowmick!

Thank you for contributing to MyCMD. A maintainer will review your PR shortly. 🎉

@github-actions
Copy link
Contributor

🚀 Hi @SauravBhowmick!

Thank you for contributing to MyCMD. A maintainer will review your PR shortly. 🎉

@github-actions
Copy link
Contributor

🚀 Hi @SauravBhowmick!

Thank you for contributing to MyCMD. A maintainer will review your PR shortly. 🎉

@SauravBhowmick
Copy link
Member Author

Hi , @anshumanjadiya1102 you can check now.

@anshumanjadiya1102 anshumanjadiya1102 merged commit b07e678 into Drive-for-Java:main Nov 10, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants