1 Commits

Author SHA1 Message Date
c144658a53 fix linter errors 2024-01-26 13:08:15 +01:00
48 changed files with 467 additions and 792 deletions

View File

@@ -1,96 +0,0 @@
prSections:
- title: Responsible PRs
filters: repo:tlinden/rpnc is:open NOT dependabot
layout:
repoName:
hidden: true
- title: Responsible Dependabot PRs
filters: repo:tlinden/rpnc is:open dependabot
layout:
repoName:
hidden: true
issuesSections:
- title: Responsible Issues
filters: is:open repo:tlinden/rpnc -author:@me
layout:
repoName:
hidden: true
- title: Note-to-Self Issues
filters: is:open repo:tlinden/rpnc author:@me
layout:
creator:
hidden: true
repoName:
hidden: true
defaults:
preview:
open: false
width: 100
keybindings:
universal:
- key: "shift+down"
builtin: pageDown
- key: "shift+up"
builtin: pageUp
prs:
- key: g
name: gitu
command: >
cd {{.RepoPath}} && /home/scip/bin/gitu
- key: M
name: squash-merge
command: gh pr merge --rebase --squash --admin --repo {{.RepoName}} {{.PrNumber}}
- key: i
name: show ci checks
command: gh pr checks --repo {{.RepoName}} {{.PrNumber}} | glow -p
- key: e
name: edit pr
command: ~/.config/gh-dash/edit-gh-pr {{.RepoName}} {{.PrNumber}}
- key: E
name: open repo in emacs
command: emacsclient {{.RepoPath}} &
issues:
- key: v
name: view
command: gh issue view --repo {{.RepoName}} {{.IssueNumber}} | glow -p
- key: l
name: add label
command: gh issue --repo {{.RepoName}} edit {{.IssueNumber}} --add-label $(gum choose bug enhancement question dependencies wontfix)
- key: L
name: remove label
command: gh issue --repo {{.RepoName}} edit {{.IssueNumber}} --remove-label $(gum choose bug enhancement question dependencies wontfix)
- key: E
name: open repo in emacs
command: emacsclient {{.RepoPath}} &
theme:
ui:
sectionsShowCount: true
table:
compact: false
showSeparator: true
colors:
text:
primary: "#E2E1ED"
secondary: "#6770cb"
inverted: "#242347"
faint: "#b0793b"
warning: "#E0AF68"
success: "#3DF294"
background:
selected: "#1B1B33"
border:
primary: "#383B5B"
secondary: "#39386B"
faint: "#8d3e0b"
repoPaths:
:owner/:repo: ~/dev/:repo
pager:
diff: delta

31
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
title: "[bug-report]"
labels: bug
assignees: TLINDEN
---
**Describtion**
<!-- Please provide a clear and concise description of the issue: -->
**Steps To Reproduce**
<!-- Please detail the steps to reproduce the behavior: -->
**Expected behavior**
<!-- What do you expected to happen instead? -->
**Version information**
<!--
Please provide as much version information as possible:
- if you have just installed a binary, provide the output of: rpn -v
- if you installed from source, provide the output of: make show-version
- provide additional details: operating system and version and shell environment
-->
**Additional informations**

View File

@@ -0,0 +1,23 @@
---
name: Feature request
about: Suggest a feature
title: "[feature-request]"
labels: feature-request
assignees: TLINDEN
---
**Describtion**
<!-- Please provide a clear and concise description of the feature you desire: -->
**Version information**
<!--
Just in case the feature is already present, please provide as
much version information as possible:
- if you have just installed a binary, provide the output of: rpn -v
- if you installed from source, provide the output of: make show-version
- provide additional details: operating system and version and shell environment
-->

View File

@@ -1,10 +0,0 @@
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "monthly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"

36
.github/workflows/ci.yaml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: build-and-test-rpn
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
version: [1.21]
os: [ubuntu-latest, windows-latest, macos-latest]
name: Build
runs-on: ${{ matrix.os }}
steps:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.version }}
id: go
- name: checkout
uses: actions/checkout@v3
- name: build
run: go build
- name: test
run: make test
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.21
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3

View File

