add fs and notifications to stdlib
This commit is contained in:
parent
f858daff59
commit
20f413508f
7 changed files with 163 additions and 35 deletions
|
@ -5,7 +5,7 @@ tmp_dir = "tmp"
|
|||
[build]
|
||||
args_bin = []
|
||||
bin = "tmp\\main.exe"
|
||||
cmd = "go build -ldflags='-H windowsgui' -o ./tmp/main.exe ./example"
|
||||
cmd = "go build -o ./tmp/main.exe ./example"
|
||||
delay = 1000
|
||||
exclude_dir = ["assets", "tmp", "vendor", "testdata", "runtime/out", "node_modules", "dist"]
|
||||
exclude_file = []
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
<button onclick="greet()">Greet</button>
|
||||
<button onclick="file()">Read File</button>
|
||||
<button onclick="directory()">List Directory</button>
|
||||
|
||||
<button onclick="notify()">Notify</button>
|
||||
|
||||
<script>
|
||||
function greet() {
|
||||
tiramisu.invoke("hello", "world")
|
||||
|
@ -27,6 +28,14 @@
|
|||
.then(files => alert("Files: " + files.join(", ")))
|
||||
.catch(error => alert("Error listing directory: " + error.message));
|
||||
}
|
||||
|
||||
function notify() {
|
||||
const message = prompt("Enter the notification message:");
|
||||
if (!message) return;
|
||||
tiramisu.notifications.notify(message)
|
||||
.then(() => alert("Notification sent!"))
|
||||
.catch(error => alert("Error sending notification: " + error.message));
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
16
go.mod
16
go.mod
|
@ -2,4 +2,18 @@ module git.iwakura.rip/grng/tiramisu
|
|||
|
||||
go 1.23.4
|
||||
|
||||
require github.com/webview/webview_go v0.0.0-20240831120633-6173450d4dd6 // indirect
|
||||
require (
|
||||
git.sr.ht/~jackmordaunt/go-toast v1.1.2 // indirect
|
||||
github.com/electricbubble/go-toast v0.3.0 // indirect
|
||||
github.com/esiqveland/notify v0.13.3 // indirect
|
||||
github.com/gen2brain/beeep v0.11.1 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/jackmordaunt/icns/v3 v3.0.1 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/sergeymakinen/go-bmp v1.0.0 // indirect
|
||||
github.com/sergeymakinen/go-ico v1.0.0-beta.0 // indirect
|
||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect
|
||||
github.com/webview/webview_go v0.0.0-20240831120633-6173450d4dd6 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
)
|
||||
|
|
37
go.sum
37
go.sum
|
@ -1,2 +1,39 @@
|
|||
git.sr.ht/~jackmordaunt/go-toast v1.1.2 h1:/yrfI55LRt1M7H1vkaw+NaH1+L1CDxrqDltwm5euVuE=
|
||||
git.sr.ht/~jackmordaunt/go-toast v1.1.2/go.mod h1:jA4OqHKTQ4AFBdwrSnwnskUIIS3HYzlJSgdzCKqfavo=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/electricbubble/go-toast v0.3.0 h1:e/PtFkpYNdLANI/utTXzoYQuMYG/N8oHT0Rwal4z/sI=
|
||||
github.com/electricbubble/go-toast v0.3.0/go.mod h1:6k4ufXmV/AS32EugdLeIXa+2jv6oYbWzv2+UZhB49FI=
|
||||
github.com/esiqveland/notify v0.13.3 h1:QCMw6o1n+6rl+oLUfg8P1IIDSFsDEb2WlXvVvIJbI/o=
|
||||
github.com/esiqveland/notify v0.13.3/go.mod h1:hesw/IRYTO0x99u1JPweAl4+5mwXJibQVUcP0Iu5ORE=
|
||||
github.com/gen2brain/beeep v0.11.1 h1:EbSIhrQZFDj1K2fzlMpAYlFOzV8YuNe721A58XcCTYI=
|
||||
github.com/gen2brain/beeep v0.11.1/go.mod h1:jQVvuwnLuwOcdctHn/uyh8horSBNJ8uGb9Cn2W4tvoc=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/jackmordaunt/icns/v3 v3.0.1 h1:xxot6aNuGrU+lNgxz5I5H0qSeCjNKp8uTXB1j8D4S3o=
|
||||
github.com/jackmordaunt/icns/v3 v3.0.1/go.mod h1:5sHL59nqTd2ynTnowxB/MDQFhKNqkK8X687uKNygaSQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sergeymakinen/go-bmp v1.0.0 h1:SdGTzp9WvCV0A1V0mBeaS7kQAwNLdVJbmHlqNWq0R+M=
|
||||
github.com/sergeymakinen/go-bmp v1.0.0/go.mod h1:/mxlAQZRLxSvJFNIEGGLBE/m40f3ZnUifpgVDlcUIEY=
|
||||
github.com/sergeymakinen/go-ico v1.0.0-beta.0 h1:m5qKH7uPKLdrygMWxbamVn+tl2HfiA3K6MFJw4GfZvQ=
|
||||
github.com/sergeymakinen/go-ico v1.0.0-beta.0/go.mod h1:wQ47mTczswBO5F0NoDt7O0IXgnV4Xy3ojrroMQzyhUk=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
|
||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o=
|
||||
github.com/webview/webview_go v0.0.0-20240831120633-6173450d4dd6 h1:VQpB2SpK88C6B5lPHTuSZKb2Qee1QWwiFlC5CKY4AW0=
|
||||
github.com/webview/webview_go v0.0.0-20240831120633-6173450d4dd6/go.mod h1:yE65LFCeWf4kyWD5re+h4XNvOHJEXOCOuJZ4v8l5sgk=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
15
runtime/index.d.ts
vendored
15
runtime/index.d.ts
vendored
|
@ -1,14 +1,25 @@
|
|||
declare global {
|
||||
interface Window {
|
||||
// internal
|
||||
__TIRAMISU_INTERNAL_invoke: (name: string, ...args: any[]) => Promise<any>;
|
||||
__TIRAMISU_INTERNAL_readFile: (path: string) => Promise<string>;
|
||||
__TIRAMISU_INTERNAL_readDir: (path: string) => Promise<string[]>;
|
||||
|
||||
// filesystem
|
||||
__TIRAMISU_FILESYSTEM_readFile: (path: string) => Promise<string>;
|
||||
__TIRAMISU_FILESYSTEM_readDir: (path: string) => Promise<string[]>;
|
||||
__TIRAMISU_INTERNAL_exists: (path: string) => Promise<boolean>;
|
||||
|
||||
// notifications
|
||||
__TIRAMISU_NOTIFICATIONS_notify: (message: string, ico?: string) => Promise<void>;
|
||||
|
||||
tiramisu: {
|
||||
invoke: (name: string, ...args: any[]) => Promise<any>;
|
||||
fs: {
|
||||
readFile(path: string): Promise<string>;
|
||||
readDir(path: string): Promise<string[]>;
|
||||
exists(path: string): Promise<boolean>;
|
||||
},
|
||||
notifications: {
|
||||
notify(message: string, ico?: string): Promise<void>;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
const tiramisu = {
|
||||
invoke: window.__TIRAMISU_INTERNAL_invoke,
|
||||
fs: {
|
||||
readFile: window.__TIRAMISU_INTERNAL_readFile,
|
||||
readDir: window.__TIRAMISU_INTERNAL_readDir
|
||||
}
|
||||
readFile: window.__TIRAMISU_FILESYSTEM_readFile,
|
||||
readDir: window.__TIRAMISU_FILESYSTEM_readDir,
|
||||
exists: window.__TIRAMISU_INTERNAL_exists,
|
||||
},
|
||||
notifications: {
|
||||
notify: window.__TIRAMISU_NOTIFICATIONS_notify,
|
||||
},
|
||||
}
|
||||
|
||||
window.tiramisu = tiramisu
|
107
tiramisu.go
107
tiramisu.go
|
@ -2,9 +2,11 @@ package tiramisu
|
|||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
toast "github.com/electricbubble/go-toast"
|
||||
wv "github.com/webview/webview_go"
|
||||
)
|
||||
|
||||
|
@ -19,6 +21,7 @@ type TiramisuOptions struct {
|
|||
type FuncHandler func(args ...any) (any, error)
|
||||
|
||||
type Tiramisu struct {
|
||||
o TiramisuOptions
|
||||
w wv.WebView
|
||||
funcs map[string]FuncHandler
|
||||
}
|
||||
|
@ -29,6 +32,7 @@ func New(o TiramisuOptions) *Tiramisu {
|
|||
w.SetTitle(o.Title)
|
||||
|
||||
t := &Tiramisu{
|
||||
o: o,
|
||||
w: w,
|
||||
funcs: make(map[string]FuncHandler),
|
||||
}
|
||||
|
@ -104,27 +108,25 @@ func (t *Tiramisu) loadJSRuntime() {
|
|||
}
|
||||
|
||||
func (t *Tiramisu) loadGoRuntime() {
|
||||
// internal
|
||||
t.bind("__TIRAMISU_INTERNAL_invoke", func(args ...any) (any, error) {
|
||||
name, ok := args[0].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("first argument must be a string, got %T", args[0])
|
||||
name, err := ArgAs[string](args, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// pass through any extra args
|
||||
if len(args) == 1 {
|
||||
return t.invoke(name)
|
||||
}
|
||||
return t.invoke(name, args[1:]...)
|
||||
})
|
||||
|
||||
t.bind("__TIRAMISU_INTERNAL_readFile", func(args ...any) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, fmt.Errorf("readFile expects exactly one argument, got %d", len(args))
|
||||
// filesystem
|
||||
t.bind("__TIRAMISU_FILESYSTEM_readFile", func(args ...any) (any, error) {
|
||||
filename, err := ArgAs[string](args, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filename, ok := args[0].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("readFile expects a string argument, got %T", args[0])
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading file %s: %w", filename, err)
|
||||
|
@ -132,25 +134,76 @@ func (t *Tiramisu) loadGoRuntime() {
|
|||
return string(data), nil
|
||||
})
|
||||
|
||||
t.bind("__TIRAMISU_INTERNAL_readDir", func(args ...any) (any, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, fmt.Errorf("readDir expects exactly one argument, got %d", len(args))
|
||||
t.bind("__TIRAMISU_FILESYSTEM_readDir", func(args ...any) (any, error) {
|
||||
dirname, err := ArgAs[string](args, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dirname, ok := args[0].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("readDir expects a string argument, got %T", args[0])
|
||||
}
|
||||
|
||||
files, err := os.ReadDir(dirname)
|
||||
entries, err := os.ReadDir(dirname)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading directory %s: %w", dirname, err)
|
||||
}
|
||||
|
||||
var fileNames []string
|
||||
for _, file := range files {
|
||||
fileNames = append(fileNames, file.Name())
|
||||
var names []string
|
||||
for _, e := range entries {
|
||||
names = append(names, e.Name())
|
||||
}
|
||||
return fileNames, nil
|
||||
return names, nil
|
||||
})
|
||||
|
||||
t.bind("__TIRAMISU_INTERNAL_exists", func(args ...any) (any, error) {
|
||||
path, err := ArgAs[string](args, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = os.Stat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return nil, fmt.Errorf("error checking existence of %s: %w", path, err)
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
// notifications
|
||||
t.bind("__TIRAMISU_NOTIFICATIONS_notify", func(args ...any) (any, error) {
|
||||
msg, err := ArgAs[string](args, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := toast.Push(msg); err != nil {
|
||||
return nil, fmt.Errorf("error sending notification: %w", err)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
})
|
||||
}
|
||||
|
||||
func Arg(args []any, i int) (any, error) {
|
||||
if i < 0 || i >= len(args) {
|
||||
return nil, fmt.Errorf("arg %d out of range [0..%d]", i, len(args)-1)
|
||||
}
|
||||
return args[i], nil
|
||||
}
|
||||
|
||||
func ArgAs[T any](args []any, i int) (T, error) {
|
||||
var t T
|
||||
|
||||
arg, err := Arg(args, i)
|
||||
if err != nil {
|
||||
return t, err
|
||||
}
|
||||
|
||||
if v, ok := arg.(T); ok {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
j, err := json.Marshal(arg)
|
||||
if err != nil {
|
||||
return t, fmt.Errorf("cannot marshal arg[%d]: %w", i, err)
|
||||
}
|
||||
if err := json.Unmarshal(j, &t); err != nil {
|
||||
return t, fmt.Errorf("cannot unmarshal arg[%d] -> %T: %w", i, t, err)
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue