Helps centralize dotfiles to a single repository

handle root properly. and rearrange some code

nuv e2f2f10e 85e05125

Changed files
+89 -72
src
+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>`