summaryrefslogtreecommitdiff
path: root/docs/guide/typescript/cli-app.md
blob: 41b1d7cba07243e7859dc24656be5775034dd721 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# CLI and App

`App` is a singleton **instance** of an [Astal.Application](https://aylur.github.io/libastal/astal3/class.Application.html).

Depending on gtk version import paths will differ

```ts
import { App } from "astal/gtk3"
import { App } from "astal/gtk4"
```

## Entry point

:::code-group

```ts [app.ts]
App.start({
    main() {
        // setup anything
        // instantiate widgets
    },
})
```

:::

## Instance identifier

You can run multiple instances by defining a unique instance name.

```ts
App.start({
    instanceName: "my-instance", // defaults to "astal"
    main() { },
})
```

## Messaging from CLI

If you want to interact with an instance from the CLI,
you can do so by sending a message.

```ts
App.start({
    requestHandler(request: string, res: (response: any) => void) {
        if (request == "say hi") {
            return res("hi cli")
        }
        res("unknown command")
    },
    main() { },
})
```

```sh
astal say hi
# hi cli
```

If you want to run arbitrary JavaScript from CLI, you can use `App.eval`
which will evaluate the passed string as the body of an `async` function.

```ts
App.start({
    main() {},
    requestHandler(js, res) {
        App.eval(js).then(res).catch(res)
    },
})
```

If the string does not contain a semicolon, a single expression is assumed and returned implicity.

```sh
astal "'hello'"
# hello
```

If the string contains a semicolon, you have to return explicitly

```sh
astal "'hello';"
# undefined

astal "return 'hello';"
# hello
```

## Toggling Windows by their name

In order for Astal to know about your windows, you have to register them.
You can do this by specifying a **unique** `name` and calling `App.add_window`

```tsx {4}
import { App } from "astal/gtk3"

function Bar() {
    return <window name="Bar" setup={self => App.add_window(self)}>
        <box />
    </window>
}
```

You can also invoke `App.add_window` by simply passing the `App` to the `application` prop.

```tsx {4}
import { App } from "astal/gtk3"

function Bar() {
    return <window name="Bar" application={App}>
        <box />
    </window>
}
```

:::warning
When assigning the `application` prop make sure `name` comes before.
Props are set sequentially and if name is applied after application it won't work.
:::

```sh [astal]
astal -t Bar
```

## Client

The first time you execute your script the `main` function gets called.
While that instance is running any subsequent execution of the script will call
the `client` function.

:::code-group

```ts [main.ts]
App.start({
    // main instance
    main(...args: Array<string>) {
        print(...args)
    },

    // every subsequent calls
    client(message: (msg: string) => string, ...args: Array<string>) {
        const res = message("you can message the main instance")
        print(res)
    },

    // this runs in the main instance
    requestHandler(request: string, res: (response: any) => void) {
        res("response from main")
    },
})
```

:::