| Age | Commit message (Collapse) | Author |
|
Idiomatic Go uses struct{} for zero-allocation sets. Two locations:
- GetCompletionTopics: seen deduplication map
- init(): seenCat category deduplication map
|
|
Add a Render func() string field to HelpTopic that overrides the
default formatTopic rendering. Use it to register 'categories' as a
normal HelpTopic entry instead of a hardcoded if-branch in GetHelp.
- Remove hardcoded if topic == "categories" from GetHelp
- Remove hardcoded 'categories' from GetCompletionTopics
- Remove dead getCategoriesHelp function from help.go
- 'categories' now discovered through normal helpByTopic lookup
|
|
The original help.go was 657 lines mixing data, indexing, and lookup
logic. Split into:
- help_topics.go (489 lines): HelpTopic struct, helpTopics data slice,
index variables, and init() that builds the lookup maps.
- help.go (171 lines): GetHelp, GetAllTopics, GetCompletionTopics,
getGeneralHelp, getCategoriesHelp, and formatTopic.
All tests pass. No behavioral changes.
|
|
Per the readline AutoCompleter docs, Do() should return suffixes
(the characters AFTER the common prefix), not full matches. The
length parameter indicates how many characters are shared.
This fixes the bug where readline appended the full match to the
typed input (e.g. 'he' + 'help' = 'hehelp') because commonLen
was 0 and readline had no idea what to replace.
Now 'he<TAB>' returns suffix 'lp' with commonLen=2, so readline
correctly replaces 'he' with 'help'.
|
|
When the typed word already exactly matches a command (e.g. 'help'),
return no completions. Readline would append the match, producing
'helphelp'. Partial matches still work normally (e.g. 'he' → 'help').
|
|
When user types 'help ' (with trailing space), the completer now
offers help topic completions (+, dup, swap, etc.). Just 'help'
without a space still completes the command normally.
Also skip 'help' itself from GetCompletionTopics to avoid
suggesting 'help help'.
|
|
'help <TAB>' was suggesting 'help help'. Skip 'help' itself
in GetCompletionTopics so tab completion offers actual topics.
|
|
Replace the old static help text with a data-driven help system that
provides one help entry per operator, function, or REPL command, each
with category, description, usage, and examples.
- help.go: 35+ help topics covering all operators (arithmetic,
comparison, stack, hyper, variables, constants, REPL commands)
- GetHelp(topic) returns formatted help; GetHelp("") returns overview
- help categories lists all topics grouped by category
- Aliases supported (e.g. help gt shows help for > operator)
- Auto-completion for help topics when typing 'help <TAB>'
- REPL entries take priority in helpByTopic (e.g. 'help clear' shows
screen clear, not RPN variable clear)
- Comprehensive tests for all public functions
|
|
MetricReader (task ok)
|
|
|
|
All operator registry keys are lowercase, so strings.ToLower(token)
was a no-op. Removing the unnecessary lowercasing and the unused
op variable, passing the original token directly to
IsStandardOperator/IsHyperOperator/EvalOperator.
|
|
Add var _ Interface assertions to verify implementations at compile
time:
- internal/rpn/variables.go: assert *Variables against
VariableReader, VariableWriter, VariablePersistence, and
VariableStore
- internal/repl/handlers.go: assert *BuiltInCommandHandler,
*RPNHandler, *PercentageHandler, and *ErrorHandler against
CommandHandler (BaseHandler intentionally excluded as it lacks a
Handle method and is only meant for embedding)
- internal/repl/completer.go: assert *AutoCompleteAdapter against
readline.AutoCompleter (adds readline import)
Note: internal/rpn/constants.go already had assertions in place.
|
|
Replace the hardcoded strings.HasPrefix check for "rpn " and "calc "
with a loop over a package-level rpnPrefixes slice. Adding a new prefix
now only requires appending to the slice, satisfying the Open/Closed
Principle.
|
|
Handlers accessed repl.rpnState.rpnCalc — three levels of concrete types
violating DIP and Law of Demeter. Define an RPNCalculator interface
capturing only the methods handlers actually need, and expose it via
REPL.RpnCalculator() so handlers depend on the interface, not the
concrete chain of *rpn.RPN.
|
|
Factor out the repeated save-restore-evaluate pattern from
RPNHandler.Handle() into a single helper method so the stack
is always restored on parse errors, across all call sites.
|
|
Merge three identical single-token blocks (operator, number, symbol)
into one block with conditional checks. Eliminates redundant
strings.Fields calls and len(fields)==1 checks.
The 'rat' command early-return is not redundant — it correctly
short-circuits before ExecuteCommand is reached.
|
|
RPNHandler.Handle silently swallowed ParseAndEvaluate errors on
multi-word input, leaving the persistent REPL stack in a corrupted
state. evaluate() modifies r.currentStack directly during token
processing, so partial evaluation on failure left orphan values.
Fix: save the stack before ParseAndEvaluate, restore it on error.
Applied to both the bare RPN path and the rpn/calc prefix path.
Added tests:
- TestRPNHandlerStackNotCorruptedOnError (bare multi-word input)
- TestRPNHandlerErrorReturnedNotSwallowed (error propagation)
- TestRPNHandlerStackNotCorruptedOnPrefixedError (rpn/calc prefix)
|
|
- completer() is not used by readline; AutoCompleteAdapter is used instead
- AutoCompleteAdapter does not wrap or use the completer() function;
it maintains its own commands slice
- NewAutoCompleter does not use the completer function
|
|
The comment claimed Start blocks until Stop is called, but Start
launches a goroutine and returns immediately. Updated the doc comment
to accurately describe the non-blocking behavior.
|
|
- NewRPNState: correct 'config directory' to 'state directory' (XDG state, not config)
- REPL struct: change 'percentage calculator' to 'calculator' (it's primarily RPN)
- NewREPL: clarify that completer parameter is unused and logWriter is only stored
- defaultExecutor: remove claim that 'handled commands are added to history' (code does the opposite)
- defaultCompleter: remove claim about case-insensitivity and descriptions (not implemented)
- RunREPLWithLog: remove claim about logging input/output (logWriter is stored but not used)
|
|
- Fix Next() doc to show correct 3-value return signature
("", false, nil) instead of (false, nil)
- Add missing symbol syntax (:x) to RPNHandler.Handle doc comment
|
|
- Fix cmdStack doc comment: it redirects to 'rpn show' rather than
displaying stack state directly (has no access to RPN state)
- Add missing 'rat' and 'stack' to cmdHelp's fallback available commands
list
|
|
Update the Go version directive to match the local runtime (go1.26.3).
Also includes go mod tidy cleanup and unrelated test improvements.
|
|
Dependency Inversion: scope MetricRegistry as a dependency rather than
relying on a global singleton. This enables testing with custom registries
and decouples code from global mutable state.
Changes:
- NewRPN(vars, reg...): accepts optional *MetricRegistry parameter.
Defaults to GetMetricRegistry() when not provided (backward compatible).
- NewOperations(vars, reg...): accepts optional *MetricRegistry parameter.
Defaults to GetMetricRegistry() when not provided (backward compatible).
- parseNumberWithMetric(token, reg): requires *MetricRegistry parameter
instead of calling GetMetricRegistry() internally.
- RPN struct stores metricRegistry field, used by rpn_parse.go for
metric lookups (@ prefix and parseNumberWithMetric).
- Added Operations.MetricRegistry() getter for external access.
All existing callers remain backward compatible via variadic defaults.
Tests updated to pass GetMetricRegistry() to parseNumberWithMetric.
|
|
Add dedicated unit tests for four REPL components that lacked
test coverage:
- SignalHandler (signal_test.go): 5 tests covering constructor,
Stop() without Start, callback execution, goroutine semantics,
and single-shot signal handling behavior
- TTYChecker (tty_test.go): 5 tests covering EnsureTTY error in
non-TTY context, error message content, IsTTY return value,
IsTTY/EnsureTTY consistency, and idempotent behavior
- HistoryManager (history_test.go): 11 tests covering constructor,
Path() with default and custom baseDir, Save/Load roundtrip,
maxEntries truncation, non-existent file, empty file/slice,
special characters, and file overwrite behavior. Added
WithBaseDir() method to enable testing with temp directories.
- AutoCompleteAdapter (completer_adapter_test.go): 5 tests covering
Do() with empty/whitespace input, exact/partial/no matches,
case-insensitive matching, multi-word completion, cursor position,
common prefix calculation, and command order preservation
|
|
Fix formatting in 12 files to match gofmt standards.
No logical changes.
|
|
Add IsStandardOperator/IsHyperOperator forwarding methods on *RPN
that delegate to OperatorRegistry. Replace the hardcoded string
literal whitelist in RPNHandler.Handle() with dynamic registry
lookups.
New operators are now automatically recognized without updating
handlers.go. Also fixes missing operators in the old whitelist
(e.g., comparison operators, assignment operators).
|
|
Delete internal/repl/calculator.go which defined the Calculator
interface and RPNCalculator adapter. Every method delegated directly
to *rpn.RPN with zero transformation — unnecessary indirection.
RPNState now holds *rpn.RPN directly instead of the Calculator
interface. Updated NewRPNState, NewREPL, handleRatCommand, and
RPNHandler.Handle() to access *rpn.RPN directly.
Removes 71 net lines, zero behavioral changes.
|
|
Task fe: The infinite for loop in Run() can only exit via return
(fmt.Errorf on readline error). The trailing 'return nil' was dead
code flagged by go vet. Removed.
|
|
- Task 31: Refactor repl tests to remove dependency on package-level singletons
- Task 41: Introduce Calculator interface to decouple REPL from RPN engine
- Task 61: Implement persistent variable store with Save/Load methods
- Task 71: Add stack inspection (peek) command to REPL
- Task 81: Expand constants library with additional mathematical constants
- Task a1: Add session logging flag (--log) to gt CLI
- Task 91: Integrate reverse history search (Ctrl+R) using readline
This commit includes:
- New: internal/repl/calculator.go - Calculator interface for RPN decoupling
- New: internal/repl/completer.go - AutoCompleteAdapter for readline
- Modified: internal/repl/repl.go - Uses readline instead of go-prompt
- Modified: internal/rpn/variables.go - Added Save/Load for persistent state
- Modified: internal/rpn/rpn_state.go - Added Stack() method
- Modified: internal/rpn/constants.go - Added more mathematical constants
- Modified: internal/repl/commands.go - Added 'stack' command
- Modified: internal/repl/completer_test.go - Updated for readline API
- Modified: internal/repl/repl_test.go - Updated for Calculator interface
- Modified: internal/repl/concurrent_test.go - Updated for Calculator interface
- Modified: internal/repl/handlers.go - Updated for Calculator interface
- Modified: internal/rpn/variables_test.go - Added Save/Load tests
- Modified: internal/rpn/constants_test.go - Added new constant tests
- Modified: cmd/gt/main.go - Added --log flag support
- Modified: Magefile.go - Symmetrized Install/Uninstall logic
- Deleted: internal/repl/prompt.go - Replaced by readline integration
- Added: STORY.md - Project history documentation
|
|
|
|
|
|
- internal/repl/repl_test.go: Remove unused state variable assignments
- internal/rpn/rpn_test.go: Remove unused result/err variable assignments
These changes address golangci-lint 'ineffectual assignment' warnings.
|
|
- Fix error handling in test files by explicitly ignoring error returns
- Remove trailing punctuation from error message in rpn_parse.go
Test file changes:
- cli_test.go: Use _ = os.Remove() in Cleanup function
- concurrent_test.go: Use _, _ = runRPN() in concurrent goroutines
Code change:
- rpn_parse.go: Changed error message to end with 'colon' instead of ':'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Renamed internal/calculator directory to internal/perc, updated package name from 'calculator' to 'perc', and updated all import references.
|
|
- Added 'SPDX-License-Identifier: MIT' and 'Copyright (c) 2026 Paul Buetow' headers
- Files updated: 24 .go files across cmd/gt/, internal/calculator/, internal/repl/, internal/rpn/
The MIT license from LICENSE file is reflected in all source files.
|
|
- Removed duplicate getCommandDescription function from completer.go
- Added package-level getCommandDescription in repl.go as single source of truth
- Updated defaultGetCommandDescription to delegate to getCommandDescription
- Created minimal completer.go that uses getCommandDescription for test compatibility
Command descriptions are now defined only once, eliminating duplication
between the original completer.go and defaultGetCommandDescription in repl.go.
The refactoring maintains:
- Backward compatibility (tests still work)
- Consistent descriptions across the codebase
- Single source of truth for command descriptions
|
|
- Enhanced NewREPL documentation with detailed parameter descriptions
- Enhanced RunREPL documentation clarifying it's a convenience wrapper
- Improved executor documentation explaining backward compatibility and testing usage
- Enhanced defaultExecutor documentation with input processing details and panic recovery
- Enhanced defaultCompleter documentation with tab-completion behavior details
- Enhanced defaultGetCommandDescription documentation with command description details
- Improved TTYChecker methods (IsTTY, EnsureTTY) documentation
- Improved SignalHandler.Start method documentation
All exported and non-exported functions in the REPL package now have comprehensive documentation comments that describe their purpose, parameters, and return values.
|
|
- Add TestDefaultExecutorCodePaths to test all code paths in defaultExecutor
- Improve TestDefaultCompleter to test with multiple input prefixes
- Add comprehensive test for unknown commands, built-in commands, and edge cases
|
|
- Move RPNState type definition before any functions
- Move rpnState and rpnStateOnce variable declarations before any functions
- Keep REPL struct and NewREPL constructor at the top (as per Go best practices)
- Update getRPNState comment to be more descriptive
This change follows Go best practices where constants, global variables, and type
definitions should be at the top of the file before functions.
|
|
- Add RPN (Reverse Polish Notation) calculator with stack-based operations
- Support precise rational number calculations using *big.Rat
- Implement chain of responsibility pattern for command handling
- Add auto-completion for built-in commands
- Add history persistence with configurable max entries
- Support standard operators: +, -, *, /, ^, %, lg, log, ln
- Support hyper operators: [+], [-], [*], [/], [^], [%], [lg], [log], [ln]
- Support stack manipulation: dup, swap, pop, show
- Support variable assignments and management
- Add rat mode for switching between float64 and rational calculations
- Refactor calculator to return Calculation struct with formatting
- Add proper version support (v0.3.0)
All changes follow Go best practices with comprehensive test coverage.
|
|
Added defer-recover mechanism to the executor function to catch unexpected panics.
When a panic occurs, a user-friendly error message is displayed and the REPL can continue to function.
This improves the robustness of the REPL when handling unexpected errors.
|
|
- Error wrapping improvements across multiple files
- Thread-safe singleton initialization using sync.Once
- Proper error handling for file close operations
- Removed speculative complexity in history management
- Fixed operator interface design
Audit report: COMPLETE_AUDIT_REPORT.md
|