rwx/sh/core/code.awk

382 lines
7.4 KiB
Awk
Raw Normal View History

2025-08-02 22:39:23 +02:00
# ╭──────╮
# │ code │
# ╰──────╯
2025-08-02 01:19:38 +02:00
2025-08-02 22:39:23 +02:00
# ╭──────┬───────────╮
# │ code │ functions │
# ╰──────┴───────────╯
2025-08-02 02:57:21 +02:00
2025-08-02 20:03:36 +02:00
function alias_eval(new, name, type) {
text = new "() { "
2025-08-02 01:19:38 +02:00
if (type == "function") {
text = text name " \"${@}\""
} else if (type == "variable") {
text = text "echo \"${" name "}\""
}
print text "; }"
2025-07-13 18:56:54 +02:00
}
2025-08-02 15:59:43 +02:00
# TODO delete when useless
2025-07-13 18:56:54 +02:00
function extract(string, type) {
2025-08-02 01:19:38 +02:00
if (type == "alias") {
split(string, array, "#=")
2025-08-02 20:20:19 +02:00
return strip(array[2])
2025-08-02 01:19:38 +02:00
} else if (type == "command") {
split(string, array, "#/")
2025-08-02 20:20:19 +02:00
return strip(array[2])
2025-08-02 01:19:38 +02:00
} else if (type == "doc") {
split(string, array, "#")
2025-08-02 20:20:19 +02:00
return strip(array[2])
2025-08-02 01:19:38 +02:00
} else if (type == "function") {
split(string, array, "(")
2025-08-02 20:20:19 +02:00
return strip(array[1])
2025-08-02 01:19:38 +02:00
} else if (type == "module") {
split(string, array, "#\\.")
2025-08-02 20:20:19 +02:00
return strip(array[2])
2025-08-02 01:19:38 +02:00
} else if (type == "shebang") {
split(string, array, "#!")
2025-08-02 20:20:19 +02:00
return strip(array[2])
2025-08-02 01:19:38 +02:00
} else if ((type == "constant") || (type == "variable")) {
split(string, array, "=")
2025-08-02 20:20:19 +02:00
return strip(array[1])
2025-08-02 01:19:38 +02:00
}
2025-07-11 15:52:38 +02:00
}
2025-08-02 22:39:23 +02:00
# ╭──────┬───────────┬─────╮
# │ code │ functions │ doc │
# ╰──────┴───────────┴─────╯
function doc_append(string) {
if (doc) {
doc = doc "\n"
}
doc = doc string
}
function doc_output(name, type) {
print "↙ " type
print name
print doc
exit
}
function doc_reset() {
if (current_function == "") {
doc = ""
}
}
# ╭──────┬───────────┬───────╮
# │ code │ functions │ strip │
# ╰──────┴───────────┴───────╯
2025-08-02 20:20:19 +02:00
function strip(string, tmp) {
tmp = string
sub("^[\t ]*", "", tmp)
sub("[\t ]*$", "", tmp)
return tmp
}
2025-08-02 20:01:43 +02:00
function strip_first(string, sep, tmp) {
2025-08-02 17:22:13 +02:00
tmp = string
2025-08-02 20:01:43 +02:00
sub(sep, "", tmp)
2025-08-02 20:20:19 +02:00
return strip(tmp)
2025-08-02 17:22:13 +02:00
}
2025-08-02 17:59:47 +02:00
function strip_from(string, sep, tmp) {
split(string, tmp, sep)
2025-08-02 20:20:19 +02:00
return strip(tmp[1])
2025-08-02 17:59:47 +02:00
}
2025-08-02 17:57:11 +02:00
2025-08-02 21:49:07 +02:00
function strip_function(string) {
2025-08-02 17:59:47 +02:00
return strip_from(string, "(")
2025-08-02 17:57:11 +02:00
}
2025-08-02 21:49:07 +02:00
function strip_task(string) {
return strip_from(strip_first(string, "#"), " ")
}
function strip_value(string) {
2025-08-02 17:59:47 +02:00
return strip_from(string, "=")
2025-08-02 17:50:04 +02:00
}
2025-08-02 22:39:23 +02:00
# ╭──────┬───────╮
# │ code │ begin │
# ╰──────┴───────╯
2025-07-06 03:16:41 +02:00
BEGIN {
2025-08-02 02:57:21 +02:00
RE_ANY = "(.*)"
RE_BEGIN = "^"
RE_CONST = "([_A-Z][_0-9A-Z]*)"
RE_SET = "=.*"
RE_SPACE = "[[:space:]]"
RE_TSK = "(FIXME|TODO)"
RE_VAR = "([_a-z][_0-9a-z]*)"
RE_SPACES = RE_SPACE "*"
RE_END = RE_SPACES "$"
RE_FUNC = RE_SPACES "\\(" RE_SPACES "\\)" RE_SPACES "{"
re["alias"] = RE_BEGIN "#=" RE_SPACES RE_VAR RE_END
re["binary"] = RE_BEGIN "#\\|" RE_SPACES RE_VAR RE_END
RE_CLOSE = RE_BEGIN "}" RE_SPACES RE_END
re["command"] = RE_BEGIN "#/" RE_SPACES RE_VAR RE_END
2025-08-02 21:49:07 +02:00
RE_COMMENT = RE_BEGIN RE_SPACES "# " RE_ANY RE_END
2025-08-02 02:57:21 +02:00
re["constant"] = RE_BEGIN RE_CONST RE_SET RE_END
2025-08-02 21:49:07 +02:00
RE_DOC = RE_BEGIN "# " RE_ANY RE_END
2025-08-02 02:57:21 +02:00
re["function"] = RE_BEGIN RE_VAR RE_FUNC RE_END
RE_MODULE = RE_BEGIN "#\\." RE_SPACES RE_ANY RE_END
RE_SHEBANG = RE_BEGIN "#!" RE_SPACES RE_ANY RE_END
RE_TASK = RE_BEGIN RE_SPACES "#" RE_SPACES RE_TSK RE_ANY RE_END
re["variable"] = RE_BEGIN RE_VAR RE_SET RE_END
2025-08-03 00:13:39 +02:00
doc = ""
2025-08-02 23:59:28 +02:00
line = 0
2025-08-03 00:13:39 +02:00
module = ""
2025-08-02 23:59:28 +02:00
2025-07-06 03:16:41 +02:00
}
2025-08-02 22:39:23 +02:00
# ╭──────┬───────╮
# │ code │ parse │
# ╰──────┴───────╯
2025-08-02 10:29:33 +02:00
function parse(string) {
2025-08-02 15:56:48 +02:00
2025-08-02 15:49:52 +02:00
# module
if (match(string, RE_MODULE)) {
current_match = "module"
2025-08-02 19:59:55 +02:00
line = 0
2025-08-02 18:01:09 +02:00
module = strip_first(string, "#\\.")
2025-08-02 15:59:43 +02:00
doc_reset()
2025-08-02 15:49:52 +02:00
shebang = ""
2025-08-02 15:56:48 +02:00
2025-08-02 15:49:52 +02:00
# shebang
} else if (match(string, RE_SHEBANG)) {
current_match = "shebang"
2025-08-02 18:01:09 +02:00
shebang = strip_first(string, "#!")
2025-08-02 15:56:48 +02:00
2025-08-02 17:50:04 +02:00
# constant
} else if (match(string, re["constant"])) {
current_match = "constant"
constant = strip_value(string)
# variable
} else if (match(string, re["variable"])) {
current_match = "variable"
variable = strip_value(string)
2025-08-02 17:15:23 +02:00
# alias
} else if (match(string, re["alias"])) {
current_match = "alias"
2025-08-02 18:01:09 +02:00
alias = strip_first(string, "#=")
2025-08-02 17:15:23 +02:00
aliases[alias] = ""
doc_append("= " alias)
# command
} else if (match(string, re["command"])) {
current_match = "command"
2025-08-02 18:01:09 +02:00
command = strip_first(string, "#/")
2025-08-02 17:15:23 +02:00
commands[command] = ""
doc_append("/ " command)
2025-08-02 17:57:11 +02:00
# function
} else if (match(string, re["function"])) {
current_match = "function"
current_function = strip_function(string)
2025-08-02 21:49:07 +02:00
# task
} else if (match(string, RE_TASK)) {
current_match = "task"
task = strip_task(string)
tasks[task] = ""
2025-08-02 22:14:49 +02:00
doc_append(line " " string)
2025-08-02 21:49:07 +02:00
2025-08-02 19:54:43 +02:00
# doc
} else if (match(string, RE_DOC)) {
2025-08-02 21:49:07 +02:00
doc_append(strip_first(string, "# "))
# comment
} else if (match(string, RE_COMMENT)) {
doc_append(string)
2025-08-02 19:54:43 +02:00
2025-08-02 15:49:52 +02:00
# other
} else {
2025-08-02 16:11:00 +02:00
if (module == target) {
2025-08-02 16:02:56 +02:00
doc_output(target, "module")
2025-08-02 15:49:52 +02:00
} else {
2025-08-02 15:59:43 +02:00
doc_reset()
2025-08-02 15:49:52 +02:00
}
2025-08-02 19:47:53 +02:00
}
2025-08-02 22:39:23 +02:00
# close
2025-08-02 19:47:53 +02:00
if (match(string, RE_CLOSE)) {
current_match = "close"
2025-08-02 15:49:52 +02:00
}
2025-08-02 15:56:48 +02:00
2025-08-02 10:29:33 +02:00
}
2025-08-02 22:39:23 +02:00
# ╭──────┬──────╮
# │ code │ main │
# ╰──────┴──────╯
2025-07-06 03:16:41 +02:00
{
2025-08-02 02:57:21 +02:00
2025-08-02 10:45:32 +02:00
# doc
2025-08-02 10:55:38 +02:00
if (action == "doc") {
2025-08-02 15:49:52 +02:00
parse($0)
2025-08-02 19:47:53 +02:00
2025-08-02 17:50:04 +02:00
# constant
2025-08-02 19:54:43 +02:00
if (current_match == "constant") {
2025-08-02 17:50:04 +02:00
if (constant == target) {
doc_output(constant, "constant")
2025-08-02 02:57:21 +02:00
} else {
2025-08-02 15:59:43 +02:00
doc_reset()
2025-08-02 17:50:04 +02:00
constant = ""
2025-08-02 02:57:21 +02:00
}
2025-08-02 19:47:53 +02:00
2025-08-02 17:50:04 +02:00
# variable
} else if (current_match == "variable") {
if (variable == target) {
doc_output(variable, "variable")
2025-08-02 01:19:38 +02:00
} else {
2025-08-02 15:59:43 +02:00
doc_reset()
2025-08-02 17:50:04 +02:00
variable = ""
2025-08-02 01:19:38 +02:00
}
2025-08-02 19:47:53 +02:00
2025-08-02 22:39:23 +02:00
# match
2025-08-02 19:47:53 +02:00
}
# function
if (current_match == "close") {
if (target == current_function) {
doc_output(current_function, "function")
} else if (target in aliases) {
2025-08-02 02:57:21 +02:00
print "= " target
2025-08-02 16:11:00 +02:00
doc_output(current_function, "function")
2025-08-02 19:47:53 +02:00
} else if (target in commands) {
2025-08-02 02:57:21 +02:00
print "/ " target
2025-08-02 16:11:00 +02:00
doc_output(current_function, "function")
2025-08-02 02:57:21 +02:00
} else {
2025-08-02 16:11:00 +02:00
current_function = ""
2025-08-02 15:59:43 +02:00
doc_reset()
2025-08-02 02:57:21 +02:00
}
2025-08-02 01:19:38 +02:00
}
2025-07-08 15:26:34 +02:00
2025-08-02 10:55:38 +02:00
# tasks
} else if (action == "tasks") {
2025-08-02 21:49:07 +02:00
parse($0)
# module
if (current_match == "module") {
2025-08-02 10:55:38 +02:00
if (output_tasks) {
print ""
2025-08-02 21:49:07 +02:00
print ". " module
2025-08-02 10:55:38 +02:00
print output_tasks
output_tasks = ""
}
doc = ""
match_task = 0
2025-08-02 21:49:07 +02:00
# task
} else if (current_match == "task") {
2025-08-02 10:55:38 +02:00
if (target) {
2025-08-02 21:49:07 +02:00
if (target in tasks) {
2025-08-02 10:55:38 +02:00
match_task = 1
}
} else {
match_task = 1
}
2025-08-02 21:49:07 +02:00
# other
2025-08-02 10:55:38 +02:00
} else {
if (match_task) {
output_tasks = output_tasks "\n" doc
}
doc = ""
match_task = 0
2025-08-02 21:49:07 +02:00
2025-08-02 22:39:23 +02:00
# match
2025-08-02 10:55:38 +02:00
}
2025-08-02 10:53:45 +02:00
# function
} else if (action == "function") {
if (match($0, re["command"])) {
2025-08-02 15:56:48 +02:00
doc_append(extract($0, "command"))
2025-08-02 10:53:45 +02:00
} else if (match($0, re["function"])) {
split(doc, array, "\n")
for (item in array) {
if (array[item] == target) {
print extract($0, "function")
exit
}
}
2025-08-02 15:59:43 +02:00
doc_reset()
2025-08-02 10:53:45 +02:00
} else {
2025-08-02 15:59:43 +02:00
doc_reset()
2025-08-02 10:53:45 +02:00
}
# eval
} else if (action == "eval") {
if (match($0, re[target])) {
2025-08-02 15:56:48 +02:00
doc_append(extract($0, target))
2025-08-02 10:53:45 +02:00
} else if (match($0, re["function"])) {
split(doc, array, "\n")
for (item in array) {
alias_eval(array[item], extract($0, "function"), "function")
}
2025-08-02 15:59:43 +02:00
doc_reset()
2025-08-02 10:53:45 +02:00
} else {
2025-08-02 15:59:43 +02:00
doc_reset()
2025-08-02 10:53:45 +02:00
}
2025-08-02 10:45:32 +02:00
# filter
} else if (action == "filter") {
if (match($0, re[target])) {
unique[extract($0, target)] = ""
}
2025-08-02 23:30:12 +02:00
# lint
} else if (action == "lint") {
2025-08-03 00:00:44 +02:00
parse($0)
2025-08-02 23:30:12 +02:00
2025-08-02 23:58:04 +02:00
# TODO RWX_ constant
# TODO rwx_ variable
# TODO rwx_ function
# TODO unique alias
# TODO unique command
# TODO unique function
2025-08-02 11:23:31 +02:00
# unknown
} else {
print "unknown action: " action
exit 1
2025-08-02 22:39:23 +02:00
# action
2025-08-02 02:57:21 +02:00
}
2025-08-02 22:39:23 +02:00
# main
2025-08-02 19:59:55 +02:00
line++
2025-08-02 10:45:32 +02:00
}
2025-08-02 02:57:21 +02:00
2025-08-02 22:39:23 +02:00
# ╭──────┬─────╮
# │ code │ end │
# ╰──────┴─────╯
2025-07-08 15:26:34 +02:00
END {
2025-08-02 02:57:21 +02:00
2025-08-02 10:45:32 +02:00
# filter
2025-08-02 02:57:21 +02:00
if (action == "filter") {
for (item in unique) {
print item
2025-08-02 01:19:38 +02:00
}
2025-08-02 10:45:32 +02:00
2025-08-02 22:39:23 +02:00
# action
2025-07-08 15:26:34 +02:00
}
2025-08-02 02:57:21 +02:00
2025-08-02 22:39:23 +02:00
# end
2025-08-02 02:57:21 +02:00
}