@@ -1,69 +0,0 @@
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
version: 2
before:
hooks:
- go mod tidy
gitea_urls:
api: https://codeberg.org/api/v1
download: https://codeberg.org
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
- freebsd
archives:
- formats: [tar.gz]
# this name template makes the OS and Arch compatible with the results of `uname`.
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end }}_{{ .Tag }}
# use zip for windows archives
format_overrides:
- goos: windows
formats: [zip]
- goos: linux
formats: [tar.gz,binary]
files:
- src: "*.md"
strip_parent: true
- src: "docs/*"
strip_parent: true
- src: Makefile.dist
dst: Makefile
wrap_in_directory: true
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
groups:
- title: Improved
regexp: '^.*?(feat|add|new)(\([[:word:]]+\))??!?:.+$'
order: 0
- title: Fixed
regexp: '^.*?(bug|fix)(\([[:word:]]+\))??!?:.+$'
order: 1
- title: Changed
order: 999
release:
header: "# Release Notes"
footer: >-
---
Full Changelog: [{{ .PreviousTag }}...{{ .Tag }}](https://codeberg.org/scip/rpnc/compare/{{ .PreviousTag }}...{{ .Tag }})

View File

@@ -1,27 +0,0 @@
matrix:
platform:
- linux/amd64
goversion:
- 1.24
labels:
platform: ${platform}
steps:
build:
when:
event: [push]
image: golang:${goversion}
commands:
- go get
- go build
- go test
linter:
when:
event: [push]
image: golang:${goversion}
commands:
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.5.0
- golangci-lint --version
- golangci-lint run ./...

View File

@@ -1,15 +0,0 @@
# build release
labels:
platform: linux/amd64
steps:
goreleaser:
image: goreleaser/goreleaser
when:
event: [tag]
environment:
GITEA_TOKEN:
from_secret: DEPLOY_TOKEN
commands:
- goreleaser release --clean --verbose

View File

@@ -25,20 +25,20 @@ UID = root
GID = 0
HAVE_POD := $(shell pod2text -h 2>/dev/null)
all: $(tool).1 cmd/$(tool).go buildlocal
all: $(tool).1 $(tool).go buildlocal
%.1: %.pod
ifdef HAVE_POD
pod2man -c "User Commands" -r 1 -s 1 $*.pod > $*.1
endif
cmd/%.go: %.pod
%.go: %.pod
ifdef HAVE_POD
echo "package main" > cmd/$*.go
echo >> cmd/$*.go
echo "var manpage = \`" >> cmd/$*.go
pod2text cmd/$*.pod >> cmd/$*.go
echo "\`" >> cmd/$*.go
echo "package main" > $*.go
echo >> $*.go
echo "var manpage = \`" >> $*.go
pod2text $*.pod >> $*.go
echo "\`" >> $*.go
endif
buildlocal:
@@ -81,8 +81,8 @@ goupdate:
buildall:
./mkrel.sh $(tool) $(VERSION)
release:
gh release create v$(VERSION) --generate-notes
release: buildall
gh release create v$(VERSION) --generate-notes releases/*
show-versions: buildlocal
@echo "### rpn version:"

View File

@@ -1,20 +0,0 @@
# -*-make-*-
.PHONY: install all
tool = rpn
PREFIX = /usr/local
UID = root
GID = 0
all:
@echo "Type 'sudo make install' to install the tool."
@echo "To change prefix, type 'sudo make install PREFIX=/opt'"
install:
install -d -o $(UID) -g $(GID) $(PREFIX)/bin
install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1
install -d -o $(UID) -g $(GID) $(PREFIX)/share/doc
install -o $(UID) -g $(GID) -m 555 $(tool) $(PREFIX)/sbin/
install -o $(UID) -g $(GID) -m 444 $(tool).1 $(PREFIX)/man/man1/
install -o $(UID) -g $(GID) -m 444 *.md $(PREFIX)/share/doc/

View File

@@ -1,7 +1,8 @@
## Programmable command-line calculator using reverse polish notation
[![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://codeberg.org/scip/rpnc/raw/branch/master/LICENSE)
[![Go Report Card](https://goreportcard.com/badge/codeberg.org/scip/rpnc)](https://goreportcard.com/report/codeberg.org/scip/rpnc)
[![Actions](https://github.com/tlinden/rpnc/actions/workflows/ci.yaml/badge.svg)](https://github.com/tlinden/rpnc/actions)
[![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://github.com/tlinden/rpnc/blob/master/LICENSE)
[![Go Report Card](https://goreportcard.com/badge/github.com/tlinden/rpnc)](https://goreportcard.com/report/github.com/tlinden/rpnc)
This is a small commandline calculator which takes its input in
[reverse polish notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation)
@@ -9,7 +10,6 @@ form.
Features:
- unlimited stack
- undo
- various stack manipulation commands
@@ -23,7 +23,6 @@ Features:
- history
- comments (comment character is `#`)
- variables
- help screen uses comfortable internal pager
## Demo
@@ -247,12 +246,7 @@ connection to the outside!**
There are multiple ways to install **rpn**:
- You can use [stew](https://github.com/marwanhawari/stew) to install rpnc:
```default
stew install tlinden/rpnc
```
- Go to the [latest release page](https://codeberg.org/scip/rpn/releases/latest),
- Go to the [latest release page](https://github.com/tlinden/rpn/releases/latest),
locate the binary for your operating system and platform.
Download it and put it into some directory within your `$PATH` variable.
@@ -265,7 +259,7 @@ There are multiple ways to install **rpn**:
- You can also install from source. Issue the following commands in your shell:
```
git clone https://codeberg.org/scip/rpn.git
git clone https://github.com/TLINDEN/rpn.git
cd rpn
make
sudo make install
@@ -279,7 +273,7 @@ hesitate to ask me about it, I'll add it.
The documentation is provided as a unix man-page. It will be
automatically installed if you install from source. However, you can
[read the man-page online](https://codeberg.org/scip/rpnc/raw/branch/master/rpn.pod)
[read the man-page online](https://github.com/TLINDEN/rpnc/blob/master/rpn.pod)
Or if you cloned the repository you can read it this way (perl needs
to be installed though): `perldoc rpn.pod`.
@@ -296,7 +290,7 @@ best way for me to forget to do something.
In order to report a bug, unexpected behavior, feature requests or to
submit a patch, please open an issue on github:
https://codeberg.org/scip/rpnc/issues.
https://github.com/TLINDEN/rpnc/issues.
## Copyright and license
@@ -308,4 +302,4 @@ T.v.Dein <tom AT vondein DOT org>
## Project homepage
https://codeberg.org/scip/rpnc
https://github.com/TLINDEN/rpnc

View File

@@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
package main
import (
"errors"
@@ -78,12 +78,6 @@ erf erfc erfcinv erfinv exp exp2 expm1 floor gamma ilogb j0 j1 log
log10 log1p log2 logb pow round roundtoeven sin sinh tan tanh trunc y0
y1 copysign dim hypot
Converter functions:
cm-to-inch yards-to-meters bytes-to-kilobytes
inch-to-cm meters-to-yards bytes-to-megabytes
gallons-to-liters miles-to-kilometers bytes-to-gigabytes
liters-to-gallons kilometers-to-miles bytes-to-terabytes
Batch functions:
sum sum of all values (alias: +)
max max of all values
@@ -278,18 +272,9 @@ func (c *Calc) EvalItem(item string) error {
return nil
}
// try time
var hour, min int
_, err = fmt.Sscanf(item, "%d:%d", &hour, &min)
if err == nil {
c.stack.Backup()
c.stack.Push(float64(hour) + float64(min)/60)
return nil
}
// try hex
var i int
_, err = fmt.Sscanf(item, "0x%x", &i)
if err == nil {
c.stack.Backup()
@@ -376,7 +361,9 @@ func (c *Calc) EvalItem(item string) error {
}
switch item {
case "?", "help":
case "?":
fallthrough
case "help":
c.PrintHelp()
default:
@@ -585,40 +572,46 @@ func sortcommands(hash Commands) []string {
}
func (c *Calc) PrintHelp() {
output := "Available configuration commands:\n"
fmt.Println("Available configuration commands:")
for _, name := range sortcommands(c.SettingsCommands) {
output += fmt.Sprintf("%-20s %s\n", name, c.SettingsCommands[name].Help)
fmt.Printf("%-20s %s\n", name, c.SettingsCommands[name].Help)
}
output += "\nAvailable show commands:\n"
fmt.Println()
fmt.Println("Available show commands:")
for _, name := range sortcommands(c.ShowCommands) {
output += fmt.Sprintf("%-20s %s\n", name, c.ShowCommands[name].Help)
fmt.Printf("%-20s %s\n", name, c.ShowCommands[name].Help)
}
output += "\nAvailable stack manipulation commands:\n"
fmt.Println()
fmt.Println("Available stack manipulation commands:")
for _, name := range sortcommands(c.StackCommands) {
output += fmt.Sprintf("%-20s %s\n", name, c.StackCommands[name].Help)
fmt.Printf("%-20s %s\n", name, c.StackCommands[name].Help)
}
output += "\nOther commands:\n"
fmt.Println()
fmt.Println("Other commands:")
for _, name := range sortcommands(c.Commands) {
output += fmt.Sprintf("%-20s %s\n", name, c.Commands[name].Help)
fmt.Printf("%-20s %s\n", name, c.Commands[name].Help)
}
output += "\n" + Help
fmt.Println()
fmt.Println(Help)
// append lua functions, if any
if len(LuaFuncs) > 0 {
output += "\nLua functions:\n"
fmt.Println("Lua functions:")
for name, function := range LuaFuncs {
output += fmt.Sprintf("%-20s %s\n", name, function.help)
fmt.Printf("%-20s %s\n", name, function.help)
}
}
Pager("rpn help overview", output)
}

View File

@@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
package main
import (
"fmt"
@@ -78,7 +78,7 @@ func TestCommentsAndWhitespace(t *testing.T) {
t.Run(testname, func(t *testing.T) {
for _, line := range test.cmd {
if err := calc.Eval(line); err != nil {
t.Error(err.Error())
t.Errorf(err.Error())
}
}
got := calc.stack.Last()
@@ -292,7 +292,7 @@ func TestCalc(t *testing.T) {
t.Run(testname, func(t *testing.T) {
calc.batch = test.batch
if err := calc.Eval(test.cmd); err != nil {
t.Error(err.Error())
t.Errorf(err.Error())
}
got := calc.Result()
calc.stack.Clear()
@@ -327,7 +327,7 @@ func TestCalcLua(t *testing.T) {
LuaInterpreter = lua.NewState(lua.Options{SkipOpenLibs: true})
defer LuaInterpreter.Close()
luarunner := NewInterpreter("../example.lua", false)
luarunner := NewInterpreter("example.lua", false)
luarunner.InitLua()
calc.SetInt(luarunner)
@@ -373,8 +373,6 @@ func FuzzEval(f *testing.F) {
"b",
"#444",
"<X",
"?",
"help",
}
for _, item := range legal {
@@ -383,21 +381,16 @@ func FuzzEval(f *testing.F) {
calc := NewCalc()
var hexnum, hour, min int
var hexnum int
f.Fuzz(func(t *testing.T, line string) {
t.Logf("Stack:\n%v\nLine: <%s>\n", calc.stack.All(), line)
switch line {
case "help", "?":
return
}
t.Logf("Stack:\n%v\n", calc.stack.All())
if err := calc.EvalItem(line); err == nil {
t.Logf("given: <%s>", line)
// not corpus and empty?
if !contains(legal, line) && len(line) > 0 {
item := strings.TrimSpace(calc.Comment.ReplaceAllString(line, ""))
_, hexerr := fmt.Sscanf(item, "0x%x", &hexnum)
_, timeerr := fmt.Sscanf(item, "%d:%d", &hour, &min)
// no comment?
if len(item) > 0 {
// no known command or function?
@@ -412,8 +405,7 @@ func FuzzEval(f *testing.F) {
!exists(calc.StackCommands, item) &&
!calc.Register.MatchString(item) &&
item != "?" && item != "help" &&
hexerr != nil &&
timeerr != nil {
hexerr != nil {
t.Errorf("Fuzzy input accepted: <%s>", line)
}
}

View File

@@ -1,120 +0,0 @@
package cmd
// pager setup using bubbletea
// file shamlelessly copied from:
// https://github.com/charmbracelet/bubbletea/tree/main/examples/pager
import (
"fmt"
"os"
"strings"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
var (
titleStyle = func() lipgloss.Style {
b := lipgloss.RoundedBorder()
b.Right = "├"
return lipgloss.NewStyle().BorderStyle(b).Padding(0, 1)
}()
infoStyle = func() lipgloss.Style {
b := lipgloss.RoundedBorder()
b.Left = "┤"
return titleStyle.BorderStyle(b)
}()
)
type model struct {
content string
title string
ready bool
viewport viewport.Model
}
func (m model) Init() tea.Cmd {
return nil
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var (
cmd tea.Cmd
cmds []tea.Cmd
)
switch msg := msg.(type) {
case tea.KeyMsg:
if k := msg.String(); k == "ctrl+c" || k == "q" || k == "esc" {
return m, tea.Quit
}
case tea.WindowSizeMsg:
headerHeight := lipgloss.Height(m.headerView())
footerHeight := lipgloss.Height(m.footerView())
verticalMarginHeight := headerHeight + footerHeight
if !m.ready {
// Since this program is using the full size of the viewport we
// need to wait until we've received the window dimensions before
// we can initialize the viewport. The initial dimensions come in
// quickly, though asynchronously, which is why we wait for them
// here.
m.viewport = viewport.New(msg.Width, msg.Height-verticalMarginHeight)
m.viewport.YPosition = headerHeight
m.viewport.SetContent(m.content)
m.ready = true
} else {
m.viewport.Width = msg.Width
m.viewport.Height = msg.Height - verticalMarginHeight
}
}
// Handle keyboard and mouse events in the viewport
m.viewport, cmd = m.viewport.Update(msg)
cmds = append(cmds, cmd)
return m, tea.Batch(cmds...)
}
func (m model) View() string {
if !m.ready {
return "\n Initializing..."
}
return fmt.Sprintf("%s\n%s\n%s", m.headerView(), m.viewport.View(), m.footerView())
}
func (m model) headerView() string {
// title := titleStyle.Render("RPN Help Overview")
title := titleStyle.Render(m.title)
line := strings.Repeat("─", max(0, m.viewport.Width-lipgloss.Width(title)))
return lipgloss.JoinHorizontal(lipgloss.Center, title, line)
}
func (m model) footerView() string {
info := infoStyle.Render(fmt.Sprintf("%3.f%%", m.viewport.ScrollPercent()*100))
line := strings.Repeat("─", max(0, m.viewport.Width-lipgloss.Width(info)))
return lipgloss.JoinHorizontal(lipgloss.Center, line, info)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func Pager(title, message string) {
p := tea.NewProgram(
model{content: message, title: title},
tea.WithAltScreen(), // use the full size of the terminal in its "alternate screen buffer"
tea.WithMouseCellMotion(), // turn on mouse support so we can track the mouse wheel
)
if _, err := p.Run(); err != nil {
fmt.Println("could not run pager:", err)
os.Exit(1)
}
}

View File

@@ -1,195 +0,0 @@
/*
Copyright © 2023-2024 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
import (
"fmt"
"log"
"os"
"strings"
"github.com/chzyer/readline"
flag "github.com/spf13/pflag"
lua "github.com/yuin/gopher-lua"
)
const VERSION string = "2.1.7"
const Usage string = `This is rpn, a reverse polish notation calculator cli.
Usage: rpn [-bdvh] [<operator>]
Options:
-b, --batchmode enable batch mode
-d, --debug enable debug mode
-s, --stack show last 5 items of the stack (off by default)
-i --intermediate print intermediate results
-m, --manual show manual
-c, --config <file> load <file> containing LUA code
-p, --precision <int> floating point number precision (default 2)
-v, --version show version
-h, --help show help
When <operator> is given, batch mode ist automatically enabled. Use
this only when working with stdin. E.g.: echo "2 3 4 5" | rpn +
Copyright (c) 2023-2025 T.v.Dein`
func Main() int {
calc := NewCalc()
showversion := false
showhelp := false
showmanual := false
enabledebug := false
configfile := ""
flag.BoolVarP(&calc.batch, "batchmode", "b", false, "batch mode")
flag.BoolVarP(&calc.showstack, "show-stack", "s", false, "show stack")
flag.BoolVarP(&calc.intermediate, "showin-termediate", "i", false,
"show intermediate results")
flag.BoolVarP(&enabledebug, "debug", "d", false, "debug mode")
flag.BoolVarP(&showversion, "version", "v", false, "show version")
flag.BoolVarP(&showhelp, "help", "h", false, "show usage")
flag.BoolVarP(&showmanual, "manual", "m", false, "show manual")
flag.StringVarP(&configfile, "config", "c",
os.Getenv("HOME")+"/.rpn.lua", "config file (lua format)")
flag.IntVarP(&calc.precision, "precision", "p", Precision, "floating point precision")
flag.Parse()
if showversion {
fmt.Printf("This is rpn version %s\n", VERSION)
return 0
}
if showhelp {
fmt.Println(Usage)
return 0
}
if enabledebug {
calc.ToggleDebug()
}
if showmanual {
man()
return 0
}
// the lua state object is global, instantiate it early
LuaInterpreter = lua.NewState(lua.Options{SkipOpenLibs: true})
defer LuaInterpreter.Close()
// our config file is interpreted as lua code, only functions can
// be defined, init() will be called by InitLua().
if _, err := os.Stat(configfile); err == nil {
luarunner := NewInterpreter(configfile, enabledebug)
luarunner.InitLua()
calc.SetInt(luarunner)
if calc.debug {
fmt.Println("loaded config")
}
} else if calc.debug {
fmt.Println(err)
}
if len(flag.Args()) > 1 {
// commandline calc operation, no readline etc needed
// called like rpn 2 2 +
calc.stdin = true
if err := calc.Eval(strings.Join(flag.Args(), " ")); err != nil {
fmt.Println(err)
return 1
}
return 0
}
// interactive mode, need readline
reader, err := readline.NewEx(&readline.Config{
Prompt: calc.Prompt(),
HistoryFile: os.Getenv("HOME") + "/.rpn-history",
HistoryLimit: 500,
AutoComplete: calc.completer,
InterruptPrompt: "^C",
EOFPrompt: "exit",
HistorySearchFold: true,
})
if err != nil {
panic(err)
}
defer func() {
if err := reader.Close(); err != nil {
log.Fatal(err)
}
}()
reader.CaptureExitSignal()
if inputIsStdin() {
// commands are coming on stdin, however we will still enter
// the same loop since readline just reads fine from stdin
calc.ToggleStdin()
}
for {
// primary program repl
line, err := reader.Readline()
if err != nil {
break
}
err = calc.Eval(line)
if err != nil {
fmt.Println(err)
}
reader.SetPrompt(calc.Prompt())
}
if len(flag.Args()) > 0 {
// called like this:
// echo 1 2 3 4 | rpn +
// batch mode enabled automatically
calc.batch = true
if err = calc.Eval(flag.Args()[0]); err != nil {
fmt.Println(err)
return 1
}
}
return 0
}
func inputIsStdin() bool {
stat, _ := os.Stdin.Stat()
return (stat.Mode() & os.ModeCharDevice) == 0
}
func man() {
Pager("rpn manual page", manpage)
}

View File

@@ -15,12 +15,11 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
package main
import (
"bufio"
"fmt"
"log"
"os"
"os/exec"
"strconv"
@@ -215,10 +214,6 @@ func (c *Calc) SetCommands() {
c.SettingsCommands["b"] = c.SettingsCommands["batch"]
c.SettingsCommands["s"] = c.SettingsCommands["showstack"]
c.SettingsCommands["togglebatch"] = c.SettingsCommands["batch"]
c.SettingsCommands["toggledebug"] = c.SettingsCommands["debug"]
c.SettingsCommands["toggleshowstack"] = c.SettingsCommands["showstack"]
c.ShowCommands["h"] = c.ShowCommands["history"]
c.ShowCommands["p"] = c.ShowCommands["dump"]
c.ShowCommands["v"] = c.ShowCommands["vars"]
@@ -264,11 +259,7 @@ func CommandEdit(calc *Calc) {
return
}
defer func() {
if err := os.Remove(tmp.Name()); err != nil {
log.Fatal(err)
}
}()
defer os.Remove(tmp.Name())
comment := `# add or remove numbers as you wish.
# each number must be on its own line.
@@ -291,9 +282,7 @@ func CommandEdit(calc *Calc) {
}
}
if err := tmp.Close(); err != nil {
log.Fatal(err)
}
tmp.Close()
// determine which editor to use
editor := "vi"
@@ -328,11 +317,7 @@ func CommandEdit(calc *Calc) {
return
}
defer func() {
if err := modified.Close(); err != nil {
log.Fatal(err)
}
}()
defer modified.Close()
// reset the stack
calc.stack.Clear()

View File

@@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
package main
import (
"errors"
@@ -437,30 +437,6 @@ func DefineFunctions() Funcalls {
},
1),
"bytes-to-kilobytes": NewFuncall(
func(arg Numbers) Result {
return NewResult(arg[0]/1024, nil)
},
1),
"bytes-to-megabytes": NewFuncall(
func(arg Numbers) Result {
return NewResult(arg[0]/1024/1024, nil)
},
1),
"bytes-to-gigabytes": NewFuncall(
func(arg Numbers) Result {
return NewResult(arg[0]/1024/1024/1024, nil)
},
1),
"bytes-to-terabytes": NewFuncall(
func(arg Numbers) Result {
return NewResult(arg[0]/1024/1024/1024/1024, nil)
},
1),
"or": NewFuncall(
func(arg Numbers) Result {
return NewResult(float64(int(arg[0])|int(arg[1])), nil)

36
go.mod
View File

@@ -1,34 +1,12 @@
module rpn
go 1.24.5
go 1.20
require (
github.com/charmbracelet/bubbles v0.21.0
github.com/charmbracelet/bubbletea v1.3.10
github.com/charmbracelet/lipgloss v1.1.0
github.com/chzyer/readline v1.5.1
github.com/rogpeppe/go-internal v1.14.1
github.com/spf13/pflag v1.0.10
github.com/yuin/gopher-lua v1.1.1
)
require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
github.com/charmbracelet/x/ansi v0.10.1 // indirect
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
github.com/charmbracelet/x/term v0.2.1 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.16.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.3.8 // indirect
golang.org/x/tools v0.26.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/yuin/gopher-lua v1.1.0 // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/tools v0.1.12 // indirect
)

66
go.sum
View File

@@ -1,60 +1,16 @@
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8=
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE=
github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=

View File

@@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
package main
import (
"errors"
@@ -116,7 +116,9 @@ func (i *Interpreter) CallLuaFunc(funcname string, items []float64) (float64, er
funcname, LuaFuncs[funcname].numargs))
switch LuaFuncs[funcname].numargs {
case 0, 1:
case 0:
fallthrough
case 1:
// 1 arg variant
if err := LuaInterpreter.CallByParam(lua.P{
Fn: LuaInterpreter.GetGlobal(funcname),

187
main.go
View File

@@ -18,10 +18,193 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"bytes"
"fmt"
"log"
"os"
"rpn/cmd"
"os/exec"
"strings"
"github.com/chzyer/readline"
flag "github.com/spf13/pflag"
lua "github.com/yuin/gopher-lua"
)
const VERSION string = "2.1.0"
const Usage string = `This is rpn, a reverse polish notation calculator cli.
Usage: rpn [-bdvh] [<operator>]
Options:
-b, --batchmode enable batch mode
-d, --debug enable debug mode
-s, --stack show last 5 items of the stack (off by default)
-i --intermediate print intermediate results
-m, --manual show manual
-c, --config <file> load <file> containing LUA code
-p, --precision <int> floating point number precision (default 2)
-v, --version show version
-h, --help show help
When <operator> is given, batch mode ist automatically enabled. Use
this only when working with stdin. E.g.: echo "2 3 4 5" | rpn +
Copyright (c) 2023-2024 T.v.Dein`
func main() {
os.Exit(cmd.Main())
os.Exit(Main())
}
func Main() int {
calc := NewCalc()
showversion := false
showhelp := false
showmanual := false
enabledebug := false
configfile := ""
flag.BoolVarP(&calc.batch, "batchmode", "b", false, "batch mode")
flag.BoolVarP(&calc.showstack, "show-stack", "s", false, "show stack")
flag.BoolVarP(&calc.intermediate, "showin-termediate", "i", false,
"show intermediate results")
flag.BoolVarP(&enabledebug, "debug", "d", false, "debug mode")
flag.BoolVarP(&showversion, "version", "v", false, "show version")
flag.BoolVarP(&showhelp, "help", "h", false, "show usage")
flag.BoolVarP(&showmanual, "manual", "m", false, "show manual")
flag.StringVarP(&configfile, "config", "c",
os.Getenv("HOME")+"/.rpn.lua", "config file (lua format)")
flag.IntVarP(&calc.precision, "precision", "p", Precision, "floating point precision")
flag.Parse()
if showversion {
fmt.Printf("This is rpn version %s\n", VERSION)
return 0
}
if showhelp {
fmt.Println(Usage)
return 0
}
if enabledebug {
calc.ToggleDebug()
}
if showmanual {
man()
return 0
}
// the lua state object is global, instantiate it early
LuaInterpreter = lua.NewState(lua.Options{SkipOpenLibs: true})
defer LuaInterpreter.Close()
// our config file is interpreted as lua code, only functions can
// be defined, init() will be called by InitLua().
if _, err := os.Stat(configfile); err == nil {
luarunner := NewInterpreter(configfile, enabledebug)
luarunner.InitLua()
calc.SetInt(luarunner)
if calc.debug {
fmt.Println("loaded config")
}
} else if calc.debug {
fmt.Println(err)
}
if len(flag.Args()) > 1 {
// commandline calc operation, no readline etc needed
// called like rpn 2 2 +
calc.stdin = true
if err := calc.Eval(strings.Join(flag.Args(), " ")); err != nil {
fmt.Println(err)
return 1
}
return 0
}
// interactive mode, need readline
reader, err := readline.NewEx(&readline.Config{
Prompt: calc.Prompt(),
HistoryFile: os.Getenv("HOME") + "/.rpn-history",
HistoryLimit: 500,
AutoComplete: calc.completer,
InterruptPrompt: "^C",
EOFPrompt: "exit",
HistorySearchFold: true,
})
if err != nil {
panic(err)
}
defer reader.Close()
reader.CaptureExitSignal()
if inputIsStdin() {
// commands are coming on stdin, however we will still enter
// the same loop since readline just reads fine from stdin
calc.ToggleStdin()
}
for {
// primary program repl
line, err := reader.Readline()
if err != nil {
break
}
err = calc.Eval(line)
if err != nil {
fmt.Println(err)
}
reader.SetPrompt(calc.Prompt())
}
if len(flag.Args()) > 0 {
// called like this:
// echo 1 2 3 4 | rpn +
// batch mode enabled automatically
calc.batch = true
if err = calc.Eval(flag.Args()[0]); err != nil {
fmt.Println(err)
return 1
}
}
return 0
}
func inputIsStdin() bool {
stat, _ := os.Stdin.Stat()
return (stat.Mode() & os.ModeCharDevice) == 0
}
func man() {
var buf bytes.Buffer
man := exec.Command("less", "-")
buf.WriteString(manpage)
man.Stdout = os.Stdout
man.Stdin = &buf
man.Stderr = os.Stderr
err := man.Run()
if err != nil {
log.Fatal(err)
}
}

View File

@@ -1,15 +1,16 @@
package main
import (
"os"
"testing"
"github.com/rogpeppe/go-internal/testscript"
)
func TestMain(m *testing.M) {
testscript.Main(m, map[string]func(){
"rpn": main,
})
os.Exit(testscript.RunMain(m, map[string]func() int{
"testrpn": Main,
}))
}
func TestRpn(t *testing.T) {

65
mkrel.sh Executable file
View File

@@ -0,0 +1,65 @@
#!/bin/bash
# Copyright © 2023 Thomas von Dein
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# get list with: go tool dist list
DIST="darwin/amd64
freebsd/amd64
linux/amd64
netbsd/amd64
openbsd/amd64
windows/amd64"
tool="$1"
version="$2"
if test -z "$version"; then
echo "Usage: $0 <tool name> <release version>"
exit 1
fi
rm -rf releases
mkdir -p releases
for D in $DIST; do
os=${D/\/*/}
arch=${D/*\//}
binfile="releases/${tool}-${os}-${arch}-${version}"
tardir="${tool}-${os}-${arch}-${version}"
tarfile="releases/${tool}-${os}-${arch}-${version}.tar.gz"
set -x
GOOS=${os} GOARCH=${arch} go build -tags osusergo,netgo -ldflags "-extldflags=-static" -o ${binfile}
mkdir -p ${tardir}
cp ${binfile} README.md LICENSE ${tardir}/
echo 'tool = rpn
PREFIX = /usr/local
UID = root
GID = 0
install:
install -d -o $(UID) -g $(GID) $(PREFIX)/bin
install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1
install -o $(UID) -g $(GID) -m 555 $(tool) $(PREFIX)/sbin/
install -o $(UID) -g $(GID) -m 444 $(tool).1 $(PREFIX)/man/man1/' > ${tardir}/Makefile
tar cpzf ${tarfile} ${tardir}
sha256sum ${binfile} | cut -d' ' -f1 > ${binfile}.sha256
sha256sum ${tarfile} | cut -d' ' -f1 > ${tarfile}.sha256
rm -rf ${tardir}
set +x
done

View File

@@ -1,4 +1,4 @@
package cmd
package main
var manpage = `
NAME
@@ -108,8 +108,7 @@ DESCRIPTION
is enabled automatically, see last example.
You can enter integers, floating point numbers (positive or negative) or
hex numbers (prefixed with 0x). Time values in hh::mm format are
possible as well.
hex numbers (prefixed with 0x).
STACK MANIPULATION
There are lots of stack manipulation commands provided. The most
@@ -166,10 +165,14 @@ DESCRIPTION
Conversion functions:
cm-to-inch yards-to-meters bytes-to-kilobytes
inch-to-cm meters-to-yards bytes-to-megabytes
gallons-to-liters miles-to-kilometers bytes-to-gigabytes
liters-to-gallons kilometers-to-miles bytes-to-terabytes
cm-to-inch
inch-to-cm
gallons-to-liters
liters-to-gallons
yards-to-meters
meters-to-yards
miles-to-kilometers
kilometers-to-miles
Configuration Commands:
@@ -330,7 +333,7 @@ GETTING HELP
BUGS
In order to report a bug, unexpected behavior, feature requests or to
submit a patch, please open an issue on github:
<https://codeberg.org/scip/rpnc/issues>.
<https://github.com/TLINDEN/rpnc/issues>.
LICENSE
This software is licensed under the GNU GENERAL PUBLIC LICENSE version

17
rpn.pod
View File

@@ -112,8 +112,7 @@ If the first parameter to rpn is a math operator or function, batch
mode is enabled automatically, see last example.
You can enter integers, floating point numbers (positive or negative)
or hex numbers (prefixed with 0x). Time values in hh::mm format are
possible as well.
or hex numbers (prefixed with 0x).
=head2 STACK MANIPULATION
@@ -173,10 +172,14 @@ Math functions:
Conversion functions:
cm-to-inch yards-to-meters bytes-to-kilobytes
inch-to-cm meters-to-yards bytes-to-megabytes
gallons-to-liters miles-to-kilometers bytes-to-gigabytes
liters-to-gallons kilometers-to-miles bytes-to-terabytes
cm-to-inch
inch-to-cm
gallons-to-liters
liters-to-gallons
yards-to-meters
meters-to-yards
miles-to-kilometers
kilometers-to-miles
Configuration Commands:
@@ -367,7 +370,7 @@ tarball, there will also be a manual page you can read using C<man rpn>.
In order to report a bug, unexpected behavior, feature requests
or to submit a patch, please open an issue on github:
L<https://codeberg.org/scip/rpnc/issues>.
L<https://github.com/TLINDEN/rpnc/issues>.
=head1 LICENSE

BIN
rpnc.mp4

Binary file not shown.

View File

@@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
package main
import (
"container/list"

View File

@@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
package main
import (
"testing"

View File

@@ -1,2 +1,2 @@
exec rpn 1 2 dump
exec testrpn 1 2 dump
stdout 'Stack revision 2 .0x'

View File

@@ -1,2 +1,2 @@
! exec rpn 1 2 dumb
! exec testrpn 1 2 dumb
stdout 'unknown command or operator'

View File

@@ -1,2 +1,2 @@
exec rpn -p 4 2 3 /
exec testrpn -p 4 2 3 /
stdout '0.6667\n'

View File

@@ -1,2 +1,2 @@
! exec rpn 4 +
! exec testrpn 4 +
stdout 'stack doesn''t provide enough arguments'

View File

@@ -1,2 +1,2 @@
exec rpn -d 44 55 *
exec testrpn -d 44 55 *
stdout 'push to stack: 2420.00\n'

View File

@@ -1,2 +1,2 @@
! exec rpn 100 50 50 - /
! exec testrpn 100 50 50 - /
stdout 'division by null'

View File

@@ -1,4 +1,4 @@
exec rpn -d -c test.lua 3 5 lower
exec testrpn -d -c test.lua 3 5 lower
stdout '3\n'
-- test.lua --

View File

@@ -1,2 +0,0 @@
exec rpn 09:55 4:15 -
stdout '5.67\n'

View File

@@ -1,2 +1,2 @@
exec rpn 44 55 *
exec testrpn 44 55 *
stdout '2420\n'

2
t/getman.txtar Normal file
View File

@@ -0,0 +1,2 @@
exec testrpn -m
stdout 'This software is licensed under the GNU GENERAL PUBLIC LICENSE'

View File

@@ -1,2 +1,2 @@
exec rpn -h
exec testrpn -h
stdout 'This is rpn'

View File

@@ -1,2 +1,2 @@
exec rpn -v
exec testrpn -v
stdout 'This is rpn version'

View File

@@ -1,4 +1,4 @@
exec echo 1 2 3 4 5 batch median
stdin stdout
exec rpn
exec testrpn
[unix] stdout '3\n'

View File

@@ -1,4 +1,4 @@
exec echo 1 2 3 4 5
stdin stdout
[unix] exec rpn median
[unix] exec testrpn median
[unix] stdout '3\n'

View File

@@ -1,4 +1,4 @@
exec echo 10 10 +
stdin stdout
exec rpn
exec testrpn
[unix] stdout '20\n'

6
t/stdin-help.txtar Normal file
View File

@@ -0,0 +1,6 @@
stdin input.txt
exec testrpn
[unix] stdout 'Available configuration commands'
-- input.txt --
?

View File

@@ -1,5 +1,5 @@
stdin input.txt
exec rpn
exec testrpn
[unix] stdout '28\n'
-- input.txt --

View File

@@ -1,4 +1,4 @@
exec echo 1 2 3 4 5 median
stdin stdout
exec rpn -b
exec testrpn -b
[unix] stdout '3\n'

View File

@@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
package main
import (
"fmt"

View File

@@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cmd
package main
import (
"testing"