Skip to content

Commit 4ee586b

Browse files
Add subject signal (#4)
Add a signal that execute functions when they connect with the most recent value (and also with the next fired values)
1 parent a7410d4 commit 4ee586b

8 files changed

+83
-7
lines changed

.vscode/settings.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"luau-lsp.require.directoryAliases": {
33
"@pkg": "node_modules/.luau-aliases"
4-
}
4+
},
5+
"stylua.targetReleaseVersion": "v2.0.1"
56
}

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Changelog
22

3+
- add new signal kind that fires with the last fired value ([#4](https://github.com/seaofvoices/luau-signal/pull/4))
4+
35
## 0.1.1
46

57
- use `luau-task` package to make Signal compatible with [Lune](https://github.com/lune-org/lune) ([#1](https://github.com/seaofvoices/luau-signal/pull/1))

README.md

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ A typed Luau signal library.
44

55
Signals are a lightweight communication mechanism used to facilitate the exchange of information between different components or modules of a software system. Signals allow parts of a program to notify others without having a dependency on them. This decoupled approach promotes modularity, making it easier to manage and maintain complex systems by broadcasting data in messages without requiring direct knowledge of their recipients.
66

7-
# Installation
7+
This library contains two kind of signals:
8+
9+
- `Signal.new()`: a typical signal that you can connect to and fire values
10+
- `Signal.newSubject(...)`: a signal that execute functions when they connect with the most recent value (and also with the next fired values)
11+
12+
## Installation
813

914
Add `luau-signal` in your dependencies:
1015

@@ -48,6 +53,10 @@ connection:disconnect()
4853

4954
Creates a new signal instance.
5055

56+
### `Signal.newSubject<T...>(...: T...): Signal<T...>`
57+
58+
Creates a new signal instance, except that when connecting to the signal, the callback will be immediately called with the most recent value. The arguments given to `newSubject` are the initial values that will be passed to function when they connect before anything was fire on the signal.
59+
5160
### `Signal:fire<T...>(...: T...)`
5261

5362
Fires the signal, triggering all connected callback functions with the provided arguments.

foreman.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tools]
22
rojo = { github = "rojo-rbx/rojo", version = "=7.4.4"}
33
selene = { github = "Kampfkarren/selene", version = "=0.27.1"}
4-
stylua = { github = "JohnnyMorganz/styLua", version = "=0.19.1" }
5-
darklua = { github = "seaofvoices/darklua", version = "=0.13.1"}
6-
luau-lsp = { github = "JohnnyMorganz/luau-lsp", version = "=1.32.4"}
4+
stylua = { github = "JohnnyMorganz/styLua", version = "=2.0.1" }
5+
darklua = { github = "seaofvoices/darklua", version = "=0.14.0"}
6+
luau-lsp = { github = "JohnnyMorganz/luau-lsp", version = "=1.35.0"}
77
wally = { github = "UpliftGames/wally", version = "=0.3.2" }

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"lint": "sh ./scripts/analyze.sh",
2323
"format": "stylua .",
2424
"style-check": "stylua . --check",
25-
"clean": "rm -rf node_modules roblox build"
25+
"clean": "rm -rf node_modules roblox build",
26+
"verify-pack": "yarn pack --dry-run"
2627
},
2728
"dependencies": {
2829
"luau-task": "^1.0.1"

src/Signal.lua

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ local task = require('@pkg/luau-task')
33
local Connection = require('./Connection')
44
export type Connection = Connection.Connection
55

6+
export type ConnectableSignal<T...> = {
7+
connect: (self: ConnectableSignal<T...>, callback: (T...) -> ()) -> Connection,
8+
}
9+
610
export type Signal<T...> = {
711
fire: (self: Signal<T...>, T...) -> (),
812
connect: (self: Signal<T...>, callback: (T...) -> ()) -> Connection,

src/Subject.lua

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
local task = require('@pkg/luau-task')
2+
3+
local Connection = require('./Connection')
4+
local Signal = require('./Signal')
5+
6+
type Connection = Connection.Connection
7+
8+
export type Subject<T...> = Signal.Signal<T...>
9+
10+
type Private<T...> = {
11+
_last: { any },
12+
_lastLength: number,
13+
}
14+
type PrivateSubject<T...> = Subject<T...> & Private<T...>
15+
16+
type SubjectStatic = {
17+
new: <T...>(T...) -> Subject<T...>,
18+
19+
fire: <T...>(self: Subject<T...>, T...) -> (),
20+
connect: <T...>(self: Subject<T...>, callback: (T...) -> ()) -> Connection,
21+
}
22+
23+
local Subject: SubjectStatic = setmetatable({}, { __index = Signal }) :: any
24+
local SubjectMetatable = {
25+
__index = Subject,
26+
}
27+
28+
function Subject.new<T...>(...): Subject<T...>
29+
local self: Private<T...> = Signal.new() :: any
30+
31+
self._last = { ... }
32+
self._lastLength = select('#', ...)
33+
34+
return setmetatable(self, SubjectMetatable) :: any
35+
end
36+
37+
function Subject:fire<T...>(...)
38+
local self: PrivateSubject<T...> = self :: any
39+
40+
self._last = { ... }
41+
self._lastLength = select('#', ...)
42+
43+
Signal.fire(self :: any, ...)
44+
end
45+
46+
function Subject:connect<T...>(callback: (T...) -> ()): Connection
47+
local self: PrivateSubject<T...> = self :: any
48+
49+
task.spawn(callback, unpack(self._last, 1, self._lastLength))
50+
51+
return Signal.connect(self :: any, callback)
52+
end
53+
54+
return Subject

src/init.lua

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
local Connection = require('./Connection')
22
local Signal = require('./Signal')
3+
local Subject = require('./Subject')
34

45
export type Connection = Connection.Connection
56
export type Signal<T...> = Signal.Signal<T...>
7+
export type ConnectableSignal<T...> = Signal.ConnectableSignal<T...>
68

7-
return Signal
9+
return {
10+
new = Signal.new,
11+
newSubject = Subject.new,
12+
}

0 commit comments

Comments
 (0)