mirror of
https://codeberg.org/scip/anydb.git
synced 2025-12-17 12:31:02 +01:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 46d641301d | |||
| d1702949a2 | |||
| eb39f57199 | |||
| 471d89eccd | |||
|
|
b74bb79a45 | ||
|
|
39436215d7 | ||
|
|
074547c356 | ||
|
|
79d031d6a8 | ||
|
|
e42f664dfd | ||
|
|
e75062d2fd | ||
| 6481e0cd15 | |||
|
|
62c975206f | ||
|
|
36a7d9f0c8 | ||
|
|
c3eb61c6d2 | ||
|
|
c8b3fd782e | ||
|
|
d7c20ed245 | ||
|
|
0e4eb60271 | ||
|
|
9b25725f5f | ||
|
|
e34c25c889 | ||
|
|
b3a7064160 | ||
|
|
1b00aeb23c | ||
|
|
aad9b31169 | ||
|
|
f22719a92b | ||
|
|
b9f9655d7c | ||
|
|
edc08f12a7 | ||
|
|
e549ae8ed5 | ||
|
|
2c0cc36551 | ||
|
|
7fe8004d41 | ||
|
|
12e3029145 | ||
| 438248d267 | |||
| 05a812ebde | |||
|
|
ef85582488 | ||
|
|
eb18e97c0d | ||
|
|
be13ec1111 | ||
|
|
44bb6a0a26 | ||
|
|
6d2800c72e |
96
.gh-dash.yml
Normal file
96
.gh-dash.yml
Normal file
@@ -0,0 +1,96 @@
|
||||
prSections:
|
||||
- title: Responsible PRs
|
||||
filters: repo:tlinden/anydb is:open NOT dependabot
|
||||
layout:
|
||||
repoName:
|
||||
hidden: true
|
||||
|
||||
- title: Responsible Dependabot PRs
|
||||
filters: repo:tlinden/anydb is:open dependabot
|
||||
layout:
|
||||
repoName:
|
||||
hidden: true
|
||||
|
||||
issuesSections:
|
||||
- title: Responsible Issues
|
||||
filters: is:open repo:tlinden/anydb -author:@me
|
||||
layout:
|
||||
repoName:
|
||||
hidden: true
|
||||
|
||||
- title: Note-to-Self Issues
|
||||
filters: is:open repo:tlinden/anydb 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
|
||||
56
.github/workflows/ci.yaml
vendored
56
.github/workflows/ci.yaml
vendored
@@ -1,56 +0,0 @@
|
||||
name: build-and-test
|
||||
|
||||
#on: [push, pull_request]
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
version: ['1.23']
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
name: Build
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.version }}
|
||||
id: go
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: build
|
||||
run: go build
|
||||
|
||||
- name: test
|
||||
run: make test
|
||||
|
||||
- name: Update coverage report
|
||||
uses: ncruces/go-coverage-report@main
|
||||
with:
|
||||
report: true
|
||||
chart: true
|
||||
amend: true
|
||||
if: |
|
||||
matrix.os == 'ubuntu-latest' &&
|
||||
github.event_name == 'push'
|
||||
continue-on-error: true
|
||||
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.23
|
||||
- uses: actions/checkout@v4
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
34
.github/workflows/pushimage.yaml
vendored
34
.github/workflows/pushimage.yaml
vendored
@@ -1,34 +0,0 @@
|
||||
name: build-push-image
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build-and-push-image:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
|
||||
with:
|
||||
registry: https://ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991
|
||||
with:
|
||||
push: true
|
||||
tags: ghcr.io/tlinden/anydb:${{ github.ref_name}}
|
||||
|
||||
- name: Build and push latest Docker image
|
||||
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991
|
||||
with:
|
||||
push: true
|
||||
tags: ghcr.io/tlinden/anydb:latest
|
||||
87
.github/workflows/release.yaml
vendored
87
.github/workflows/release.yaml
vendored
@@ -1,87 +0,0 @@
|
||||
name: build-release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Build Release Assets
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.23.5
|
||||
|
||||
- name: Build the executables
|
||||
run: ./mkrel.sh anydb ${{ github.ref_name}}
|
||||
|
||||
- name: List the executables
|
||||
run: ls -l ./releases
|
||||
|
||||
- name: Upload the binaries
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: ${{ github.ref_name }}
|
||||
file: ./releases/*
|
||||
file_glob: true
|
||||
|
||||
- name: Build Changelog
|
||||
id: github_release
|
||||
uses: mikepenz/release-changelog-builder-action@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
mode: "PR"
|
||||
configurationJson: |
|
||||
{
|
||||
"template": "#{{CHANGELOG}}\n\n**Full Changelog**: #{{RELEASE_DIFF}}",
|
||||
"pr_template": "- #{{TITLE}} (##{{NUMBER}}) by #{{AUTHOR}}\n#{{BODY}}",
|
||||
"empty_template": "- no changes",
|
||||
"categories": [
|
||||
{
|
||||
"title": "## New Features",
|
||||
"labels": ["add", "feature"]
|
||||
},
|
||||
{
|
||||
"title": "## Bug Fixes",
|
||||
"labels": ["fix", "bug", "revert"]
|
||||
},
|
||||
{
|
||||
"title": "## Documentation Enhancements",
|
||||
"labels": ["doc"]
|
||||
},
|
||||
{
|
||||
"title": "## Refactoring Efforts",
|
||||
"labels": ["refactor"]
|
||||
},
|
||||
{
|
||||
"title": "## Miscellaneus Changes",
|
||||
"labels": []
|
||||
}
|
||||
],
|
||||
"ignore_labels": [
|
||||
"duplicate", "good first issue", "help wanted", "invalid", "question", "wontfix"
|
||||
],
|
||||
"label_extractor": [
|
||||
{
|
||||
"pattern": "(.) (.+)",
|
||||
"target": "$1"
|
||||
},
|
||||
{
|
||||
"pattern": "(.) (.+)",
|
||||
"target": "$1",
|
||||
"on_property": "title"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
body: ${{steps.github_release.outputs.changelog}}
|
||||
6
.golangci.bck.yaml
Normal file
6
.golangci.bck.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
linters:
|
||||
exclusions:
|
||||
rules:
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: "QF1008:"
|
||||
7
.golangci.yaml
Normal file
7
.golangci.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
version: "2"
|
||||
linters:
|
||||
exclusions:
|
||||
rules:
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: "QF1008:"
|
||||
69
.goreleaser.yaml
Normal file
69
.goreleaser.yaml
Normal file
@@ -0,0 +1,69 @@
|
||||
# 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/epuppy/compare/{{ .PreviousTag }}...{{ .Tag }})
|
||||
27
.woodpecker/build.yaml
Normal file
27
.woodpecker/build.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
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 ./...
|
||||
32
.woodpecker/image.yaml
Normal file
32
.woodpecker/image.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
# https://woodpecker-ci.org/plugins/docker-buildx
|
||||
# enable Package unit and go to /scip/-/packages after building to link to proj
|
||||
|
||||
variables:
|
||||
- &repo codeberg.org/${CI_REPO_OWNER}/anydb
|
||||
|
||||
steps:
|
||||
dryrun:
|
||||
image: docker.io/woodpeckerci/plugin-docker-buildx:latest
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
platforms: linux/amd64
|
||||
dry_run: true
|
||||
repo: *repo
|
||||
tags: latest
|
||||
when:
|
||||
event: [pull_request]
|
||||
|
||||
publish:
|
||||
image: docker.io/woodpeckerci/plugin-docker-buildx:latest
|
||||
settings:
|
||||
dockerfile: Dockerfile
|
||||
platforms: linux/amd64
|
||||
repo: *repo
|
||||
registry: codeberg.org
|
||||
tags: latest,${CI_COMMIT_SHA:0:8},${CI_COMMIT_TAG}
|
||||
username: ${CI_REPO_OWNER}
|
||||
password:
|
||||
from_secret: REGISTRY_TOKEN
|
||||
when:
|
||||
event: [tag]
|
||||
branch: main
|
||||
15
.woodpecker/release.yaml
Normal file
15
.woodpecker/release.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
# 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
|
||||
@@ -14,7 +14,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/>.
|
||||
#
|
||||
FROM golang:1.23-alpine as builder
|
||||
FROM golang:1.24-alpine as builder
|
||||
|
||||
RUN apk update
|
||||
RUN apk upgrade
|
||||
|
||||
8
Makefile
8
Makefile
@@ -51,11 +51,11 @@ endif
|
||||
|
||||
app/dbentry.pb.go: app/dbentry.proto
|
||||
protoc -I=. --go_out=app app/dbentry.proto
|
||||
mv app/github.com/tlinden/anydb/app/dbentry.pb.go app/dbentry.pb.go
|
||||
mv app/codeberg.org/scip/anydb/app/dbentry.pb.go app/dbentry.pb.go
|
||||
rm -rf app/github.com
|
||||
|
||||
buildlocal:
|
||||
go build -ldflags "-X 'github.com/tlinden/anydb/cfg.VERSION=$(VERSION)'"
|
||||
go build -ldflags "-X 'codeberg.org/scip/anydb/cfg.VERSION=$(VERSION)'"
|
||||
|
||||
# binaries are being built by ci workflow on tag creation
|
||||
release:
|
||||
@@ -70,12 +70,12 @@ install: buildlocal
|
||||
clean:
|
||||
rm -rf $(tool) releases coverage.out
|
||||
|
||||
test:
|
||||
test: clean
|
||||
ANYDB_PASSWORD=test go test -v ./...
|
||||
|
||||
singletest:
|
||||
@echo "Call like this: ''make singletest TEST=TestPrepareColumns MOD=lib"
|
||||
ANYDB_PASSWORD=test go test -run $(TEST) github.com/tlinden/anydb/$(MOD)
|
||||
ANYDB_PASSWORD=test go test -run $(TEST) codeberg.org/scip/anydb/$(MOD)
|
||||
|
||||
cover-report:
|
||||
go test ./... -cover -coverprofile=coverage.out
|
||||
|
||||
38
README.md
38
README.md
@@ -1,18 +1,24 @@
|
||||
## A personal key value store
|
||||
|
||||
[](https://github.com/tlinden/anydb/actions)
|
||||
[](https://github.com/tlinden/anydb/blob/master/LICENSE)
|
||||
[](https://raw.githack.com/wiki/tlinden/anydb/coverage.html)
|
||||
[](https://goreportcard.com/report/github.com/tlinden/anydb)
|
||||
[](https://github.com/TLINDEN/anydb/releases/latest)
|
||||
[](https://github.com/TLINDEN/anydb/blob/master/anydb.pod)
|
||||
[](https://ci.codeberg.org/repos/15517)
|
||||
[](https://codeberg.org/scip/anydb/blob/master/LICENSE)
|
||||
[](https://goreportcard.com/report/codeberg.org/scip/anydb)
|
||||
[](https://codeberg.org/scip/anydb/releases)
|
||||
[](https://codeberg.org/scip/anydb/raw/branch/main/anydb.pod)
|
||||
|
||||
> [!CAUTION]
|
||||
> Version 0.1.3 introduced a [regression bug](https://github.com/TLINDEN/anydb/issues/19),
|
||||
> Between version 0.1.0 and version 0.2.1 deletion of keys did not work. There
|
||||
> is a unit test to check for this, but this unit test had a bug as well and
|
||||
> didn't catch it. The bug and the test have been fixed. You are advised to
|
||||
> upgrade to 0.2.1 and above.
|
||||
|
||||
> [!CAUTION]
|
||||
> Version 0.1.3 introduced a [regression](https://codeberg.org/scip/anydb/issues/19),
|
||||
> which caused the encryption feature not to work correctly anymore.
|
||||
> If you are using anydb 0.1.3, you are urgently advised to
|
||||
> upgrade to 0.2.0
|
||||
|
||||
|
||||
Anydb is a simple to use commandline tool to store anything you'd
|
||||
like, even binary files etc. It is a re-implementation of
|
||||
[skate](https://github.com/charmbracelet/skate) for the following
|
||||
@@ -40,17 +46,17 @@ And I wrote a very similar [tool](https://www.daemon.de/projects/dbtool/) 24 yea
|
||||
|
||||
**anydb** can do all the things you can do with skate:
|
||||
|
||||

|
||||

|
||||
|
||||
However, there are more features than just that!
|
||||
|
||||

|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
There are multiple ways to install **anydb**:
|
||||
|
||||
- Go to the [latest release page](https://github.com/tlinden/anydb/releases/latest),
|
||||
- Go to the [latest release page](https://codeberg.org/scip/anydb/releases),
|
||||
locate the binary for your operating system and platform.
|
||||
|
||||
Download it and put it into some directory within your `$PATH` variable.
|
||||
@@ -63,7 +69,7 @@ There are multiple ways to install **anydb**:
|
||||
|
||||
- You can also install from source. Issue the following commands in your shell:
|
||||
```shell
|
||||
git clone https://github.com/TLINDEN/anydb.git
|
||||
git clone https://codeberg.org/scip/anydb.git
|
||||
cd anydb
|
||||
make
|
||||
sudo make install
|
||||
@@ -71,7 +77,7 @@ There are multiple ways to install **anydb**:
|
||||
|
||||
- Or, if you have the GO toolkit installed, just install it like this:
|
||||
```shell
|
||||
go install github.com/tlinden/anydb@latest
|
||||
go install codeberg.org/scip/anydb@latest
|
||||
```
|
||||
|
||||
If you do not find a binary release for your platform, please don't
|
||||
@@ -98,14 +104,14 @@ Here, we operate in a local directory `mydb`, which we'll use as HOME
|
||||
inside the docker container. anydb will store its database in
|
||||
`mydb/.config/anydb/default.db`.
|
||||
|
||||
A list of available images is [here](https://github.com/tlinden/anydb/pkgs/container/anydb/versions?filters%5Bversion_type%5D=tagged)
|
||||
A list of available images is [here](https://codeberg.org/scip/anydb/pkgs/container/anydb/versions?filters%5Bversion_type%5D=tagged)
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
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://github.com/TLINDEN/anydb/blob/master/anydb.pod)
|
||||
[read the man-page online](https://codeberg.org/scip/anydb/blob/master/anydb.pod)
|
||||
|
||||
Or if you cloned the repository you can read it this way (perl needs
|
||||
to be installed though): `perldoc anydb.pod`.
|
||||
@@ -122,7 +128,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://github.com/TLINDEN/anydb/issues.
|
||||
https://codeberg.org/scip/anydb/issues.
|
||||
|
||||
## Copyright and license
|
||||
|
||||
@@ -134,7 +140,7 @@ T.v.Dein <tom AT vondein DOT org>
|
||||
|
||||
## Project homepage
|
||||
|
||||
https://github.com/TLINDEN/anydb
|
||||
https://codeberg.org/scip/anydb
|
||||
|
||||
## Copyright and License
|
||||
|
||||
|
||||
6
anydb.1
6
anydb.1
@@ -1,4 +1,4 @@
|
||||
.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42)
|
||||
.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40)
|
||||
.\"
|
||||
.\" Standard preamble:
|
||||
.\" ========================================================================
|
||||
@@ -133,7 +133,7 @@
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "ANYDB 1"
|
||||
.TH ANYDB 1 "2025-02-10" "1" "User Commands"
|
||||
.TH ANYDB 1 "2025-02-11" "1" "User Commands"
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.if n .ad l
|
||||
@@ -746,7 +746,7 @@ List all keys:
|
||||
.IX Header "BUGS"
|
||||
In order to report a bug, unexpected behavior, feature requests
|
||||
or to submit a patch, please open an issue on github:
|
||||
<https://github.com/TLINDEN/anydb/issues>.
|
||||
<https://codeberg.org/scip/anydb/issues>.
|
||||
.PP
|
||||
Please repeat the failing command with debugging enabled \f(CW\*(C`\-d\*(C'\fR and
|
||||
include the output in the issue.
|
||||
|
||||
@@ -583,7 +583,7 @@ List all keys:
|
||||
|
||||
In order to report a bug, unexpected behavior, feature requests
|
||||
or to submit a patch, please open an issue on github:
|
||||
L<https://github.com/TLINDEN/anydb/issues>.
|
||||
L<https://codeberg.org/scip/anydb/issues>.
|
||||
|
||||
Please repeat the failing command with debugging enabled C<-d> and
|
||||
include the output in the issue.
|
||||
|
||||
101
app/db.go
101
app/db.go
@@ -20,6 +20,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -27,6 +28,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
common "codeberg.org/scip/anydb/common"
|
||||
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"google.golang.org/protobuf/proto"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
@@ -60,15 +63,8 @@ type DbTag struct {
|
||||
Keys []string `json:"key"`
|
||||
}
|
||||
|
||||
// required for ui
|
||||
func (entry DbEntry) FilterValue() string {
|
||||
return entry.Preview
|
||||
}
|
||||
func (entry DbEntry) Description() string {
|
||||
return "Val: " + entry.Preview
|
||||
}
|
||||
func (entry DbEntry) Title() string {
|
||||
return "Key: " + entry.Key
|
||||
func (entry *DbEntry) Taglist() string {
|
||||
return strings.Join(entry.Tags, ",")
|
||||
}
|
||||
|
||||
const BucketData string = "data"
|
||||
@@ -104,7 +100,14 @@ func (db *DB) Open() error {
|
||||
}
|
||||
}
|
||||
|
||||
b, err := bolt.Open(db.Dbfile, 0600, nil)
|
||||
var opts *bolt.Options
|
||||
|
||||
if db.Debug {
|
||||
log := common.Slogger{Logger: slog.Default()}
|
||||
opts = &bolt.Options{Logger: log}
|
||||
}
|
||||
|
||||
b, err := bolt.Open(db.Dbfile, 0600, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open DB %s: %w", db.Dbfile, err)
|
||||
}
|
||||
@@ -113,8 +116,10 @@ func (db *DB) Open() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) Close() error {
|
||||
return db.DB.Close()
|
||||
func (db *DB) Close() {
|
||||
if err := db.DB.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (db *DB) List(attr *DbAttr, fulltext bool) (DbEntries, error) {
|
||||
@@ -233,48 +238,29 @@ func (db *DB) Set(attr *DbAttr) error {
|
||||
// check if the entry already exists and if yes, check if it has
|
||||
// any tags. if so, we initialize our update struct with these
|
||||
// tags unless it has new tags configured.
|
||||
// FIXME: use Get()
|
||||
err := db.DB.View(func(tx *bolt.Tx) error {
|
||||
root := tx.Bucket([]byte(db.Bucket))
|
||||
if root == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
bucket := root.Bucket([]byte("meta"))
|
||||
if bucket == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
slog.Debug("opened buckets", "root", root, "data", bucket)
|
||||
|
||||
pbentry := bucket.Get([]byte(entry.Key))
|
||||
if pbentry == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var oldentry DbEntry
|
||||
if err := proto.Unmarshal(pbentry, &oldentry); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal from protobuf: %w", err)
|
||||
slog.Debug("+++ GET")
|
||||
oldentry, err := db.txGet(attr)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "no such key") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if oldentry != nil {
|
||||
if len(oldentry.Tags) > 0 && len(entry.Tags) == 0 {
|
||||
// initialize update entry with tags from old entry
|
||||
entry.Tags = oldentry.Tags
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
slog.Debug("+++ MARSHAL")
|
||||
// marshall our data
|
||||
pbentry, err := proto.Marshal(&entry)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshall protobuf: %w", err)
|
||||
}
|
||||
|
||||
slog.Debug("+++ UPDATE")
|
||||
err = db.DB.Update(func(tx *bolt.Tx) error {
|
||||
// create root bucket
|
||||
root, err := tx.CreateBucketIfNotExists([]byte(db.Bucket))
|
||||
@@ -318,12 +304,10 @@ func (db *DB) Set(attr *DbAttr) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) Get(attr *DbAttr) (*DbEntry, error) {
|
||||
if err := db.Open(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// internal DB getter, assumes db.DB has already been
|
||||
// opened successfully. Do NOT call this w/o valid
|
||||
// DB handle!
|
||||
func (db *DB) txGet(attr *DbAttr) (*DbEntry, error) {
|
||||
entry := DbEntry{}
|
||||
|
||||
err := db.DB.View(func(tx *bolt.Tx) error {
|
||||
@@ -375,12 +359,27 @@ func (db *DB) Get(attr *DbAttr) (*DbEntry, error) {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read from DB: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &entry, nil
|
||||
}
|
||||
|
||||
func (db *DB) Get(attr *DbAttr) (*DbEntry, error) {
|
||||
if err := db.Open(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
entry, err := db.txGet(attr)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read from DB: %w", err)
|
||||
}
|
||||
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
func (db *DB) Del(attr *DbAttr) error {
|
||||
if err := db.Open(); err != nil {
|
||||
return err
|
||||
@@ -388,8 +387,14 @@ func (db *DB) Del(attr *DbAttr) error {
|
||||
defer db.Close()
|
||||
|
||||
err := db.DB.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket([]byte(db.Bucket))
|
||||
// root bucket
|
||||
root := tx.Bucket([]byte(db.Bucket))
|
||||
if root == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// get data sub bucket
|
||||
bucket := root.Bucket([]byte("meta"))
|
||||
if bucket == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.1
|
||||
// protoc v3.21.12
|
||||
// protoc-gen-go v1.36.5
|
||||
// protoc v4.24.4
|
||||
// source: app/dbentry.proto
|
||||
|
||||
package app
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -133,7 +134,7 @@ func (x *DbEntry) GetValue() string {
|
||||
|
||||
var File_app_dbentry_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_app_dbentry_proto_rawDesc = []byte{
|
||||
var file_app_dbentry_proto_rawDesc = string([]byte{
|
||||
0x0a, 0x11, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x12, 0x03, 0x61, 0x70, 0x70, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||
@@ -156,16 +157,16 @@ var file_app_dbentry_proto_rawDesc = []byte{
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x6c, 0x69, 0x6e, 0x64, 0x65,
|
||||
0x6e, 0x2f, 0x61, 0x6e, 0x79, 0x64, 0x62, 0x2f, 0x61, 0x70, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
}
|
||||
})
|
||||
|
||||
var (
|
||||
file_app_dbentry_proto_rawDescOnce sync.Once
|
||||
file_app_dbentry_proto_rawDescData = file_app_dbentry_proto_rawDesc
|
||||
file_app_dbentry_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_app_dbentry_proto_rawDescGZIP() []byte {
|
||||
file_app_dbentry_proto_rawDescOnce.Do(func() {
|
||||
file_app_dbentry_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_dbentry_proto_rawDescData)
|
||||
file_app_dbentry_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_dbentry_proto_rawDesc), len(file_app_dbentry_proto_rawDesc)))
|
||||
})
|
||||
return file_app_dbentry_proto_rawDescData
|
||||
}
|
||||
@@ -193,7 +194,7 @@ func file_app_dbentry_proto_init() {
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_app_dbentry_proto_rawDesc,
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_dbentry_proto_rawDesc), len(file_app_dbentry_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
@@ -204,7 +205,6 @@ func file_app_dbentry_proto_init() {
|
||||
MessageInfos: file_app_dbentry_proto_msgTypes,
|
||||
}.Build()
|
||||
File_app_dbentry_proto = out.File
|
||||
file_app_dbentry_proto_rawDesc = nil
|
||||
file_app_dbentry_proto_goTypes = nil
|
||||
file_app_dbentry_proto_depIdxs = nil
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ package app;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/tlinden/anydb/app";
|
||||
option go_package = "codeberg.org/scip/anydb/app";
|
||||
|
||||
message DbEntry {
|
||||
string Id = 1;
|
||||
|
||||
@@ -20,8 +20,7 @@ import "os"
|
||||
|
||||
func cleanError(file string, err error) error {
|
||||
// remove given [backup] file and forward the given error
|
||||
os.Remove(file)
|
||||
return err
|
||||
return os.Remove(file)
|
||||
}
|
||||
|
||||
func fileExists(filename string) bool {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright © 2024 Thomas von Dein
|
||||
Copyright © 2025 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
|
||||
@@ -22,11 +22,11 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/tlinden/anydb/app"
|
||||
"github.com/tlinden/anydb/common"
|
||||
"codeberg.org/scip/anydb/app"
|
||||
"codeberg.org/scip/anydb/common"
|
||||
)
|
||||
|
||||
var Version string = "v0.2.0"
|
||||
var Version string = "v0.2.6"
|
||||
|
||||
type BucketConfig struct {
|
||||
Encrypt bool
|
||||
|
||||
@@ -517,7 +517,7 @@ REST API
|
||||
BUGS
|
||||
In order to report a bug, unexpected behavior, feature requests or to
|
||||
submit a patch, please open an issue on github:
|
||||
<https://github.com/TLINDEN/anydb/issues>.
|
||||
<https://codeberg.org/scip/anydb/issues>.
|
||||
|
||||
Please repeat the failing command with debugging enabled "-d" and
|
||||
include the output in the issue.
|
||||
|
||||
@@ -22,9 +22,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/tlinden/anydb/app"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
"github.com/tlinden/anydb/output"
|
||||
"codeberg.org/scip/anydb/app"
|
||||
"codeberg.org/scip/anydb/cfg"
|
||||
"codeberg.org/scip/anydb/output"
|
||||
)
|
||||
|
||||
func Set(conf *cfg.Config) *cobra.Command {
|
||||
@@ -156,7 +156,7 @@ func Del(conf *cfg.Config) *cobra.Command {
|
||||
Long: `Delete key and value matching key`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("No key specified")
|
||||
return errors.New("no key specified")
|
||||
}
|
||||
|
||||
// errors at this stage do not cause the usage to be shown
|
||||
|
||||
51
cmd/extra.go
51
cmd/extra.go
@@ -21,16 +21,15 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/tlinden/anydb/app"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
"github.com/tlinden/anydb/output"
|
||||
"github.com/tlinden/anydb/rest"
|
||||
"github.com/tlinden/anydb/ui"
|
||||
"codeberg.org/scip/anydb/app"
|
||||
"codeberg.org/scip/anydb/cfg"
|
||||
"codeberg.org/scip/anydb/output"
|
||||
"codeberg.org/scip/anydb/rest"
|
||||
)
|
||||
|
||||
func Export(conf *cfg.Config) *cobra.Command {
|
||||
@@ -287,7 +286,11 @@ func editContent(editor string, content string) (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create templ file: %w", err)
|
||||
}
|
||||
defer os.Remove(tmp.Name())
|
||||
defer func() {
|
||||
if err := os.Remove(tmp.Name()); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
// put the content into a tmp file
|
||||
_, err = tmp.WriteString(content)
|
||||
@@ -312,7 +315,11 @@ func editContent(editor string, content string) (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to open temp file: %w", err)
|
||||
}
|
||||
defer modified.Close()
|
||||
defer func() {
|
||||
if err := modified.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
newcontent, err := io.ReadAll(modified)
|
||||
if err != nil {
|
||||
@@ -326,31 +333,3 @@ func editContent(editor string, content string) (string, error) {
|
||||
|
||||
return newcontentstr, nil
|
||||
}
|
||||
|
||||
func Shell(conf *cfg.Config) *cobra.Command {
|
||||
var cmd = &cobra.Command{
|
||||
Use: "shell",
|
||||
Short: "shell",
|
||||
Long: `interactive ui`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// errors at this stage do not cause the usage to be shown
|
||||
cmd.SilenceUsage = true
|
||||
|
||||
entries, err := conf.DB.List(&app.DbAttr{}, conf.Fulltext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := tea.NewProgram(ui.NewModel(conf, entries), tea.WithAltScreen())
|
||||
if _, err := p.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().BoolVarP(&conf.NoHumanize, "no-human", "N", false, "do not translate to human readable values")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
22
cmd/root.go
22
cmd/root.go
@@ -24,10 +24,9 @@ import (
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
|
||||
slogmulti "github.com/samber/slog-multi"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/tlinden/anydb/app"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
"codeberg.org/scip/anydb/app"
|
||||
"codeberg.org/scip/anydb/cfg"
|
||||
"github.com/tlinden/yadu"
|
||||
)
|
||||
|
||||
@@ -91,25 +90,13 @@ func Execute() {
|
||||
|
||||
slog.SetLogLoggerLevel(slog.LevelDebug)
|
||||
|
||||
dbg, err := os.Create("debug.log")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// FIXME: control this with a flag!
|
||||
//outhandler := yadu.NewHandler(os.Stdout, opts)
|
||||
filehandler := yadu.NewHandler(dbg, opts)
|
||||
|
||||
debuglogger := slog.New(slogmulti.Fanout(
|
||||
//outhandler,
|
||||
filehandler,
|
||||
)).With(
|
||||
handler := yadu.NewHandler(os.Stdout, opts)
|
||||
debuglogger := slog.New(handler).With(
|
||||
slog.Group("program_info",
|
||||
slog.Int("pid", os.Getpid()),
|
||||
slog.String("go_version", buildInfo.GoVersion),
|
||||
),
|
||||
)
|
||||
|
||||
slog.SetDefault(debuglogger)
|
||||
|
||||
slog.Debug("parsed config", "conf", conf)
|
||||
@@ -170,7 +157,6 @@ func Execute() {
|
||||
rootCmd.AddCommand(Man(&conf))
|
||||
rootCmd.AddCommand(Info(&conf))
|
||||
rootCmd.AddCommand(Edit(&conf))
|
||||
rootCmd.AddCommand(Shell(&conf))
|
||||
|
||||
err = rootCmd.Execute()
|
||||
if err != nil {
|
||||
|
||||
@@ -20,8 +20,7 @@ import "os"
|
||||
|
||||
func CleanError(file string, err error) error {
|
||||
// remove given [backup] file and forward the given error
|
||||
os.Remove(file)
|
||||
return err
|
||||
return os.Remove(file)
|
||||
}
|
||||
|
||||
func FileExists(filename string) bool {
|
||||
|
||||
23
common/logger.go
Normal file
23
common/logger.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type Slogger struct {
|
||||
*slog.Logger
|
||||
}
|
||||
|
||||
func (l Slogger) Debug(v ...interface{}) {}
|
||||
func (l Slogger) Debugf(format string, v ...interface{}) { l.Logger.Debug(fmt.Sprintf(format, v...)) }
|
||||
func (l Slogger) Error(v ...interface{}) {}
|
||||
func (l Slogger) Errorf(format string, v ...interface{}) { l.Logger.Error(fmt.Sprintf(format, v...)) }
|
||||
func (l Slogger) Info(v ...interface{}) {}
|
||||
func (l Slogger) Infof(format string, v ...interface{}) { l.Logger.Info(fmt.Sprintf(format, v...)) }
|
||||
func (l Slogger) Warning(v ...interface{}) {}
|
||||
func (l Slogger) Warningf(format string, v ...interface{}) { l.Logger.Warn(fmt.Sprintf(format, v...)) }
|
||||
func (l Slogger) Fatal(v ...interface{}) {}
|
||||
func (l Slogger) Fatalf(format string, v ...interface{}) { l.Logger.Error(fmt.Sprintf(format, v...)) }
|
||||
func (l Slogger) Panic(v ...interface{}) {}
|
||||
func (l Slogger) Panicf(format string, v ...interface{}) { l.Logger.Error(fmt.Sprintf(format, v...)) }
|
||||
95
contrib/anydbui
Executable file
95
contrib/anydbui
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/sh
|
||||
|
||||
template="{{.Key}} {{.Created.AsTime.Year}}-{{.Created.AsTime.Month}}-{{.Created.AsTime.Day}} {{.Taglist}} {{.Preview}}"
|
||||
header="TITLE DATE TAGS PREVIEW"
|
||||
|
||||
# its possible to use another version of anydb for testing purposes
|
||||
anydb="${ANYDB:-anydb}"
|
||||
|
||||
# list command
|
||||
command="( echo '$header'; $anydb ls -m template --template '$template' ) | column -t -l4"
|
||||
|
||||
for binary in fzf $anydb column diff awk less; do
|
||||
if ! type $binary > /dev/null 2>&1; then
|
||||
echo "$binary is not installed!"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if type gum > /dev/null 2>&1; then
|
||||
GUM=1
|
||||
fi
|
||||
|
||||
_rand() {
|
||||
awk 'BEGIN {srand(); printf( "%d\n", 1024 * rand() )}'
|
||||
}
|
||||
|
||||
_list() {
|
||||
(
|
||||
echo "$header"
|
||||
$anydb ls -m template --template "$template"
|
||||
) | column -t -l4
|
||||
}
|
||||
|
||||
_updater() {
|
||||
_port="$1"
|
||||
_cache="/tmp/anydbcache.$port"
|
||||
_current="/tmp/anydbcache.$port.current"
|
||||
|
||||
touch $_current $_cache
|
||||
|
||||
while :; do
|
||||
sleep 10
|
||||
|
||||
_list > $_current
|
||||
|
||||
if ! diff -q $_current $_cache > /dev/null 2>&1; then
|
||||
curl -d "reload($command)+clear-screen" "http://127.0.0.1:$_port"
|
||||
fi
|
||||
cp $_current $_cache
|
||||
done
|
||||
}
|
||||
|
||||
_cleanup() {
|
||||
# get rid of the update child
|
||||
kill $pid
|
||||
|
||||
# clean up reloader cache
|
||||
rm -f /tmp/anydbcache.${port}*
|
||||
}
|
||||
|
||||
|
||||
|
||||
# fork background updater
|
||||
port=$((8000 + $(_rand) % 1000))
|
||||
_updater $port &
|
||||
pid=$!
|
||||
|
||||
db=$($anydb info | grep Database | cut -d: -f2)
|
||||
shorthelp="$db - [enter]read [c-e]edit [c-k]kill [c-c]exit [c-k]delete"
|
||||
|
||||
if test -n "$GUM"; then
|
||||
color="Color \"#ff\" \"#0000ff\"" # white on blue
|
||||
db="{{ $color \"Database:\"}}$db"
|
||||
enter="{{ $color \"[Enter]\"}} Read"
|
||||
edit="{{ $color \"[ctrl-c]\"}} Edit"
|
||||
delete="{{ $color \"[ctrl-k]\"}} Delete"
|
||||
template="$db $enter $edit $delete"
|
||||
shorthelp=$(echo "$template" | gum format -t template)
|
||||
fi
|
||||
|
||||
trap '_cleanup; (exit $?); exit' INT TERM EXIT
|
||||
|
||||
: | command="$command" fzf \
|
||||
--bind "start:reload:$command" \
|
||||
--header-lines 1 --layout=reverse --info=inline \
|
||||
--height 100% --pointer="→" --separator="─" \
|
||||
--scrollbar="│" --preview-window "right:50%" \
|
||||
--border-label="$shorthelp" \
|
||||
--border=bottom --layout=reverse --info=inline \
|
||||
--height 100% --header-first --cycle --header-lines=1 --listen=$port \
|
||||
--bind "enter:execute: clear; $anydb get {1} | less" \
|
||||
--bind "ctrl-e:execute: $anydb edit {1}" \
|
||||
--bind "ctrl-k:execute:$anydb del {1}"
|
||||
|
||||
|
||||
@@ -177,6 +177,6 @@ Enter
|
||||
Sleep 3s
|
||||
|
||||
Enter
|
||||
Type "# Try it out yourself: github.com/tlinden/anydb!"
|
||||
Type "# Try it out yourself: codeberg.org/scip/anydb!"
|
||||
Enter
|
||||
Sleep 4s
|
||||
|
||||
55
go.mod
55
go.mod
@@ -1,59 +1,40 @@
|
||||
module github.com/tlinden/anydb
|
||||
module codeberg.org/scip/anydb
|
||||
|
||||
go 1.23
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.23.5
|
||||
toolchain go1.24.1
|
||||
|
||||
require (
|
||||
github.com/alecthomas/repr v0.4.0
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/gofiber/fiber/v2 v2.52.6
|
||||
github.com/gofiber/fiber/v2 v2.52.9
|
||||
github.com/inconshreveable/mousetrap v1.1.0
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/olekukonko/tablewriter v1.1.0
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/rogpeppe/go-internal v1.13.1
|
||||
github.com/spf13/cobra v1.8.1
|
||||
go.etcd.io/bbolt v1.4.0
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/term v0.27.0
|
||||
google.golang.org/protobuf v1.36.5
|
||||
github.com/rogpeppe/go-internal v1.14.1
|
||||
github.com/spf13/cobra v1.10.1
|
||||
github.com/tlinden/yadu v0.1.3
|
||||
go.etcd.io/bbolt v1.4.3
|
||||
golang.org/x/crypto v0.42.0
|
||||
golang.org/x/term v0.35.0
|
||||
google.golang.org/protobuf v1.36.9
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/charmbracelet/bubbles v0.20.0 // indirect
|
||||
github.com/charmbracelet/bubbletea v1.3.3 // indirect
|
||||
github.com/charmbracelet/lipgloss v1.0.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.8.0 // indirect
|
||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/gofiber/fiber/v3 v3.0.0-beta.3 // indirect
|
||||
github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // 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.15.2 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/sahilm/fuzzy v0.1.1 // indirect
|
||||
github.com/samber/lo v1.49.1 // indirect
|
||||
github.com/samber/slog-multi v1.4.0 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/tlinden/yadu v0.1.3 // indirect
|
||||
github.com/olekukonko/errors v1.1.0 // indirect
|
||||
github.com/olekukonko/ll v0.0.9 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/spf13/pflag v1.0.9 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.55.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
golang.org/x/sys v0.36.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
162
go.sum
162
go.sum
@@ -1,163 +1,75 @@
|
||||
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/Sereal/Sereal v0.0.0-20190618215532-0b8ac451a863/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
|
||||
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
|
||||
github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac=
|
||||
github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0=
|
||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
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.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
|
||||
github.com/charmbracelet/bubbletea v1.3.3 h1:WpU6fCY0J2vDWM3zfS3vIDi/ULq3SYphZhkAGGvmEUY=
|
||||
github.com/charmbracelet/bubbletea v1.3.3/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo=
|
||||
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
|
||||
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
|
||||
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
|
||||
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
|
||||
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
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/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
|
||||
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
|
||||
github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
|
||||
github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||
github.com/gofiber/fiber/v3 v3.0.0-beta.3 h1:7Q2I+HsIqnIEEDB+9oe7Gadpakh6ZLhXpTYz/L20vrg=
|
||||
github.com/gofiber/fiber/v3 v3.0.0-beta.3/go.mod h1:kcMur0Dxqk91R7p4vxEpJfDWZ9u5IfvrtQc8Bvv/JmY=
|
||||
github.com/gofiber/utils/v2 v2.0.0-beta.4 h1:1gjbVFFwVwUb9arPcqiB6iEjHBwo7cHsyS41NeIW3co=
|
||||
github.com/gofiber/utils/v2 v2.0.0-beta.4/go.mod h1:sdRsPU1FXX6YiDGGxd+q2aPJRMzpsxdzCXo9dz+xtOY=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gofiber/fiber/v2 v2.52.9 h1:YjKl5DOiyP3j0mO61u3NTmK7or8GzzWzCFzkboyP5cw=
|
||||
github.com/gofiber/fiber/v2 v2.52.9/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
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-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
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.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
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.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
|
||||
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
|
||||
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
|
||||
github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY=
|
||||
github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
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.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
|
||||
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
|
||||
github.com/samber/slog-multi v1.4.0 h1:pwlPMIE7PrbTHQyKWDU+RIoxP1+HKTNOujk3/kdkbdg=
|
||||
github.com/samber/slog-multi v1.4.0/go.mod h1:FsQ4Uv2L+E/8TZt+/BVgYZ1LoDWCbfCU21wVIoMMrO8=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
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/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
|
||||
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
|
||||
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tlinden/yadu v0.1.3 h1:5cRCUmj+l5yvlM2irtpFBIJwVV2DPEgYSaWvF19FtcY=
|
||||
github.com/tlinden/yadu v0.1.3/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
|
||||
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
||||
github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
|
||||
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
|
||||
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
|
||||
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
|
||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
||||
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
||||
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=
|
||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
4
main.go
4
main.go
@@ -24,7 +24,7 @@ import (
|
||||
"runtime"
|
||||
|
||||
"github.com/inconshreveable/mousetrap"
|
||||
"github.com/tlinden/anydb/cmd"
|
||||
"codeberg.org/scip/anydb/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -41,7 +41,7 @@ func init() {
|
||||
// thus give the user time to read it.
|
||||
if runtime.GOOS == "windows" {
|
||||
if mousetrap.StartedByExplorer() {
|
||||
fmt.Println("Do no double click kleingebaeck.exe!")
|
||||
fmt.Println("Do no double click anydb.exe!")
|
||||
fmt.Println("Please open a command shell and run it from there.")
|
||||
fmt.Println()
|
||||
fmt.Print("Press any key to quit: ")
|
||||
|
||||
@@ -17,16 +17,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rogpeppe/go-internal/testscript"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(testscript.RunMain(m, map[string]func() int{
|
||||
"anydb": Main,
|
||||
}))
|
||||
testscript.Main(m, map[string]func(){
|
||||
"anydb": main,
|
||||
})
|
||||
}
|
||||
|
||||
func TestAnydb(t *testing.T) {
|
||||
|
||||
9
mkrel.sh
9
mkrel.sh
@@ -52,8 +52,15 @@ for D in $DIST; do
|
||||
|
||||
tardir="${tool}-${os}-${arch}-${version}"
|
||||
tarfile="releases/${tool}-${os}-${arch}-${version}.tar.gz"
|
||||
|
||||
if test "$D" = "linux/amd64"; then
|
||||
pie="-buildmode=pie"
|
||||
fi
|
||||
|
||||
set -x
|
||||
GOOS=${os} GOARCH=${arch} go build -tags osusergo,netgo -ldflags "-extldflags=-static" -o ${binfile}
|
||||
GOOS=${os} GOARCH=${arch} go build -tags osusergo,netgo -ldflags "-extldflags=-static -w" --trimpath $pie -o ${binfile}
|
||||
strip --strip-all ${binfile}
|
||||
|
||||
mkdir -p ${tardir}
|
||||
cp ${binfile} README.md LICENSE ${tardir}/
|
||||
echo 'tool = anydb
|
||||
|
||||
@@ -21,8 +21,8 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/tlinden/anydb/app"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
"codeberg.org/scip/anydb/app"
|
||||
"codeberg.org/scip/anydb/cfg"
|
||||
)
|
||||
|
||||
func WriteJSON(attr *app.DbAttr, conf *cfg.Config, entries app.DbEntries) error {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright © 2024 Thomas von Dein
|
||||
Copyright © 2025 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
|
||||
@@ -28,8 +28,10 @@ import (
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/tlinden/anydb/app"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
"github.com/olekukonko/tablewriter/renderer"
|
||||
"github.com/olekukonko/tablewriter/tw"
|
||||
"codeberg.org/scip/anydb/app"
|
||||
"codeberg.org/scip/anydb/cfg"
|
||||
)
|
||||
|
||||
func List(writer io.Writer, conf *cfg.Config, entries app.DbEntries) error {
|
||||
@@ -71,7 +73,9 @@ func ListTemplate(writer io.Writer, conf *cfg.Config, entries app.DbEntries) err
|
||||
}
|
||||
|
||||
if buf.Len() > 0 {
|
||||
fmt.Fprintln(writer, buf.String())
|
||||
if _, err := fmt.Fprintln(writer, buf.String()); err != nil {
|
||||
return fmt.Errorf("failed to write output: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,13 +84,46 @@ func ListTemplate(writer io.Writer, conf *cfg.Config, entries app.DbEntries) err
|
||||
|
||||
func ListTable(writer io.Writer, conf *cfg.Config, entries app.DbEntries) error {
|
||||
tableString := &strings.Builder{}
|
||||
table := tablewriter.NewWriter(tableString)
|
||||
|
||||
styleTSV := tw.NewSymbolCustom("space").WithColumn("\t")
|
||||
|
||||
table := tablewriter.NewTable(tableString,
|
||||
tablewriter.WithRenderer(
|
||||
renderer.NewBlueprint(tw.Rendition{
|
||||
Borders: tw.BorderNone,
|
||||
Symbols: styleTSV,
|
||||
Settings: tw.Settings{
|
||||
Separators: tw.Separators{BetweenRows: tw.Off, BetweenColumns: tw.On},
|
||||
Lines: tw.Lines{ShowFooterLine: tw.Off, ShowHeaderLine: tw.Off},
|
||||
},
|
||||
})),
|
||||
tablewriter.WithConfig(tablewriter.Config{
|
||||
Header: tw.CellConfig{
|
||||
Formatting: tw.CellFormatting{
|
||||
AutoFormat: tw.Off,
|
||||
},
|
||||
Padding: tw.CellPadding{
|
||||
Global: tw.Padding{Left: "", Right: ""},
|
||||
},
|
||||
},
|
||||
Row: tw.CellConfig{
|
||||
Formatting: tw.CellFormatting{
|
||||
AutoWrap: tw.WrapNone,
|
||||
Alignment: tw.AlignLeft,
|
||||
},
|
||||
Padding: tw.CellPadding{
|
||||
Global: tw.Padding{Left: "", Right: ""},
|
||||
},
|
||||
},
|
||||
}),
|
||||
tablewriter.WithPadding(tw.PaddingNone),
|
||||
)
|
||||
|
||||
if !conf.NoHeaders {
|
||||
if conf.Mode == "wide" {
|
||||
table.SetHeader([]string{"KEY", "TAGS", "SIZE", "UPDATED", "VALUE"})
|
||||
table.Header([]string{"KEY", "TAGS", "SIZE", "UPDATED", "VALUE"})
|
||||
} else {
|
||||
table.SetHeader([]string{"KEY", "VALUE"})
|
||||
table.Header([]string{"KEY", "VALUE"})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,44 +131,42 @@ func ListTable(writer io.Writer, conf *cfg.Config, entries app.DbEntries) error
|
||||
if conf.Mode == "wide" {
|
||||
switch conf.NoHumanize {
|
||||
case true:
|
||||
table.Append([]string{
|
||||
row.Key,
|
||||
strings.Join(row.Tags, ","),
|
||||
strconv.FormatUint(row.Size, 10),
|
||||
row.Created.AsTime().Format("02.01.2006T03:04.05"),
|
||||
row.Preview,
|
||||
})
|
||||
if err :=
|
||||
table.Append([]string{
|
||||
row.Key,
|
||||
strings.Join(row.Tags, ","),
|
||||
strconv.FormatUint(row.Size, 10),
|
||||
row.Created.AsTime().Format("02.01.2006T03:04.05"),
|
||||
row.Preview,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to add data to table: %w", err)
|
||||
}
|
||||
default:
|
||||
table.Append([]string{
|
||||
if err := table.Append([]string{
|
||||
row.Key,
|
||||
strings.Join(row.Tags, ","),
|
||||
humanize.Bytes(uint64(row.Size)),
|
||||
humanize.Time(row.Created.AsTime()),
|
||||
row.Preview,
|
||||
})
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to add data to table: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
table.Append([]string{row.Key, row.Preview})
|
||||
if err := table.Append([]string{row.Key, row.Preview}); err != nil {
|
||||
return fmt.Errorf("failed to add data to table: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
|
||||
table.SetAutoWrapText(false)
|
||||
table.SetAutoFormatHeaders(true)
|
||||
table.SetAlignment(tablewriter.ALIGN_LEFT)
|
||||
table.SetCenterSeparator("")
|
||||
table.SetColumnSeparator("")
|
||||
table.SetRowSeparator("")
|
||||
table.SetHeaderLine(false)
|
||||
table.SetBorder(false)
|
||||
table.SetNoWhiteSpace(true)
|
||||
if err := table.Render(); err != nil {
|
||||
return fmt.Errorf("failed to render table: %w", err)
|
||||
}
|
||||
|
||||
table.SetTablePadding("\t") // pad with tabs
|
||||
|
||||
table.Render()
|
||||
|
||||
fmt.Fprint(writer, tableString.String())
|
||||
if _, err := fmt.Fprint(writer, tableString.String()); err != nil {
|
||||
return fmt.Errorf("failed to write output: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,12 +20,13 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/tlinden/anydb/app"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
"codeberg.org/scip/anydb/app"
|
||||
"codeberg.org/scip/anydb/cfg"
|
||||
"golang.org/x/term"
|
||||
//"github.com/alecthomas/repr"
|
||||
)
|
||||
@@ -43,7 +44,9 @@ func Print(writer io.Writer, conf *cfg.Config, attr *app.DbAttr, entry *app.DbEn
|
||||
if isatty {
|
||||
fmt.Println("binary data omitted")
|
||||
} else {
|
||||
os.Stdout.WriteString(entry.Value)
|
||||
if _, err := os.Stdout.WriteString(entry.Value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fmt.Print(string(entry.Value))
|
||||
@@ -79,7 +82,11 @@ func WriteFile(writer io.Writer, conf *cfg.Config, attr *app.DbAttr, entry *app.
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open file %s for writing: %w", attr.File, err)
|
||||
}
|
||||
defer fd.Close()
|
||||
defer func() {
|
||||
if err := fd.Close(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
fileHandle = fd
|
||||
}
|
||||
@@ -102,34 +109,45 @@ func WriteFile(writer io.Writer, conf *cfg.Config, attr *app.DbAttr, entry *app.
|
||||
}
|
||||
|
||||
func Info(writer io.Writer, conf *cfg.Config, info *app.DbInfo) error {
|
||||
fmt.Fprintf(writer, "Database: %s\n", info.Path)
|
||||
if _, err := fmt.Fprintf(writer, "Database: %s\n", info.Path); err != nil {
|
||||
return fmt.Errorf("failed to write output: %w", err)
|
||||
}
|
||||
|
||||
for _, bucket := range info.Buckets {
|
||||
if conf.NoHumanize {
|
||||
fmt.Fprintf(
|
||||
if _, err := fmt.Fprintf(
|
||||
writer,
|
||||
"%19s: %s\n%19s: %d\n%19s: %d\n%19s: %t\n",
|
||||
"Bucket", bucket.Name,
|
||||
"Size", bucket.Size,
|
||||
"Keys", bucket.Keys,
|
||||
"Encrypted", conf.Encrypt)
|
||||
"Encrypted", conf.Encrypt); err != nil {
|
||||
return fmt.Errorf("failed to write output: %w", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(
|
||||
if _, err := fmt.Fprintf(
|
||||
writer,
|
||||
"%19s: %s\n%19s: %s\n%19s: %d\n",
|
||||
"Bucket", bucket.Name,
|
||||
"Size", humanize.Bytes(uint64(bucket.Size)),
|
||||
"Keys", bucket.Keys)
|
||||
"Keys", bucket.Keys); err != nil {
|
||||
return fmt.Errorf("failed to write output: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if conf.Debug {
|
||||
val := reflect.ValueOf(&bucket.Stats).Elem()
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
fmt.Fprintf(writer, "%19s: %v\n", val.Type().Field(i).Name, val.Field(i))
|
||||
if _, err := fmt.Fprintf(writer, "%19s: %v\n", val.Type().Field(i).Name, val.Field(i)); err != nil {
|
||||
return fmt.Errorf("failed to write output: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintln(writer)
|
||||
if _, err := fmt.Fprintln(writer); err != nil {
|
||||
return fmt.Errorf("failed to write output: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ import (
|
||||
//"github.com/alecthomas/repr"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/tlinden/anydb/app"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
"codeberg.org/scip/anydb/app"
|
||||
"codeberg.org/scip/anydb/cfg"
|
||||
)
|
||||
|
||||
type SetContext struct {
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"github.com/gofiber/fiber/v2/middleware/compress"
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
"codeberg.org/scip/anydb/cfg"
|
||||
)
|
||||
|
||||
// used to return to the api client
|
||||
@@ -104,11 +104,7 @@ Wrapper to respond with proper json status, message and code,
|
||||
shall be prepared and called by the handlers directly.
|
||||
*/
|
||||
func JsonStatus(c *fiber.Ctx, code int, msg string) error {
|
||||
success := true
|
||||
|
||||
if code != fiber.StatusOK {
|
||||
success = false
|
||||
}
|
||||
success := code == fiber.StatusOK
|
||||
|
||||
return c.Status(code).JSON(Result{
|
||||
Code: code,
|
||||
|
||||
@@ -78,4 +78,4 @@ exec anydb -f test.db del foo
|
||||
|
||||
# check deleted
|
||||
exec anydb -f test.db list
|
||||
! stdout bar
|
||||
! stdout blah
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"log"
|
||||
"log/slog"
|
||||
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/list"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/tlinden/anydb/app"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
)
|
||||
|
||||
func newItemDelegate(keys *delegateKeyMap, config *cfg.Config) list.DefaultDelegate {
|
||||
d := list.NewDefaultDelegate()
|
||||
|
||||
d.UpdateFunc = func(msg tea.Msg, m *list.Model) tea.Cmd {
|
||||
var title string
|
||||
|
||||
if entry, ok := m.SelectedItem().(item); ok {
|
||||
title = entry.Title()
|
||||
slog.Debug("active entry", "entry", title)
|
||||
} else {
|
||||
slog.Debug("no active entry")
|
||||
return nil
|
||||
}
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch {
|
||||
case key.Matches(msg, keys.choose):
|
||||
return m.NewStatusMessage(statusMessageStyle("You chose " + title))
|
||||
|
||||
case key.Matches(msg, keys.remove):
|
||||
if err := config.DB.Del(&app.DbAttr{Key: title}); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
index := m.Index()
|
||||
m.RemoveItem(index)
|
||||
if len(m.Items()) == 0 {
|
||||
keys.remove.SetEnabled(false)
|
||||
}
|
||||
return m.NewStatusMessage(statusMessageStyle("Deleted " + title))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
help := []key.Binding{keys.choose, keys.remove}
|
||||
|
||||
d.ShortHelpFunc = func() []key.Binding {
|
||||
return help
|
||||
}
|
||||
|
||||
d.FullHelpFunc = func() [][]key.Binding {
|
||||
return [][]key.Binding{help}
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
type delegateKeyMap struct {
|
||||
choose key.Binding
|
||||
remove key.Binding
|
||||
}
|
||||
|
||||
// Additional short help entries. This satisfies the help.KeyMap interface and
|
||||
// is entirely optional.
|
||||
func (d delegateKeyMap) ShortHelp() []key.Binding {
|
||||
return []key.Binding{
|
||||
d.choose,
|
||||
d.remove,
|
||||
}
|
||||
}
|
||||
|
||||
// Additional full help entries. This satisfies the help.KeyMap interface and
|
||||
// is entirely optional.
|
||||
func (d delegateKeyMap) FullHelp() [][]key.Binding {
|
||||
return [][]key.Binding{
|
||||
{
|
||||
d.choose,
|
||||
d.remove,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDelegateKeyMap() *delegateKeyMap {
|
||||
return &delegateKeyMap{
|
||||
choose: key.NewBinding(
|
||||
key.WithKeys("enter"),
|
||||
key.WithHelp("enter", "choose"),
|
||||
),
|
||||
remove: key.NewBinding(
|
||||
key.WithKeys("x", "backspace"),
|
||||
key.WithHelp("x", "delete"),
|
||||
),
|
||||
}
|
||||
}
|
||||
95
ui/root.bak
95
ui/root.bak
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
Copyright © 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 ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/spinner"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
)
|
||||
|
||||
type model struct {
|
||||
spinner spinner.Model
|
||||
conf *cfg.Config
|
||||
quitting bool
|
||||
err error
|
||||
}
|
||||
|
||||
var quitKeys = key.NewBinding(
|
||||
key.WithKeys("q", "esc", "ctrl+c"),
|
||||
key.WithHelp("", "press q to quit"),
|
||||
)
|
||||
|
||||
var (
|
||||
appStyle = lipgloss.NewStyle().Padding(1, 2)
|
||||
|
||||
titleStyle = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color("#FFFDF5")).
|
||||
Background(lipgloss.Color("#25A065")).
|
||||
Padding(0, 1)
|
||||
|
||||
statusMessageStyle = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.AdaptiveColor{Light: "#04B575", Dark: "#04B575"}).
|
||||
Render
|
||||
)
|
||||
|
||||
func InitialModel(conf *cfg.Config) model {
|
||||
s := spinner.New()
|
||||
s.Spinner = spinner.Dot
|
||||
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
|
||||
return model{spinner: s, conf: conf}
|
||||
}
|
||||
|
||||
func (m model) Init() tea.Cmd {
|
||||
return m.spinner.Tick
|
||||
}
|
||||
|
||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
|
||||
case tea.KeyMsg:
|
||||
if key.Matches(msg, quitKeys) {
|
||||
m.quitting = true
|
||||
return m, tea.Quit
|
||||
|
||||
}
|
||||
return m, nil
|
||||
case error:
|
||||
m.err = msg
|
||||
return m, nil
|
||||
|
||||
default:
|
||||
var cmd tea.Cmd
|
||||
m.spinner, cmd = m.spinner.Update(msg)
|
||||
return m, cmd
|
||||
}
|
||||
}
|
||||
|
||||
func (m model) View() string {
|
||||
if m.err != nil {
|
||||
return m.err.Error()
|
||||
}
|
||||
str := fmt.Sprintf("\n\n %s Loading forever... %s\n\n", m.spinner.View(), quitKeys.Help().Desc)
|
||||
if m.quitting {
|
||||
return str + "\n"
|
||||
}
|
||||
return str
|
||||
}
|
||||
213
ui/root.go
213
ui/root.go
@@ -1,213 +0,0 @@
|
||||
/*
|
||||
Copyright © 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 ui
|
||||
|
||||
import (
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/list"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/tlinden/anydb/app"
|
||||
"github.com/tlinden/anydb/cfg"
|
||||
)
|
||||
|
||||
var (
|
||||
appStyle = lipgloss.NewStyle().Padding(1, 2)
|
||||
|
||||
titleStyle = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color("#FFFDF5")).
|
||||
Background(lipgloss.Color("#25A065")).
|
||||
Padding(0, 1)
|
||||
|
||||
statusMessageStyle = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.AdaptiveColor{Light: "#04B575", Dark: "#04B575"}).
|
||||
Render
|
||||
)
|
||||
|
||||
type Loader struct {
|
||||
items []list.Item
|
||||
conf *cfg.Config
|
||||
}
|
||||
|
||||
func (loader *Loader) Update() error {
|
||||
entries, err := loader.conf.DB.List(&app.DbAttr{}, loader.conf.Fulltext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loader.items = nil
|
||||
|
||||
for _, entry := range entries {
|
||||
loader.items = append(loader.items, item{
|
||||
title: entry.Key,
|
||||
description: entry.Preview,
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type model struct {
|
||||
conf *cfg.Config
|
||||
loader *Loader
|
||||
quitting bool
|
||||
err error
|
||||
list list.Model
|
||||
keys *listKeyMap
|
||||
delegateKeys *delegateKeyMap
|
||||
}
|
||||
|
||||
type listKeyMap struct {
|
||||
toggleSpinner key.Binding
|
||||
toggleTitleBar key.Binding
|
||||
toggleStatusBar key.Binding
|
||||
togglePagination key.Binding
|
||||
toggleHelpMenu key.Binding
|
||||
insertItem key.Binding
|
||||
}
|
||||
|
||||
type item struct {
|
||||
title string
|
||||
description string
|
||||
}
|
||||
|
||||
func (i item) Title() string { return i.title }
|
||||
func (i item) Description() string { return i.description }
|
||||
func (i item) FilterValue() string { return i.title }
|
||||
|
||||
func newListKeyMap() *listKeyMap {
|
||||
return &listKeyMap{
|
||||
insertItem: key.NewBinding(
|
||||
key.WithKeys("a"),
|
||||
key.WithHelp("a", "add item"),
|
||||
),
|
||||
toggleSpinner: key.NewBinding(
|
||||
key.WithKeys("s"),
|
||||
key.WithHelp("s", "toggle spinner"),
|
||||
),
|
||||
toggleTitleBar: key.NewBinding(
|
||||
key.WithKeys("T"),
|
||||
key.WithHelp("T", "toggle title"),
|
||||
),
|
||||
toggleStatusBar: key.NewBinding(
|
||||
key.WithKeys("S"),
|
||||
key.WithHelp("S", "toggle status"),
|
||||
),
|
||||
togglePagination: key.NewBinding(
|
||||
key.WithKeys("P"),
|
||||
key.WithHelp("P", "toggle pagination"),
|
||||
),
|
||||
toggleHelpMenu: key.NewBinding(
|
||||
key.WithKeys("H"),
|
||||
key.WithHelp("H", "toggle help"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func NewModel(config *cfg.Config, entries app.DbEntries) model {
|
||||
var (
|
||||
delegateKeys = newDelegateKeyMap()
|
||||
listKeys = newListKeyMap()
|
||||
loader = Loader{conf: config}
|
||||
)
|
||||
|
||||
// Setup list
|
||||
if err := loader.Update(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
delegate := newItemDelegate(delegateKeys, config)
|
||||
dbList := list.New(loader.items, delegate, 0, 0)
|
||||
dbList.Title = "DB Entries"
|
||||
dbList.Styles.Title = titleStyle
|
||||
|
||||
dbList.AdditionalFullHelpKeys = func() []key.Binding {
|
||||
return []key.Binding{
|
||||
listKeys.toggleSpinner,
|
||||
listKeys.insertItem,
|
||||
listKeys.toggleTitleBar,
|
||||
listKeys.toggleStatusBar,
|
||||
listKeys.togglePagination,
|
||||
listKeys.toggleHelpMenu,
|
||||
}
|
||||
}
|
||||
|
||||
return model{
|
||||
list: dbList,
|
||||
keys: listKeys,
|
||||
delegateKeys: delegateKeys,
|
||||
}
|
||||
}
|
||||
|
||||
func (m model) Init() tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
var cmds []tea.Cmd
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
h, v := appStyle.GetFrameSize()
|
||||
m.list.SetSize(msg.Width-h, msg.Height-v)
|
||||
|
||||
case tea.KeyMsg:
|
||||
// Don't match any of the keys below if we're actively filtering.
|
||||
if m.list.FilterState() == list.Filtering {
|
||||
break
|
||||
}
|
||||
|
||||
switch {
|
||||
case key.Matches(msg, m.keys.toggleSpinner):
|
||||
cmd := m.list.ToggleSpinner()
|
||||
return m, cmd
|
||||
|
||||
case key.Matches(msg, m.keys.toggleTitleBar):
|
||||
v := !m.list.ShowTitle()
|
||||
m.list.SetShowTitle(v)
|
||||
m.list.SetShowFilter(v)
|
||||
m.list.SetFilteringEnabled(v)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keys.toggleStatusBar):
|
||||
m.list.SetShowStatusBar(!m.list.ShowStatusBar())
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keys.togglePagination):
|
||||
m.list.SetShowPagination(!m.list.ShowPagination())
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keys.toggleHelpMenu):
|
||||
m.list.SetShowHelp(!m.list.ShowHelp())
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keys.insertItem):
|
||||
panic(1)
|
||||
}
|
||||
}
|
||||
|
||||
// This will also call our delegate's update function.
|
||||
newListModel, cmd := m.list.Update(msg)
|
||||
m.list = newListModel
|
||||
cmds = append(cmds, cmd)
|
||||
|
||||
return m, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (m model) View() string {
|
||||
return appStyle.Render(m.list.View())
|
||||
}
|
||||
Reference in New Issue
Block a user