Skip to content

Commit e7d7057

Browse files
committed
Init
1 parent 18f927d commit e7d7057

File tree

8 files changed

+506
-2
lines changed

8 files changed

+506
-2
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
nimcache/
2+
redux/examples/*
3+
!redux/examples/*.nim

README.md

+207-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,207 @@
1-
# redux.nim
2-
Redux.nim is a predictable state container for Nim apps
1+
# Redux.nim
2+
3+
Redux.nim is a predictable state container for Nim apps. Nim version of [Redux.js](http://redux.js.org/).
4+
5+
## Examples
6+
7+
To run the examples below:
8+
9+
```
10+
nimble install # For first time
11+
```
12+
13+
```
14+
cd redux/examples/
15+
nim c -r counter.nim
16+
nim c -r todos.nim
17+
nim c -r todosundoable.nim
18+
```
19+
20+
### Counter
21+
22+
```nim
23+
type
24+
CounterState = ref object
25+
count: int
26+
IncrementAction = ref object of Action
27+
DecrementAction = ref object of Action
28+
29+
proc counter(state: CounterState, action: Action): CounterState =
30+
if state == nil:
31+
return CounterState(count: 0)
32+
if action of IncrementAction:
33+
result = CounterState(count: state.count + 1)
34+
elif action of DecrementAction:
35+
result = CounterState(count: state.count - 1)
36+
else:
37+
result = state
38+
39+
var store = newStore(counter)
40+
41+
store.dispatch(IncrementAction())
42+
echo store.getState().count
43+
44+
store.dispatch(DecrementAction())
45+
echo store.getState().count
46+
```
47+
48+
Output:
49+
50+
```
51+
1
52+
0
53+
```
54+
55+
### Todos with Undo/Redo
56+
57+
```nim
58+
type
59+
Todo = object
60+
text: string
61+
completed: bool
62+
63+
VisibilityFilter = enum
64+
All,
65+
Done,
66+
Incomplete
67+
68+
TodosStateObj = object
69+
filter: VisibilityFilter
70+
todos: seq[Todo]
71+
TodosState = ref TodosStateObj
72+
73+
AddTodoAction = ref object of Action
74+
text: string
75+
76+
ToggleTodoAction = ref object of Action
77+
index: Natural
78+
79+
SetFilterAction = ref object of Action
80+
filter: VisibilityFilter
81+
82+
{.experimental.}
83+
84+
using
85+
state: TodosState
86+
action: Action
87+
filter: VisibilityFilter
88+
todo: Todo
89+
90+
proc `$`(filter): string =
91+
case filter
92+
of All: "All"
93+
of Done: "Done"
94+
of Incomplete: "Incomplete"
95+
96+
proc `$`(state: UndoableState[TodosState]): string =
97+
let state = state.getPresent()
98+
result = "Todos(" & $state.filter & "):\n"
99+
let todos = state.todos.filter(proc(todo): bool =
100+
state.filter == All or todo.completed and state.filter == Done or not todo.completed and state.filter == Incomplete
101+
)
102+
if len(todos) == 0:
103+
result &= "/empty/\n"
104+
else:
105+
for todo in todos:
106+
result &= (if todo.completed: "[x] " else: "[ ] ") & todo.text & "\n"
107+
108+
proc todos(state, action): TodosState =
109+
if state == nil:
110+
return TodosState(
111+
filter: VisibilityFilter.All,
112+
todos: @[]
113+
)
114+
new(result); result[] = state[]
115+
if action of SetFilterAction:
116+
result.filter = SetFilterAction(action).filter
117+
elif action of AddTodoAction:
118+
let todo = Todo(text: AddTodoAction(action).text)
119+
result.todos = todo & result.todos
120+
elif action of ToggleTodoAction:
121+
let index = ToggleTodoAction(action).index
122+
var todo = result.todos[index]
123+
todo.completed = not todo.completed
124+
result.todos[index] = todo
125+
else:
126+
result = state
127+
128+
var store = newStore(undoable(todos))
129+
130+
store.subscribe(proc (state: UndoableState[TodosState]) = echo $state)
131+
132+
store.dispatch(AddTodoAction(text: "First point"))
133+
store.dispatch(UndoAction())
134+
store.dispatch(RedoAction())
135+
store.dispatch(AddTodoAction(text: "Next point"))
136+
store.dispatch(ToggleTodoAction(index: 1))
137+
store.dispatch(SetFilterAction(filter: Done))
138+
store.dispatch(SetFilterAction(filter: Incomplete))
139+
store.dispatch(ToggleTodoAction(index: 0))
140+
store.dispatch(UndoAction())
141+
store.dispatch(UndoAction())
142+
store.dispatch(UndoAction())
143+
store.dispatch(UndoAction())
144+
store.dispatch(UndoAction())
145+
store.dispatch(UndoAction())
146+
```
147+
148+
Output:
149+
150+
```
151+
Todos(All):
152+
[ ] First point
153+
154+
Todos(All):
155+
/empty/
156+
157+
Todos(All):
158+
[ ] First point
159+
160+
Todos(All):
161+
[ ] Next point
162+
[ ] First point
163+
164+
Todos(All):
165+
[ ] Next point
166+
[x] First point
167+
168+
Todos(Done):
169+
[x] First point
170+
171+
Todos(Incomplete):
172+
[ ] Next point
173+
174+
Todos(Incomplete):
175+
/empty/
176+
177+
Todos(Incomplete):
178+
[ ] Next point
179+
180+
Todos(Done):
181+
[x] First point
182+
183+
Todos(All):
184+
[ ] Next point
185+
[x] First point
186+
187+
Todos(All):
188+
[ ] Next point
189+
[ ] First point
190+
191+
Todos(All):
192+
[ ] First point
193+
194+
Todos(All):
195+
/empty/
196+
```
197+
198+
## TODO
199+
200+
* Add `combineReducers`.
201+
* Elaborate on asyncrounus dispatch.
202+
203+
## License
204+
205+
This library is licensed under the MIT license. Read [LICENSE](https://github.com/pragmagic/redux.nim/blob/master/LICENSE) file for details.
206+
207+
Copyright (c) 2017 Pragmagic, Inc.

redux.nimble

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Package
2+
3+
version = "0.1.0"
4+
author = "Pragmagic, Inc."
5+
description = "Predictable state container."
6+
license = "MIT"
7+
8+
# Dependencies
9+
10+
requires "nim >= 0.17"

redux/examples/counter.nim

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import ../redux
2+
3+
type
4+
CounterState = ref object
5+
count: int
6+
IncrementAction = ref object of Action
7+
DecrementAction = ref object of Action
8+
9+
proc counter(state: CounterState, action: Action): CounterState =
10+
if state == nil:
11+
return CounterState(count: 0)
12+
if action of IncrementAction:
13+
result = CounterState(count: state.count + 1)
14+
elif action of DecrementAction:
15+
result = CounterState(count: state.count - 1)
16+
else:
17+
result = state
18+
19+
var store = newStore(counter)
20+
21+
store.dispatch(IncrementAction())
22+
echo store.getState().count
23+
24+
store.dispatch(DecrementAction())
25+
echo store.getState().count

redux/examples/todos.nim

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import sequtils
2+
import ../redux
3+
4+
type
5+
Todo = object
6+
text: string
7+
completed: bool
8+
9+
VisibilityFilter = enum
10+
All,
11+
Done,
12+
Incomplete
13+
14+
TodosStateObj = object
15+
filter: VisibilityFilter
16+
todos: seq[Todo]
17+
TodosState = ref TodosStateObj
18+
19+
AddTodoAction = ref object of Action
20+
text: string
21+
22+
ToggleTodoAction = ref object of Action
23+
index: Natural
24+
25+
SetFilterAction = ref object of Action
26+
filter: VisibilityFilter
27+
28+
{.experimental.}
29+
30+
using
31+
state: TodosState
32+
action: Action
33+
filter: VisibilityFilter
34+
todo: Todo
35+
36+
proc `$`(filter): string =
37+
case filter
38+
of All: "All"
39+
of Done: "Done"
40+
of Incomplete: "Incomplete"
41+
42+
proc `$`(state): string =
43+
result = "Todos(" & $state.filter & "):\n"
44+
let todos = state.todos.filter(proc(todo): bool =
45+
state.filter == All or todo.completed and state.filter == Done or not todo.completed and state.filter == Incomplete
46+
)
47+
if len(todos) == 0:
48+
result &= "/empty/"
49+
else:
50+
for todo in todos:
51+
result &= (if todo.completed: "[x] " else: "[ ] ") & todo.text & "\n"
52+
53+
proc todos(state, action): TodosState =
54+
if state == nil:
55+
return TodosState(
56+
filter: VisibilityFilter.All,
57+
todos: @[]
58+
)
59+
new(result); result[] = state[]
60+
if action of SetFilterAction:
61+
result.filter = SetFilterAction(action).filter
62+
elif action of AddTodoAction:
63+
let todo = Todo(text: AddTodoAction(action).text)
64+
result.todos = todo & result.todos
65+
elif action of ToggleTodoAction:
66+
let index = ToggleTodoAction(action).index
67+
var todo = result.todos[index]
68+
todo.completed = not todo.completed
69+
result.todos[index] = todo
70+
else:
71+
result = state
72+
73+
var store = newStore(todos)
74+
75+
store.subscribe(proc (state) = echo $state)
76+
77+
store.dispatch(AddTodoAction(text: "First point"))
78+
store.dispatch(AddTodoAction(text: "Next point"))
79+
store.dispatch(ToggleTodoAction(index: 1))
80+
store.dispatch(SetFilterAction(filter: Done))
81+
store.dispatch(SetFilterAction(filter: Incomplete))
82+
store.dispatch(ToggleTodoAction(index: 0))

0 commit comments

Comments
 (0)