Skip to content

Commit

Permalink
Merge branch 'master' into dev/moul/cow
Browse files Browse the repository at this point in the history
  • Loading branch information
moul authored Jan 30, 2025
2 parents a168a6a + 57da324 commit 27d5994
Show file tree
Hide file tree
Showing 84 changed files with 856 additions and 279 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
with:
go-version: ${{ matrix.goversion }}
- run: go install -v ./gnovm/cmd/gno
- run: go run ./gnovm/cmd/gno transpile -v --gobuild ./examples
- run: go run ./gnovm/cmd/gno tool transpile -v --gobuild ./examples
test:
strategy:
fail-fast: false
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/gnoland.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ on:
# Changes to examples/ can create failures in gno.land, eg. txtars,
# see: https://github.com/gnolang/gno/pull/3590
- examples/**
# We trigger the testing workflow for changes to the main go.mod,
# since this can affect test results
- go.mod
workflow_dispatch:

jobs:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/gnovm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ on:
paths:
- gnovm/**
- tm2/** # GnoVM has a dependency on TM2 types
# We trigger the testing workflow for changes to the main go.mod,
# since this can affect test results
- go.mod
workflow_dispatch:

jobs:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/tm2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ on:
pull_request:
paths:
- tm2/**
# We trigger the testing workflow for changes to the main go.mod,
# since this can affect test results
- go.mod
workflow_dispatch:

jobs:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ coverage.out
*.swp
*.swo
*.bak

.tmp/
wal/
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ Additionally, it's not possible to use `gofumpt` for code formatting with
(flycheck-define-checker gno-lint
"A GNO syntax checker using the gno lint tool."
:command ("gno" "lint" source-original)
:command ("gno" "tool" "lint" source-original)
:error-patterns (;; ./file.gno:32: error message (code=1)
(error line-start (file-name) ":" line ": " (message) " (code=" (id (one-or-more digit)) ")." line-end))
;; Ensure the file is saved, to work around
Expand Down
56 changes: 28 additions & 28 deletions docs/reference/go-gno-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,31 +297,31 @@ Legend:

## Tooling (`gno` binary)

| go command | gno command | comment |
|-------------------|---------------------------|-----------------------------------------------------------------------|
| go bug | gno bug | same behavior |
| go build | gno transpile -gobuild | same intention, limited compatibility |
| go clean | gno clean | same intention, limited compatibility |
| go doc | gno doc | limited compatibility; see https://github.com/gnolang/gno/issues/522 |
| go env | gno env | |
| go fix | | |
| go fmt | gno fmt | gofmt (& similar tools, like gofumpt) works on gno code. |
| go generate | | |
| go get | | see `gno mod download`. |
| go help | gno $cmd --help | ie. `gno doc --help` |
| go install | | |
| go list | | |
| go mod | gno mod | |
| + go mod init | gno mod init | same behavior |
| + go mod download | gno mod download | same behavior |
| + go mod tidy | gno mod tidy | same behavior |
| + go mod why | gno mod why | same intention |
| | gno transpile | |
| go work | | |
| | gno repl | |
| go run | gno run | |
| go test | gno test | limited compatibility |
| go tool | | |
| go version | | |
| go vet | | |
| golint | gno lint | same intention |
| go command | gno command | comment |
|-------------------|------------------------------|-----------------------------------------------------------------------|
| go bug | gno bug | same behavior |
| go build | gno tool transpile -gobuild | same intention, limited compatibility |
| go clean | gno clean | same intention, limited compatibility |
| go doc | gno doc | limited compatibility; see https://github.com/gnolang/gno/issues/522 |
| go env | gno env | |
| go fix | | |
| go fmt | gno fmt | gofmt (& similar tools, like gofumpt) works on gno code. |
| go generate | | |
| go get | | see `gno mod download`. |
| go help | gno $cmd --help | ie. `gno doc --help` |
| go install | | |
| go list | | |
| go mod | gno mod | |
| + go mod init | gno mod init | same behavior |
| + go mod download | gno mod download | same behavior |
| + go mod tidy | gno mod tidy | same behavior |
| + go mod why | gno mod why | same intention |
| | gno tool transpile | |
| go work | | |
| | gno tool repl | |
| go run | gno run | |
| go test | gno test | limited compatibility |
| go tool | | |
| go version | | |
| go vet | | |
| golint | gno tool lint | same intention |
6 changes: 3 additions & 3 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ OFFICIAL_PACKAGES += ./gno.land/r/gov
# Dev tools
.PHONY: transpile
transpile:
go run ../gnovm/cmd/gno transpile -v .
go run ../gnovm/cmd/gno tool transpile -v .

.PHONY: build
build:
go run ../gnovm/cmd/gno transpile -v --gobuild .
go run ../gnovm/cmd/gno tool transpile -v --gobuild .

.PHONY: test
test:
go run ../gnovm/cmd/gno test -v ./...

.PHONY: lint
lint:
go run ../gnovm/cmd/gno lint -v $(OFFICIAL_PACKAGES)
go run ../gnovm/cmd/gno tool lint -v $(OFFICIAL_PACKAGES)

.PHONY: test.sync
test.sync:
Expand Down
1 change: 1 addition & 0 deletions examples/gno.land/r/docs/avl_pager_with_params/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module gno.land/r/docs/avl_pager_params
86 changes: 86 additions & 0 deletions examples/gno.land/r/docs/avl_pager_with_params/render.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package avl_pager_params

import (
"gno.land/p/demo/avl"
"gno.land/p/demo/avl/pager"
"gno.land/p/demo/seqid"
"gno.land/p/demo/ufmt"
"gno.land/p/moul/realmpath"
)

// We'll keep some demo data in an AVL tree to showcase pagination.
var (
items *avl.Tree
idCounter seqid.ID
)

func init() {
items = avl.NewTree()
// Populate the tree with 15 sample items for demonstration.
for i := 1; i <= 15; i++ {
id := idCounter.Next().String()
items.Set(id, "Some item value: "+id)
}
}

func Render(path string) string {
// 1) Parse the incoming path to split route vs. query.
req := realmpath.Parse(path)
// - req.Path contains everything *before* ? or $ (? - query params, $ - gnoweb params)
// - The remaining part (page=2, size=5, etc.) is not in req.Path.

// 2) If no specific route is provided (req.Path == ""), we’ll show a “home” page
// that displays a list of configs in paginated form.
if req.Path == "" {
return renderHome(path)
}

// 3) If a route *is* provided (e.g. :SomeKey),
// we will interpret it as a request for a specific page.
return renderConfigItem(req.Path)
}

// renderHome shows a paginated list of config items if route == "".
func renderHome(fullPath string) string {
// Create a Pager for our config tree, with a default page size of 5.
p := pager.NewPager(items, 5, false)

// MustGetPageByPath uses the *entire* path (including query parts: ?page=2, etc.)
page := p.MustGetPageByPath(fullPath)

// Start building the output (plain text or markdown).
out := "# AVL Pager + Render paths\n\n"
out += `This realm showcases how to maintain a paginated list while properly parsing render paths.
You can see how a single page can include a paginated element (like the example below), and how clicking
an item can take you to a dedicated page for that specific item.
No matter how you browse through the paginated list, the introductory text (this section) remains the same.
`

out += ufmt.Sprintf("Showing page %d of %d\n\n", page.PageNumber, page.TotalPages)

// List items for this page.
for _, item := range page.Items {
// Link each item to a details page: e.g. ":Config01"
out += ufmt.Sprintf("- [Item %s](/r/docs/avl_pager_params:%s)\n", item.Key, item.Key)
}

// Insert pagination controls (previous/next links, etc.).
out += "\n" + page.Picker() + "\n\n"
out += "### [Go back to r/docs](/r/docs)"

return out
}

// renderConfigItem shows details for a single item, e.g. ":item001".
func renderConfigItem(itemName string) string {
value, ok := items.Get(itemName)
if !ok {
return ufmt.Sprintf("**No item found** for key: %s", itemName)
}

out := ufmt.Sprintf("# Item %s\n\n%s\n\n", itemName, value.(string))
out += "[Go back](/r/docs/avl_pager_params)"
return out
}
2 changes: 2 additions & 0 deletions examples/gno.land/r/docs/docs.gno
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ Explore various examples to learn more about Gno functionality and usage.
- [Source](/r/docs/source) - View realm source code.
- [Buttons](/r/docs/buttons) - Add buttons to your realm's render.
- [AVL Pager](/r/docs/avl_pager) - Paginate through AVL tree items.
- [AVL Pager + Render paths](/r/docs/avl_pager_params) - Handle render arguments with pagination.
- [Img Embed](/r/docs/img_embed) - Demonstrates how to embed an image.
- [Optional Render](/r/docs/optional_render) - Render() is optional in realms.
- ...
<!-- meta issue with suggestions: https://github.com/gnolang/gno/issues/3292 -->
Expand Down
1 change: 1 addition & 0 deletions examples/gno.land/r/docs/optional_render/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module gno.land/r/docs/optional_render
7 changes: 7 additions & 0 deletions examples/gno.land/r/docs/optional_render/optional_render.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package optional_render

func Info() string {
return `Having a Render() function in your realm is optional!
If you do decide to have a Render() function, it must have the following signature:
func Render(path string) string { ... }`
}
119 changes: 87 additions & 32 deletions examples/gno.land/r/leon/config/config.gno
Original file line number Diff line number Diff line change
Expand Up @@ -3,61 +3,116 @@ package config
import (
"errors"
"std"
"strconv"
"strings"
"time"

"gno.land/p/demo/avl"
p "gno.land/p/demo/avl/pager"
"gno.land/p/demo/ownable"
"gno.land/p/demo/ufmt"
"gno.land/p/moul/md"
"gno.land/p/moul/realmpath"
)

var (
main std.Address // leon's main address
backup std.Address // backup address
configs = avl.NewTree()
pager = p.NewPager(configs, 10, false)
banner = "---\n[[Leon's Home page]](/r/leon/home) | [[GitHub: @leohhhn]](https://github.com/leohhhn)\n\n---"
absPath = strings.TrimPrefix(std.CurrentRealm().PkgPath(), std.GetChainDomain())

// SafeObjects
OwnableMain = ownable.NewWithAddress("g125em6arxsnj49vx35f0n0z34putv5ty3376fg5")
OwnableBackup = ownable.NewWithAddress("g1lavlav7zwsjqlzzl3qdl3nl242qtf638vnhdjh")

ErrInvalidAddr = errors.New("leon's config: invalid address")
ErrUnauthorized = errors.New("leon's config: unauthorized")
)

func init() {
main = "g125em6arxsnj49vx35f0n0z34putv5ty3376fg5"
type Config struct {
lines string
updated time.Time
}

func Address() std.Address {
return main
}
func AddConfig(name, lines string) {
if !IsAuthorized(std.PrevRealm().Addr()) {
panic(ErrUnauthorized)
}

func Backup() std.Address {
return backup
configs.Set(name, Config{
lines: lines,
updated: time.Now(),
}) // no overwrite check
}

func SetAddress(a std.Address) error {
if !a.IsValid() {
return ErrInvalidAddr
func RemoveConfig(name string) {
if !IsAuthorized(std.PrevRealm().Addr()) {
panic(ErrUnauthorized)
}

if err := checkAuthorized(); err != nil {
return err
if _, ok := configs.Remove(name); !ok {
panic("no config with that name")
}

main = a
return nil
}

func SetBackup(a std.Address) error {
if !a.IsValid() {
return ErrInvalidAddr
func UpdateBanner(newBanner string) {
if !IsAuthorized(std.PrevRealm().Addr()) {
panic(ErrUnauthorized)
}

if err := checkAuthorized(); err != nil {
return err
}
banner = newBanner
}

backup = a
return nil
func IsAuthorized(addr std.Address) bool {
return addr == OwnableMain.Owner() || addr == OwnableBackup.Owner()
}

func checkAuthorized() error {
caller := std.PrevRealm().Addr()
isAuthorized := caller == main || caller == backup
func Banner() string {
return banner
}

func Render(path string) (out string) {
req := realmpath.Parse(path)
if req.Path == "" {
out += md.H1("Leon's config package")

out += ufmt.Sprintf("Leon's main address: %s\n\n", OwnableMain.Owner().String())
out += ufmt.Sprintf("Leon's backup address: %s\n\n", OwnableBackup.Owner().String())

if !isAuthorized {
return ErrUnauthorized
out += md.H2("Leon's configs")

if configs.Size() == 0 {
out += "No configs yet :c\n\n"
}

page := pager.MustGetPageByPath(path)
for _, item := range page.Items {
out += ufmt.Sprintf("- [%s](%s:%s)\n\n", item.Key, absPath, item.Key)
}

out += page.Picker()
out += "\n\n"
out += "Page " + strconv.Itoa(page.PageNumber) + " of " + strconv.Itoa(page.TotalPages) + "\n\n"

out += Banner()

return out
}

return nil
return renderConfPage(req.Path)
}

func renderConfPage(confName string) (out string) {
raw, ok := configs.Get(confName)
if !ok {
out += md.H1("404")
out += "That config does not exist :/"
return out
}

conf := raw.(Config)
out += md.H1(confName)
out += ufmt.Sprintf("```\n%s\n```\n\n", conf.lines)
out += ufmt.Sprintf("_Last updated on %s_", conf.updated.Format("02 Jan, 2006"))

return out
}
Loading

0 comments on commit 27d5994

Please sign in to comment.