-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoption_example_test.go
More file actions
119 lines (110 loc) · 2.62 KB
/
option_example_test.go
File metadata and controls
119 lines (110 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package verbs_test
import (
"fmt"
"os"
"strconv"
"github.com/revl/verbs"
)
const (
TagAdd = "add"
TagSub = "sub"
TagMul = "mul"
TagDiv = "div"
)
var rpnCalcCLI = &verbs.CLI{
ProgramName: "rpncalc",
Summary: "Reverse Polish Notation calculator",
Description: "A simple RPN calculator that processes numbers and " +
"operations from the command line. Numbers are pushed onto " +
"a stack, and operations pop operands from the stack and " +
"push the result.\n\n" +
"Example:\n" +
" $ rpncalc 3 4 -a 2 -m # This computes (3 + 4) * 2 = 14",
Options: []*verbs.Option{
{
Name: "a|add",
Description: "Add the top two numbers on the stack",
Tag: TagAdd,
},
{
Name: "s|sub",
Description: "Subtract the top two numbers on the stack (second - first)",
Tag: TagSub,
},
{
Name: "m|mul",
Description: "Multiply the top two numbers on the stack",
Tag: TagMul,
},
{
Name: "d|div",
Description: "Divide the top two numbers on the stack (second / first)",
Tag: TagDiv,
},
},
Args: []*verbs.Arg{
{
Name: "NUMBER",
Occurrence: verbs.ZeroOrMore,
Description: "Numbers to push onto the stack",
},
},
OptionDescriptionIndent: 14,
}
// This example demonstrates argument-only mode, where the program accepts
// only options and positional arguments without requiring a command.
func ExampleOption() {
result := verbs.NewParser(rpnCalcCLI).Parse(os.Args)
stack := []float64{}
// Process parsed options and arguments in order
for _, item := range result.OptsAndArgs {
if item.Tag == "NUMBER" {
// Parse number and push onto stack
num, err := strconv.ParseFloat(item.Value, 64)
if err != nil {
result.HandleError(fmt.Errorf(
"invalid number: %s", item.Value))
}
stack = append(stack, num)
} else if len(stack) < 2 {
result.HandleError(fmt.Errorf("operation %s "+
"requires at least 2 numbers on stack",
item.Token))
} else {
// Pop two operands
b := stack[len(stack)-1]
a := stack[len(stack)-2]
stack = stack[:len(stack)-2]
// Perform operation
var res float64
switch item.Tag {
case TagAdd:
res = a + b
case TagSub:
res = a - b
case TagMul:
res = a * b
case TagDiv:
if b == 0 {
fmt.Fprintln(os.Stderr,
"Error: division by zero")
os.Exit(1)
}
res = a / b
}
stack = append(stack, res)
}
}
// Print result
switch len(stack) {
case 0:
fmt.Println("0")
case 1:
fmt.Println(stack[0])
default:
fmt.Fprintf(os.Stderr,
"Error: %d numbers remaining on stack: %v\n",
len(stack), stack)
os.Exit(1)
}
}