Read Write eXecute framework rwx.rwx.work
at dev 465 lines 10 kB view raw
1# ╭──────╮ 2# │ code │ 3# ╰──────╯ 4 5# ╭──────┬───────────╮ 6# │ code │ functions │ 7# ╰──────┴───────────╯ 8 9function alias_eval(new, name, type) { 10 text = new "() { " 11 if (type == "function") { 12 text = text name " \"${@}\"" 13 } else if (type == "variable") { 14 text = text "echo \"${" name "}\"" 15 } 16 return text "; }" 17} 18 19# TODO delete when useless 20function extract(string, type) { 21 if (type == "alias") { 22 split(string, array, "#=") 23 return strip(array[2]) 24 } else if (type == "command") { 25 split(string, array, "#/") 26 return strip(array[2]) 27 } else if (type == "doc") { 28 split(string, array, "#") 29 return strip(array[2]) 30 } else if (type == "function") { 31 split(string, array, "(") 32 return strip(array[1]) 33 } else if (type == "module") { 34 split(string, array, "#\\.") 35 return strip(array[2]) 36 } else if (type == "shebang") { 37 split(string, array, "#!") 38 return strip(array[2]) 39 } else if ((type == "constant") || (type == "variable")) { 40 split(string, array, "=") 41 return strip(array[1]) 42 } 43} 44 45# ╭──────┬───────────┬─────╮ 46# │ code │ functions │ doc │ 47# ╰──────┴───────────┴─────╯ 48 49function doc_append(string) { 50 if (doc) { 51 doc = doc "\n" 52 } 53 doc = doc string 54} 55 56function doc_output(name, type) { 57 print "↙ " type 58 print name 59 print doc 60 exit 61} 62 63function doc_reset() { 64 if (current_function == "") { 65 doc = "" 66 } 67} 68 69# ╭──────┬───────────┬─────╮ 70# │ code │ functions │ ids │ 71# ╰──────┴───────────┴─────╯ 72 73function ids_get(type) { 74 return ids[type] 75} 76 77function ids_put(type, name) { 78 if (ids[type]) { 79 ids[type] = ids[type] "\n" 80 } 81 ids[type] = ids[type] name 82} 83 84# ╭──────┬───────────┬───────╮ 85# │ code │ functions │ strip │ 86# ╰──────┴───────────┴───────╯ 87 88function strip(string, tmp) { 89 tmp = string 90 sub("^[\t ]*", "", tmp) 91 sub("[\t ]*$", "", tmp) 92 return tmp 93} 94 95function strip_first(string, sep, tmp) { 96 tmp = string 97 sub(sep, "", tmp) 98 return strip(tmp) 99} 100 101function strip_from(string, sep, tmp) { 102 split(string, tmp, sep) 103 return strip(tmp[1]) 104} 105 106function strip_function(string) { 107 return strip_from(string, "(") 108} 109 110function strip_task(string) { 111 return strip_from(strip_first(string, "#"), " ") 112} 113 114function strip_value(string) { 115 return strip_from(string, "=") 116} 117 118# ╭──────┬───────╮ 119# │ code │ begin │ 120# ╰──────┴───────╯ 121 122BEGIN { 123 124# ╭──────┬───────┬───────────╮ 125# │ code │ begin │ constants │ 126# ╰──────┴───────┴───────────╯ 127 128 RECORD_SEPARATOR = "\036" 129 UNIT_SEPARATOR = "\037" 130 131# ╭──────┬───────┬───────────┬───────╮ 132# │ code │ begin │ constants │ regex │ 133# ╰──────┴───────┴───────────┴───────╯ 134 135 RE_ANY = "(.*)" 136 RE_BEGIN = "^" 137 RE_CONST = "([_A-Z][_0-9A-Z]*)" 138 RE_SET = "=.*" 139 RE_SPACE = "[[:space:]]" 140 RE_TSK = "(FIXME|TODO)" 141 RE_VAR = "([_a-z][_0-9a-z]*)" 142 143 RE_SPACES = RE_SPACE "*" 144 145 RE_END = RE_SPACES "$" 146 RE_FUNC = RE_SPACES "\\(" RE_SPACES "\\)" RE_SPACES 147 148 re["alias"] = RE_BEGIN "#=" RE_SPACES RE_VAR RE_END 149 re["binary"] = RE_BEGIN "#\\|" RE_SPACES RE_VAR RE_END 150 RE_CLOSE = RE_BEGIN RE_ANY "}" RE_SPACES RE_END 151 re["command"] = RE_BEGIN "#/" RE_SPACES RE_VAR RE_END 152 RE_COMMENT = RE_BEGIN RE_SPACES "#" RE_ANY RE_END 153 re["constant"] = RE_BEGIN RE_CONST RE_SET RE_END 154 RE_DOC = RE_BEGIN RE_SPACES "# " RE_ANY RE_END 155 re["function"] = RE_BEGIN RE_VAR RE_FUNC RE_ANY RE_END 156 RE_MODULE = RE_BEGIN "#\\." RE_SPACES RE_ANY RE_END 157 RE_SHEBANG = RE_BEGIN "#!" RE_SPACES RE_ANY RE_END 158 RE_TASK = RE_BEGIN RE_SPACES "#" RE_SPACES RE_TSK RE_ANY RE_END 159 re["variable"] = RE_BEGIN RE_VAR RE_SET RE_END 160 161# ╭──────┬───────┬───────────╮ 162# │ code │ begin │ variables │ 163# ╰──────┴───────┴───────────╯ 164 165 current_function = "" 166 current_match = "" 167 doc = "" 168 line = 0 169 lint = "" 170 module = "" 171 172# begin 173} 174 175# ╭──────┬───────╮ 176# │ code │ parse │ 177# ╰──────┴───────╯ 178 179function parse(string, name) { 180 181 # module 182 if (match(string, RE_MODULE)) { 183 current_match = "module" 184 line = 0 185 module = strip_first(string, "#\\.") 186 doc_reset() 187 shebang = "" 188 189 # shebang 190 } else if (match(string, RE_SHEBANG)) { 191 current_match = "shebang" 192 shebang = strip_first(string, "#!") 193 194 # constant 195 } else if (match(string, re["constant"])) { 196 current_match = "constant" 197 constant = strip_value(string) 198 ids_put(current_match, constant) 199 200 # variable 201 } else if (match(string, re["variable"])) { 202 current_match = "variable" 203 variable = strip_value(string) 204 ids_put(current_match, variable) 205 206 # alias 207 } else if (match(string, re["alias"])) { 208 current_match = "alias" 209 current_alias = strip_first(string, "#=") 210 ids_put(current_match, current_alias) 211 current_aliases[current_alias] = "" 212 doc_append("= " current_alias) 213 214 # command 215 } else if (match(string, re["command"])) { 216 current_match = "command" 217 current_command = strip_first(string, "#/") 218 ids_put(current_match, current_command) 219 current_commands[current_command] = "" 220 doc_append("/ " current_command) 221 222 # function 223 } else if (match(string, re["function"])) { 224 current_match = "function" 225 current_function = strip_function(string) 226 ids_put(current_match, current_function) 227 for (name in current_aliases) { 228 aliases[name] = current_function 229 } 230 delete current_aliases 231 for (name in current_commands) { 232 commands[name] = current_function 233 } 234 delete current_commands 235 236 # task 237 } else if (match(string, RE_TASK)) { 238 current_match = "task" 239 task = strip_task(string) 240 tasks[task] = "" 241 doc_append(line " " string) 242 243 # doc 244 } else if (match(string, RE_DOC)) { 245 current_match = "doc" 246 doc_append(strip_first(string, "# ")) 247 248 # comment 249 } else if (match(string, RE_COMMENT)) { 250 current_match = "comment" 251 doc_append(string) 252 253 # other 254 } else { 255 current_match = "" 256 if (target) { 257 if (module == target) { 258 doc_output(target, "module") 259 } 260 } 261 doc_reset() 262 263 # match 264 } 265 266 # close 267 if (match(string, RE_CLOSE)) { 268 current_match = "close" 269 } 270 271} 272 273# ╭──────┬──────╮ 274# │ code │ main │ 275# ╰──────┴──────╯ 276 277{ 278 279# ╭──────┬──────┬───────╮ 280# │ code │ main │ parse │ 281# ╰──────┴──────┴───────╯ 282 283parse($0) 284 285# ╭──────┬──────┬──────╮ 286# │ code │ main │ exit │ 287# ╰──────┴──────┴──────╯ 288 289# doc 290if (action == "doc") { 291 292 # constant 293 if (current_match == "constant") { 294 if (constant == target) { 295 doc_output(constant, "constant") 296 } 297 298 # variable 299 } else if (current_match == "variable") { 300 if (variable == target) { 301 doc_output(variable, "variable") 302 } 303 304 # match 305 } 306 307 # function 308 if (current_match == "close") { 309 if (target == current_function) { 310 doc_output(current_function, "function") 311 } else if (target in aliases) { 312 print "= " target 313 doc_output(current_function, "function") 314 } else if (target in commands) { 315 print "/ " target 316 doc_output(current_function, "function") 317 } 318 } 319 320# tasks 321} else if (action == "tasks") { 322 323 # module 324 if (current_match == "module") { 325 if (output_tasks) { 326 print "" 327 print ". " module 328 print output_tasks 329 output_tasks = "" 330 } 331 doc = "" 332 match_task = 0 333 334 # task 335 } else if (current_match == "task") { 336 if (target) { 337 if (target in tasks) { 338 match_task = 1 339 } 340 } else { 341 match_task = 1 342 } 343 344 # other 345 } else { 346 if (match_task) { 347 output_tasks = output_tasks "\n" doc 348 } 349 doc = "" 350 match_task = 0 351 352 # match 353 } 354 355# function 356} else if (action == "function") { 357 358 if (current_match == "function") { 359 if (target in commands) { 360 print commands[target] 361 exit 362 } 363 } 364 365# lint 366} else if (action == "lint") { 367 368 # TODO RWX_ constant 369 # TODO rwx_ variable 370 # TODO rwx_ function 371 372 # TODO unique alias 373 if (current_match == "alias") { 374 if (alias in aliases) { 375 print "dupe: " alias 376 } 377 } 378 # TODO unique command 379 # TODO unique function 380 381# eval 382} else if (action == "eval") { 383 384# filter 385} else if (action == "filter") { 386 387# unknown 388} else { 389 print "unknown action: " action 390 exit 1 391 392# action 393} 394 395# ╭──────┬──────┬──────╮ 396# │ code │ main │ next │ 397# ╰──────┴──────┴──────╯ 398 399 # constant 400 if (current_match == "constant") { 401 doc_reset() 402 constant = "" 403 404 # variable 405 } else if (current_match == "variable") { 406 doc_reset() 407 variable = "" 408 409 # alias 410 } else if (current_match == "alias") { 411 current_alias = "" 412 413 # command 414 } else if (current_match == "command") { 415 current_command = "" 416 417 # task 418 } else if (current_match == "task") { 419 task = "" 420 421 # close 422 } else if (current_match == "close") { 423 doc_reset() 424 current_function = "" 425 426 # match 427 } 428 429 # next 430 line++ 431 432# main 433} 434 435# ╭──────┬─────╮ 436# │ code │ end │ 437# ╰──────┴─────╯ 438 439END { 440 441 # eval 442 if (action == "eval") { 443 if (target == "alias") { 444 for (eval in aliases) { 445 print alias_eval(eval, aliases[eval], "function") 446 } 447 } else if (target == "command") { 448 for (eval in commands) { 449 print alias_eval(eval, commands[eval], "function") 450 } 451 } 452 453 # filter 454 } else if (action == "filter") { 455 print ids_get(target) 456 457 # lint 458 } else if (action == "lint") { 459 print lint 460 461 # action 462 } 463 464# end 465}