+89
-72
src/dotfiles.gleam
+89
-72
src/dotfiles.gleam
···
13
13
/// location, relative to $HOME, of the dotfiles repo
14
14
const dotfiles = "dotfiles"
15
15
16
+
pub fn main() -> Nil {
17
+
let program_args = argv.load().arguments
18
+
let assert Ok(home_dir) = envoy.get("HOME") as "$HOME not defined"
19
+
20
+
case program_args {
21
+
["help"] -> show_help()
22
+
["new"] -> {
23
+
let _ =
24
+
setup_new(home_dir)
25
+
|> result.map_error(describe_error)
26
+
|> result.map_error(io.println_error)
27
+
28
+
Nil
29
+
}
30
+
31
+
["init", link] -> {
32
+
let _ =
33
+
init_from_link(link, home_dir)
34
+
|> result.map_error(describe_error)
35
+
|> result.map_error(io.println_error)
36
+
37
+
Nil
38
+
}
39
+
["init"] -> {
40
+
let _ =
41
+
update_symlinks(home_dir)
42
+
|> result.map_error(describe_error)
43
+
|> result.map_error(io.println_error)
44
+
45
+
Nil
46
+
}
47
+
["add", "submodule", link, path] -> {
48
+
let _ =
49
+
add_submodule(home_dir, link, path)
50
+
|> result.map_error(describe_error)
51
+
|> result.map_error(io.println_error)
52
+
Nil
53
+
}
54
+
["add", ..rest] -> {
55
+
let _ =
56
+
add_many(home_dir, rest)
57
+
|> result.map_error(describe_error)
58
+
|> result.map_error(io.println_error)
59
+
Nil
60
+
}
61
+
_ -> show_help()
62
+
}
63
+
}
64
+
65
+
// errors -----------------------------------------------------------------------
66
+
16
67
type InternalError {
17
68
FailedToCopy(path: String, error: simplifile.FileError)
18
69
FailedToRead(path: String, error: simplifile.FileError)
···
68
119
}
69
120
}
70
121
71
-
pub fn main() -> Nil {
72
-
let program_args = argv.load().arguments
73
-
let assert Ok(home_dir) = envoy.get("HOME") as "$HOME not defined"
74
-
75
-
case program_args {
76
-
["help"] -> show_help()
77
-
["new"] -> {
78
-
let _ =
79
-
setup_new(home_dir)
80
-
|> result.map_error(describe_error)
81
-
|> result.map_error(io.println_error)
82
-
83
-
Nil
84
-
}
122
+
// ------------------------------------------------------------------------------
123
+
// actions
124
+
// ------------------------------------------------------------------------------
85
125
86
-
["init", link] -> {
87
-
let _ =
88
-
init_from_link(link, home_dir)
89
-
|> result.map_error(describe_error)
90
-
|> result.map_error(io.println_error)
91
-
92
-
Nil
93
-
}
94
-
["init"] -> {
95
-
let _ =
96
-
update_symlinks(home_dir)
97
-
|> result.map_error(describe_error)
98
-
|> result.map_error(io.println_error)
99
-
100
-
Nil
101
-
}
102
-
["add", "submodule", link, path] -> {
103
-
let _ =
104
-
add_submodule(home_dir, link, path)
105
-
|> result.map_error(describe_error)
106
-
|> result.map_error(io.println_error)
107
-
Nil
108
-
}
109
-
["add", ..rest] -> {
110
-
let _ =
111
-
add_many(home_dir, rest)
112
-
|> result.map_error(describe_error)
113
-
|> result.map_error(io.println_error)
114
-
Nil
115
-
}
116
-
_ -> show_help()
117
-
}
118
-
}
126
+
// new
119
127
120
128
fn setup_new(home_dir: String) {
121
129
let path = filepath.join(home_dir, dotfiles)
···
127
135
shellout.command(run: "git", with: ["init"], in: path, opt: [])
128
136
|> result.map_error(FailedToInitRepo)
129
137
}
138
+
139
+
// init <link> ------------------------------------------------------------------
130
140
131
141
/// git clone's the provided link and then runs normal setup
132
142
///
···
145
155
|> result.map_error(FailedToCloneRepo)
146
156
}
147
157
158
+
// init -------------------------------------------------------------------------
159
+
160
+
/// loads specs from spec.json and tries to create the symlinks based on it
161
+
///
162
+
fn update_symlinks(home home: String) -> Result(List(String), InternalError) {
163
+
use specs <- result.try(
164
+
spec_path(home)
165
+
|> load_specs,
166
+
)
167
+
168
+
specs
169
+
|> list.map(make_symlink_from_spec(_, home))
170
+
|> list.map(result.map(_, string.inspect))
171
+
|> result.all()
172
+
}
173
+
174
+
// add submodule <link> ---------------------------------------------------------
175
+
148
176
fn add_submodule(home: String, link: String, config_path: String) {
149
177
use spec <- result.try(spec_from_config_path(config_path))
150
178
···
155
183
"submodule",
156
184
"add",
157
185
link,
186
+
// drop `dotfiles` from `dotfiles/dot_config/nvim`
158
187
spec.dotfiles_path |> drop_first_dir,
159
188
],
160
189
in: filepath.join(home, dotfiles),
···
226
255
}
227
256
}
228
257
229
-
/// loads specs from spec.json and tries to create the symlinks based on it
230
-
///
231
-
fn update_symlinks(home home: String) -> Result(List(String), InternalError) {
232
-
use specs <- result.try(
233
-
spec_path(home)
234
-
|> load_specs,
235
-
)
236
-
237
-
specs
238
-
|> list.map(make_symlink_from_spec(_, home))
239
-
|> list.map(result.map(_, string.inspect))
240
-
|> result.all()
241
-
}
242
-
243
-
// path manipulation ------------------------------------------------------------
244
-
245
-
fn drop_home(from) {
246
-
from
247
-
|> filepath.split()
248
-
// drop `/`, `home` and `<user>`
249
-
|> list.drop(3)
250
-
|> list.fold("", filepath.join)
251
-
}
252
-
253
258
fn to_dotfiles_path(path) {
254
259
string.split(path, on: "/")
255
260
|> list.map(string.replace(_, ".", "dot_"))
···
312
317
313
318
type Spec {
314
319
/// both without the /home/<user> for portability
315
-
/// `dotfiles_path` <- the path in `~/dotfiles/dot_config/nvim/`
320
+
/// `dotfiles_path` <- the path in `~/dotfiles/dot_config/nvim/` | does start with 'dotfiles'
316
321
/// `target_path` <- the path the config belongs in i.e. `~/.config/nvim`
317
322
///
318
323
Spec(dotfiles_path: String, target_path: String)
···
321
326
fn spec_from_config_path(path: String) -> Result(Spec, InternalError) {
322
327
use path <- result.try(case path {
323
328
"/home" <> _ -> drop_home(path) |> Ok
329
+
"/root/" <> path -> path |> Ok
324
330
_ -> Error(FileNotInHomeDirectory(path))
325
331
})
326
332
327
333
Spec(to_dotfiles_path(path), path) |> Ok
334
+
}
335
+
336
+
/// drops '/', 'home' and '<user>' from supplied path
337
+
/// uses filepath.join to reassemble the path
338
+
///
339
+
fn drop_home(from) {
340
+
from
341
+
|> filepath.split()
342
+
// drop `/`, `home` and `<user>`
343
+
|> list.drop(3)
344
+
|> list.fold("", filepath.join)
328
345
}
329
346
330
347
/// gets path of spec.json using `/home/<user>`