about summary refs log tree commit diff stats
path: root/templates
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-04-02 01:30:07 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-04-02 01:30:07 +0200
commitb9a7a8cefd304ae590fd7ac0c5d4cb4ffe030648 (patch)
treec3d655f3dfc6fff416b53b58c0750ebbc2452ff7 /templates
parentfeat(treewide): Use new `%INIT_` variables (diff)
downloadflake-templates-b9a7a8cefd304ae590fd7ac0c5d4cb4ffe030648.tar.gz
flake-templates-b9a7a8cefd304ae590fd7ac0c5d4cb4ffe030648.zip
chore(treewide): Update and format files
Diffstat (limited to 'templates')
-rw-r--r--templates/awk/README.md1
-rwxr-xr-xtemplates/awk/init71
-rw-r--r--templates/awk/shell_line_editor.sh247
-rw-r--r--templates/c/README.md1
-rwxr-xr-xtemplates/c/init71
-rw-r--r--templates/c/shell_line_editor.sh247
-rw-r--r--templates/latex/README.md1
-rwxr-xr-xtemplates/latex/init71
-rw-r--r--templates/latex/shell_line_editor.sh247
-rw-r--r--templates/rust/README.md1
-rwxr-xr-xtemplates/rust/init71
-rw-r--r--templates/rust/shell_line_editor.sh247
-rw-r--r--templates/shell/README.md1
-rwxr-xr-xtemplates/shell/init71
-rw-r--r--templates/shell/shell_line_editor.sh247
15 files changed, 1595 insertions, 0 deletions
diff --git a/templates/awk/README.md b/templates/awk/README.md
index 79f2a41..46287a6 100644
--- a/templates/awk/README.md
+++ b/templates/awk/README.md
@@ -1,4 +1,5 @@
 # %INIT_APPLICATION_NAME_STYLIZED
+
 > %INIT_DESCRIPTION
 
 Some text about the project.
diff --git a/templates/awk/init b/templates/awk/init
new file mode 100755
index 0000000..787b663
--- /dev/null
+++ b/templates/awk/init
@@ -0,0 +1,71 @@
+#!/usr/bin/env sh
+
+. "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+
+replacement_file="$(mktemp)"
+
+trap cleanup INT
+trap "cleanup; remove" EXIT
+cleanup() {
+    rm "$replacement_file"
+}
+remove() {
+    rm "$(realpath "$0")"
+    rm "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+    git add .
+}
+
+# Prompt the user for a specific variable. The variable is the first
+# input, the second is an optional description.
+# The third argument can be a suggested answer, already pre populated.
+prompt() {
+    pr_variable_upper="$(echo "$1" | sed 's/\([a-z]\)/\U\1/')"
+    pr_description="$2"
+    pr_suggested_answer="$3"
+
+    printf "\033[94;1mEnter %s\033[0m" "$pr_variable_upper"
+    if [ -n "$pr_description" ];then
+        printf " (\033[93;1m%s\033[0m):\n" "$pr_description"
+    else
+        printf ":\n"
+    fi
+
+    # LE "> " 0 " " "$pr_suggested_answer" "yes_please_produce_debug_output"
+    LE "> " 0 " " "$pr_suggested_answer" ""
+
+    pr_new_variable="$(printf '%s="%s"' "$pr_variable_upper" "$REPLY")"
+
+    eval "$pr_new_variable"
+    printf "%s\n" "$pr_new_variable" >> "$replacement_file"
+}
+
+git init
+
+# necessary meta data
+prompt APPLICATION_NAME "The name of the application" "$(basename "$PWD")"
+prompt APPLICATION_NAME_STYLIZED "The stylized name of the application (for documentation)" "$(basename "$PWD" | sed 's/\([a-z]\)/\u\1/')"
+prompt AUTHOR_NAME "The name of the author (or authors)" "$(git config --get user.name)"
+prompt AUTHOR_EMAIL "The email of the author (or authors)" "$(git config --get user.email)"
+
+# cog change-log variables
+prompt REMOTE "The remote, this project will be pushed to" "codeberg.org"
+prompt REPOSITORY "The name of the repository in the remote" "$APPLICATION_NAME"
+prompt OWNER "The name of owner of the repository" "$AUTHOR_NAME"
+
+# nice meta data
+prompt DESCRIPTION "The description of this project" "[can be empty]"
+
+# LICENSE.spdx data (source: https://github.com/david-a-wheeler/spdx-tutorial)
+prompt APPLICATION_ORIGINATOR "The person or organization from whom the package originally came" "$AUTHOR_NAME"
+prompt APPLICATION_HOME_PAGE "The package's home page URL" "https://$REMOTE/$OWNER/$REPOSITORY"
+
+echo "$DESCRIPTION" > .git/description
+
+while read -r var; do
+    var_name="${var%=*}"
+    var_value="${var#*=\"}"
+    var_value="${var_value%\"}"
+
+    fd . --hidden --type file --exec sed --in-place "s|%\bINIT_$var_name\b|$var_value|"
+done < "$replacement_file"
+# vim: ft=sh
diff --git a/templates/awk/shell_line_editor.sh b/templates/awk/shell_line_editor.sh
new file mode 100644
index 0000000..8d6833a
--- /dev/null
+++ b/templates/awk/shell_line_editor.sh
@@ -0,0 +1,247 @@
+#! /usr/bin/env sh
+# Taken in verbatim from: https://unix.stackexchange.com/a/113450, and somewhat changed
+
+LE_print_debug() {
+    LE_debug="$1"
+    LE_debug_msg="$2"
+    [ -n "$LE_debug" ] && printf "\nDBG: (%s)\n" "$LE_debug_msg" >outfile.debug
+}
+
+LE() {
+    # Shell Line Editor. Extremely slow and stupid code. However it
+    # should work on ansi/vt100/linux derived terminals on POSIX
+    # systems.
+    # Understands some emacs key bindings: CTRL-(A,B,D,E,F,H,K,L)
+    # plus the CTRL-W and CTRL-U normal killword and kill.
+    # no Meta-X key, but handling of <Left>, <Right>, <Home>, <End>
+    # <Suppr>.
+    #
+    # Args:
+    #  [1]: prompt (\x sequences recognized, defaults to "")
+    #  [2]: max input length (unlimited if < 0, (default))
+    #  [3]: fill character when erasing (defaults to space)
+    #  [4]: initial value.
+    #  [5]: whether to output debugfiles (outfile.debug and outfile.raw.debug)
+    # Returns:
+    #  0: OK
+    #  1: od(d) error or CTRL-C hit
+
+    LE_prompt="$1"
+    LE_max=${2--1}
+    LE_fill=${3-" "}
+    LE_debug="$5"
+
+    LE_backward() {
+        LE_substract="$1"
+        while [ -n "$LE_substract" ]; do
+            printf '\b%s' "$2"
+            LE_substract=${LE_substract%?}
+        done
+    }
+
+    LE_fill() {
+        LE_substract="$1"
+        while [ -n "$LE_substract" ]; do
+            printf '%s' "$LE_fill"
+            LE_substract=${LE_substract%?}
+        done
+    }
+
+    # Used but not right now
+    # shellcheck disable=2016
+    LE_restore='stty "$LE_tty"
+              LC_COLLATE='${LC_COLLATE-"; unset LC_COLLATE"}
+
+    # LE_tty is used in the restore above
+    # shellcheck disable=2034
+    LE_ret=1 LE_tty=$(stty -g) LC_COLLATE=C
+
+    # text on the right of the cursor
+    LE_left=$4
+    # text on the left of the cursor
+    LE_right=''
+
+    # Tell the terminal to show us every char inputted
+    stty -icanon -echo -isig min 3 time 1 -istrip
+    printf '%b%s' "$LE_prompt" "$LE_left"
+
+    # clear the output
+    [ -n "$LE_debug" ] && printf "" >outfile.debug
+    [ -n "$LE_debug" ] && printf "" >outfile.raw.debug
+
+    # The value needs to be split for it to work (and it's either way just numbers)
+    # shellcheck disable=2046
+    while set -- $(dd bs=3 count=1 2>/dev/null | od -vAn -to1); do
+        while [ "$#" -gt 0 ]; do
+            [ -n "$LE_debug" ] && printf "%b" "\0$1" >>outfile.debug
+            [ -n "$LE_debug" ] && printf "%s " "$1" >>outfile.raw.debug
+            LE_current_key=$1
+            shift
+
+            # 033 is ^[ (`printf "\\$1\n" | cat -v`)
+            if [ "$LE_current_key" = 033 ]; then
+                case "$1$2$3" in
+                # [ C | O C -> ^F forward
+                133103* | 117103*)
+                    shift 2
+                    LE_current_key=006
+                    ;;
+                # [ D | O D -> ^B backward
+                133104* | 117104*)
+                    shift 2
+                    LE_current_key=002
+                    ;;
+                # [ H | O H -> ^A beginning of line
+                133110* | 117110*)
+                    shift 2
+                    LE_current_key=001
+                    ;;
+                # [ P | O P -> ^D del char
+                133120* | 117120*)
+                    shift 2
+                    LE_current_key=004
+                    ;;
+                # [ F | O F -> ^E end of line
+                133106* | 117106*)
+                    shift 2
+                    LE_current_key=005
+                    ;;
+                # [ 1 ~ -> ^A beginning of line
+                133061176)
+                    shift 3
+                    LE_current_key=001
+                    ;;
+                # [ 4 ~ -> ^E end of line
+                133064176)
+                    shift 3
+                    LE_current_key=005
+                    ;;
+                # [ 3 ~ -> ^D del char
+                133063176)
+                    shift 3
+                    LE_current_key=004
+                    ;;
+                # [ | O
+                133* | 117*)
+                    shift
+                    # Is $1 in ge 0 AND le 9 OR eq ';'?
+                    # These are control sequences for things like colors; Ignore them
+                    while [ "0$1" -ge 060 ] && [ "0$1" -le 071 ] ||
+                        [ "0$1" -eq 073 ]; do
+                        shift
+                    done
+                    ;;
+                esac
+            fi
+
+            case "$LE_current_key" in
+            001) # ^A beginning of line
+                LE_backward "$LE_left"
+                LE_right="$LE_left$LE_right"
+                LE_left=
+                ;;
+            002) # ^B backward
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "backward with empty left"
+                else
+                    printf '\b'
+                    LE_tmp="${LE_left%?}"
+                    LE_right="${LE_left#"$LE_tmp"}$LE_right"
+                    LE_left="$LE_tmp"
+                fi ;;
+            003) # CTRL-C
+                break 2 ;;
+            004) # ^D del char
+                if [ "$LE_right" = "" ]; then
+                    # bell (tell the user that the line is empty)
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "delete with empty right"
+                else
+                    LE_right="${LE_right#?}"
+                    printf '%s\b' "$LE_right$LE_fill"
+                    LE_backward "$LE_right"
+                fi ;;
+            012 | 015) # NL or CR
+                LE_ret=0
+                break 2
+                ;;
+            005) # ^E end of line
+                printf '%s' "$LE_right"
+                LE_left="$LE_left$LE_right"
+                LE_right=
+                ;;
+            006) # ^F forward
+                if [ "$LE_right" = "" ]; then
+                    # bell (tell the user that the line is empty)
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "forward with empty right"
+                else
+                    LE_tmp="${LE_right#?}"
+                    LE_left="$LE_left${LE_right%"$LE_tmp"}"
+                    printf %s "${LE_right%"$LE_tmp"}"
+                    LE_right="$LE_tmp"
+                fi ;;
+            010 | 177) # backspace or del
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "backspace with empty left"
+                else
+                    printf '\b%s\b' "$LE_right$LE_fill"
+                    LE_backward "$LE_right"
+                    LE_left="${LE_left%?}"
+                fi ;;
+            013) # ^K kill to end of line
+                LE_fill "$LE_right"
+                LE_backward "$LE_right"
+                LE_right=""
+                ;;
+            014) # ^L redraw
+                printf '\r%b%s' "$LE_prompt" "$LE_left$LE_right"
+                LE_backward "$LE_right"
+                ;;
+            025) # ^U kill line
+                LE_backward "$LE_left"
+                LE_fill "$LE_left$LE_right"
+                LE_backward "$LE_left$LE_right"
+                LE_left=""
+                LE_right=""
+                ;;
+            027) # ^W kill word
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                else
+                    LE_tmp="${LE_left% *}"
+                    LE_backward "${LE_left#"$LE_tmp"}"
+                    LE_fill "${LE_left#"$LE_tmp"}"
+                    LE_backward "${LE_left#"$LE_tmp"}"
+                    LE_left="$LE_tmp"
+                fi ;;
+            # Print the received key, as it did not match a special key
+            [02][4-7]? | [13]??) # 040 -> 177, 240 -> 377
+                # was assuming iso8859-x at the time
+                if [ "$LE_max" -gt 0 ] && LE_tmp="$LE_left$LE_right" &&
+                    [ "${#LE_tmp}" -eq "$LE_max" ]; then
+                    # bell, when the user is trying to cross the line limit
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "max output reached"
+                else
+                    LE_left="$LE_left$(printf '%b' "\0$LE_current_key")"
+                    printf '%b%s' "\0$LE_current_key" "$LE_right"
+                    LE_backward "$LE_right"
+                fi ;;
+            *)
+                LE_print_debug "$LE_debug" "key not recognized: $(printf "%b" "\0$LE_current_key")"
+                printf '\a'
+                ;;
+            esac
+        done
+    done
+    eval "$LE_restore"
+    REPLY=$LE_left$LE_right
+    echo
+    return "$LE_ret"
+}
diff --git a/templates/c/README.md b/templates/c/README.md
index 79f2a41..46287a6 100644
--- a/templates/c/README.md
+++ b/templates/c/README.md
@@ -1,4 +1,5 @@
 # %INIT_APPLICATION_NAME_STYLIZED
+
 > %INIT_DESCRIPTION
 
 Some text about the project.
diff --git a/templates/c/init b/templates/c/init
new file mode 100755
index 0000000..787b663
--- /dev/null
+++ b/templates/c/init
@@ -0,0 +1,71 @@
+#!/usr/bin/env sh
+
+. "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+
+replacement_file="$(mktemp)"
+
+trap cleanup INT
+trap "cleanup; remove" EXIT
+cleanup() {
+    rm "$replacement_file"
+}
+remove() {
+    rm "$(realpath "$0")"
+    rm "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+    git add .
+}
+
+# Prompt the user for a specific variable. The variable is the first
+# input, the second is an optional description.
+# The third argument can be a suggested answer, already pre populated.
+prompt() {
+    pr_variable_upper="$(echo "$1" | sed 's/\([a-z]\)/\U\1/')"
+    pr_description="$2"
+    pr_suggested_answer="$3"
+
+    printf "\033[94;1mEnter %s\033[0m" "$pr_variable_upper"
+    if [ -n "$pr_description" ];then
+        printf " (\033[93;1m%s\033[0m):\n" "$pr_description"
+    else
+        printf ":\n"
+    fi
+
+    # LE "> " 0 " " "$pr_suggested_answer" "yes_please_produce_debug_output"
+    LE "> " 0 " " "$pr_suggested_answer" ""
+
+    pr_new_variable="$(printf '%s="%s"' "$pr_variable_upper" "$REPLY")"
+
+    eval "$pr_new_variable"
+    printf "%s\n" "$pr_new_variable" >> "$replacement_file"
+}
+
+git init
+
+# necessary meta data
+prompt APPLICATION_NAME "The name of the application" "$(basename "$PWD")"
+prompt APPLICATION_NAME_STYLIZED "The stylized name of the application (for documentation)" "$(basename "$PWD" | sed 's/\([a-z]\)/\u\1/')"
+prompt AUTHOR_NAME "The name of the author (or authors)" "$(git config --get user.name)"
+prompt AUTHOR_EMAIL "The email of the author (or authors)" "$(git config --get user.email)"
+
+# cog change-log variables
+prompt REMOTE "The remote, this project will be pushed to" "codeberg.org"
+prompt REPOSITORY "The name of the repository in the remote" "$APPLICATION_NAME"
+prompt OWNER "The name of owner of the repository" "$AUTHOR_NAME"
+
+# nice meta data
+prompt DESCRIPTION "The description of this project" "[can be empty]"
+
+# LICENSE.spdx data (source: https://github.com/david-a-wheeler/spdx-tutorial)
+prompt APPLICATION_ORIGINATOR "The person or organization from whom the package originally came" "$AUTHOR_NAME"
+prompt APPLICATION_HOME_PAGE "The package's home page URL" "https://$REMOTE/$OWNER/$REPOSITORY"
+
+echo "$DESCRIPTION" > .git/description
+
+while read -r var; do
+    var_name="${var%=*}"
+    var_value="${var#*=\"}"
+    var_value="${var_value%\"}"
+
+    fd . --hidden --type file --exec sed --in-place "s|%\bINIT_$var_name\b|$var_value|"
+done < "$replacement_file"
+# vim: ft=sh
diff --git a/templates/c/shell_line_editor.sh b/templates/c/shell_line_editor.sh
new file mode 100644
index 0000000..8d6833a
--- /dev/null
+++ b/templates/c/shell_line_editor.sh
@@ -0,0 +1,247 @@
+#! /usr/bin/env sh
+# Taken in verbatim from: https://unix.stackexchange.com/a/113450, and somewhat changed
+
+LE_print_debug() {
+    LE_debug="$1"
+    LE_debug_msg="$2"
+    [ -n "$LE_debug" ] && printf "\nDBG: (%s)\n" "$LE_debug_msg" >outfile.debug
+}
+
+LE() {
+    # Shell Line Editor. Extremely slow and stupid code. However it
+    # should work on ansi/vt100/linux derived terminals on POSIX
+    # systems.
+    # Understands some emacs key bindings: CTRL-(A,B,D,E,F,H,K,L)
+    # plus the CTRL-W and CTRL-U normal killword and kill.
+    # no Meta-X key, but handling of <Left>, <Right>, <Home>, <End>
+    # <Suppr>.
+    #
+    # Args:
+    #  [1]: prompt (\x sequences recognized, defaults to "")
+    #  [2]: max input length (unlimited if < 0, (default))
+    #  [3]: fill character when erasing (defaults to space)
+    #  [4]: initial value.
+    #  [5]: whether to output debugfiles (outfile.debug and outfile.raw.debug)
+    # Returns:
+    #  0: OK
+    #  1: od(d) error or CTRL-C hit
+
+    LE_prompt="$1"
+    LE_max=${2--1}
+    LE_fill=${3-" "}
+    LE_debug="$5"
+
+    LE_backward() {
+        LE_substract="$1"
+        while [ -n "$LE_substract" ]; do
+            printf '\b%s' "$2"
+            LE_substract=${LE_substract%?}
+        done
+    }
+
+    LE_fill() {
+        LE_substract="$1"
+        while [ -n "$LE_substract" ]; do
+            printf '%s' "$LE_fill"
+            LE_substract=${LE_substract%?}
+        done
+    }
+
+    # Used but not right now
+    # shellcheck disable=2016
+    LE_restore='stty "$LE_tty"
+              LC_COLLATE='${LC_COLLATE-"; unset LC_COLLATE"}
+
+    # LE_tty is used in the restore above
+    # shellcheck disable=2034
+    LE_ret=1 LE_tty=$(stty -g) LC_COLLATE=C
+
+    # text on the right of the cursor
+    LE_left=$4
+    # text on the left of the cursor
+    LE_right=''
+
+    # Tell the terminal to show us every char inputted
+    stty -icanon -echo -isig min 3 time 1 -istrip
+    printf '%b%s' "$LE_prompt" "$LE_left"
+
+    # clear the output
+    [ -n "$LE_debug" ] && printf "" >outfile.debug
+    [ -n "$LE_debug" ] && printf "" >outfile.raw.debug
+
+    # The value needs to be split for it to work (and it's either way just numbers)
+    # shellcheck disable=2046
+    while set -- $(dd bs=3 count=1 2>/dev/null | od -vAn -to1); do
+        while [ "$#" -gt 0 ]; do
+            [ -n "$LE_debug" ] && printf "%b" "\0$1" >>outfile.debug
+            [ -n "$LE_debug" ] && printf "%s " "$1" >>outfile.raw.debug
+            LE_current_key=$1
+            shift
+
+            # 033 is ^[ (`printf "\\$1\n" | cat -v`)
+            if [ "$LE_current_key" = 033 ]; then
+                case "$1$2$3" in
+                # [ C | O C -> ^F forward
+                133103* | 117103*)
+                    shift 2
+                    LE_current_key=006
+                    ;;
+                # [ D | O D -> ^B backward
+                133104* | 117104*)
+                    shift 2
+                    LE_current_key=002
+                    ;;
+                # [ H | O H -> ^A beginning of line
+                133110* | 117110*)
+                    shift 2
+                    LE_current_key=001
+                    ;;
+                # [ P | O P -> ^D del char
+                133120* | 117120*)
+                    shift 2
+                    LE_current_key=004
+                    ;;
+                # [ F | O F -> ^E end of line
+                133106* | 117106*)
+                    shift 2
+                    LE_current_key=005
+                    ;;
+                # [ 1 ~ -> ^A beginning of line
+                133061176)
+                    shift 3
+                    LE_current_key=001
+                    ;;
+                # [ 4 ~ -> ^E end of line
+                133064176)
+                    shift 3
+                    LE_current_key=005
+                    ;;
+                # [ 3 ~ -> ^D del char
+                133063176)
+                    shift 3
+                    LE_current_key=004
+                    ;;
+                # [ | O
+                133* | 117*)
+                    shift
+                    # Is $1 in ge 0 AND le 9 OR eq ';'?
+                    # These are control sequences for things like colors; Ignore them
+                    while [ "0$1" -ge 060 ] && [ "0$1" -le 071 ] ||
+                        [ "0$1" -eq 073 ]; do
+                        shift
+                    done
+                    ;;
+                esac
+            fi
+
+            case "$LE_current_key" in
+            001) # ^A beginning of line
+                LE_backward "$LE_left"
+                LE_right="$LE_left$LE_right"
+                LE_left=
+                ;;
+            002) # ^B backward
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "backward with empty left"
+                else
+                    printf '\b'
+                    LE_tmp="${LE_left%?}"
+                    LE_right="${LE_left#"$LE_tmp"}$LE_right"
+                    LE_left="$LE_tmp"
+                fi ;;
+            003) # CTRL-C
+                break 2 ;;
+            004) # ^D del char
+                if [ "$LE_right" = "" ]; then
+                    # bell (tell the user that the line is empty)
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "delete with empty right"
+                else
+                    LE_right="${LE_right#?}"
+                    printf '%s\b' "$LE_right$LE_fill"
+                    LE_backward "$LE_right"
+                fi ;;
+            012 | 015) # NL or CR
+                LE_ret=0
+                break 2
+                ;;
+            005) # ^E end of line
+                printf '%s' "$LE_right"
+                LE_left="$LE_left$LE_right"
+                LE_right=
+                ;;
+            006) # ^F forward
+                if [ "$LE_right" = "" ]; then
+                    # bell (tell the user that the line is empty)
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "forward with empty right"
+                else
+                    LE_tmp="${LE_right#?}"
+                    LE_left="$LE_left${LE_right%"$LE_tmp"}"
+                    printf %s "${LE_right%"$LE_tmp"}"
+                    LE_right="$LE_tmp"
+                fi ;;
+            010 | 177) # backspace or del
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "backspace with empty left"
+                else
+                    printf '\b%s\b' "$LE_right$LE_fill"
+                    LE_backward "$LE_right"
+                    LE_left="${LE_left%?}"
+                fi ;;
+            013) # ^K kill to end of line
+                LE_fill "$LE_right"
+                LE_backward "$LE_right"
+                LE_right=""
+                ;;
+            014) # ^L redraw
+                printf '\r%b%s' "$LE_prompt" "$LE_left$LE_right"
+                LE_backward "$LE_right"
+                ;;
+            025) # ^U kill line
+                LE_backward "$LE_left"
+                LE_fill "$LE_left$LE_right"
+                LE_backward "$LE_left$LE_right"
+                LE_left=""
+                LE_right=""
+                ;;
+            027) # ^W kill word
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                else
+                    LE_tmp="${LE_left% *}"
+                    LE_backward "${LE_left#"$LE_tmp"}"
+                    LE_fill "${LE_left#"$LE_tmp"}"
+                    LE_backward "${LE_left#"$LE_tmp"}"
+                    LE_left="$LE_tmp"
+                fi ;;
+            # Print the received key, as it did not match a special key
+            [02][4-7]? | [13]??) # 040 -> 177, 240 -> 377
+                # was assuming iso8859-x at the time
+                if [ "$LE_max" -gt 0 ] && LE_tmp="$LE_left$LE_right" &&
+                    [ "${#LE_tmp}" -eq "$LE_max" ]; then
+                    # bell, when the user is trying to cross the line limit
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "max output reached"
+                else
+                    LE_left="$LE_left$(printf '%b' "\0$LE_current_key")"
+                    printf '%b%s' "\0$LE_current_key" "$LE_right"
+                    LE_backward "$LE_right"
+                fi ;;
+            *)
+                LE_print_debug "$LE_debug" "key not recognized: $(printf "%b" "\0$LE_current_key")"
+                printf '\a'
+                ;;
+            esac
+        done
+    done
+    eval "$LE_restore"
+    REPLY=$LE_left$LE_right
+    echo
+    return "$LE_ret"
+}
diff --git a/templates/latex/README.md b/templates/latex/README.md
index 88664ee..ffa08c2 100644
--- a/templates/latex/README.md
+++ b/templates/latex/README.md
@@ -1,4 +1,5 @@
 # %INIT_APPLICATION_NAME_STYLIZED
+
 > %INIT_DESCRIPTION
 
 Some text about the project.
diff --git a/templates/latex/init b/templates/latex/init
new file mode 100755
index 0000000..787b663
--- /dev/null
+++ b/templates/latex/init
@@ -0,0 +1,71 @@
+#!/usr/bin/env sh
+
+. "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+
+replacement_file="$(mktemp)"
+
+trap cleanup INT
+trap "cleanup; remove" EXIT
+cleanup() {
+    rm "$replacement_file"
+}
+remove() {
+    rm "$(realpath "$0")"
+    rm "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+    git add .
+}
+
+# Prompt the user for a specific variable. The variable is the first
+# input, the second is an optional description.
+# The third argument can be a suggested answer, already pre populated.
+prompt() {
+    pr_variable_upper="$(echo "$1" | sed 's/\([a-z]\)/\U\1/')"
+    pr_description="$2"
+    pr_suggested_answer="$3"
+
+    printf "\033[94;1mEnter %s\033[0m" "$pr_variable_upper"
+    if [ -n "$pr_description" ];then
+        printf " (\033[93;1m%s\033[0m):\n" "$pr_description"
+    else
+        printf ":\n"
+    fi
+
+    # LE "> " 0 " " "$pr_suggested_answer" "yes_please_produce_debug_output"
+    LE "> " 0 " " "$pr_suggested_answer" ""
+
+    pr_new_variable="$(printf '%s="%s"' "$pr_variable_upper" "$REPLY")"
+
+    eval "$pr_new_variable"
+    printf "%s\n" "$pr_new_variable" >> "$replacement_file"
+}
+
+git init
+
+# necessary meta data
+prompt APPLICATION_NAME "The name of the application" "$(basename "$PWD")"
+prompt APPLICATION_NAME_STYLIZED "The stylized name of the application (for documentation)" "$(basename "$PWD" | sed 's/\([a-z]\)/\u\1/')"
+prompt AUTHOR_NAME "The name of the author (or authors)" "$(git config --get user.name)"
+prompt AUTHOR_EMAIL "The email of the author (or authors)" "$(git config --get user.email)"
+
+# cog change-log variables
+prompt REMOTE "The remote, this project will be pushed to" "codeberg.org"
+prompt REPOSITORY "The name of the repository in the remote" "$APPLICATION_NAME"
+prompt OWNER "The name of owner of the repository" "$AUTHOR_NAME"
+
+# nice meta data
+prompt DESCRIPTION "The description of this project" "[can be empty]"
+
+# LICENSE.spdx data (source: https://github.com/david-a-wheeler/spdx-tutorial)
+prompt APPLICATION_ORIGINATOR "The person or organization from whom the package originally came" "$AUTHOR_NAME"
+prompt APPLICATION_HOME_PAGE "The package's home page URL" "https://$REMOTE/$OWNER/$REPOSITORY"
+
+echo "$DESCRIPTION" > .git/description
+
+while read -r var; do
+    var_name="${var%=*}"
+    var_value="${var#*=\"}"
+    var_value="${var_value%\"}"
+
+    fd . --hidden --type file --exec sed --in-place "s|%\bINIT_$var_name\b|$var_value|"
+done < "$replacement_file"
+# vim: ft=sh
diff --git a/templates/latex/shell_line_editor.sh b/templates/latex/shell_line_editor.sh
new file mode 100644
index 0000000..8d6833a
--- /dev/null
+++ b/templates/latex/shell_line_editor.sh
@@ -0,0 +1,247 @@
+#! /usr/bin/env sh
+# Taken in verbatim from: https://unix.stackexchange.com/a/113450, and somewhat changed
+
+LE_print_debug() {
+    LE_debug="$1"
+    LE_debug_msg="$2"
+    [ -n "$LE_debug" ] && printf "\nDBG: (%s)\n" "$LE_debug_msg" >outfile.debug
+}
+
+LE() {
+    # Shell Line Editor. Extremely slow and stupid code. However it
+    # should work on ansi/vt100/linux derived terminals on POSIX
+    # systems.
+    # Understands some emacs key bindings: CTRL-(A,B,D,E,F,H,K,L)
+    # plus the CTRL-W and CTRL-U normal killword and kill.
+    # no Meta-X key, but handling of <Left>, <Right>, <Home>, <End>
+    # <Suppr>.
+    #
+    # Args:
+    #  [1]: prompt (\x sequences recognized, defaults to "")
+    #  [2]: max input length (unlimited if < 0, (default))
+    #  [3]: fill character when erasing (defaults to space)
+    #  [4]: initial value.
+    #  [5]: whether to output debugfiles (outfile.debug and outfile.raw.debug)
+    # Returns:
+    #  0: OK
+    #  1: od(d) error or CTRL-C hit
+
+    LE_prompt="$1"
+    LE_max=${2--1}
+    LE_fill=${3-" "}
+    LE_debug="$5"
+
+    LE_backward() {
+        LE_substract="$1"
+        while [ -n "$LE_substract" ]; do
+            printf '\b%s' "$2"
+            LE_substract=${LE_substract%?}
+        done
+    }
+
+    LE_fill() {
+        LE_substract="$1"
+        while [ -n "$LE_substract" ]; do
+            printf '%s' "$LE_fill"
+            LE_substract=${LE_substract%?}
+        done
+    }
+
+    # Used but not right now
+    # shellcheck disable=2016
+    LE_restore='stty "$LE_tty"
+              LC_COLLATE='${LC_COLLATE-"; unset LC_COLLATE"}
+
+    # LE_tty is used in the restore above
+    # shellcheck disable=2034
+    LE_ret=1 LE_tty=$(stty -g) LC_COLLATE=C
+
+    # text on the right of the cursor
+    LE_left=$4
+    # text on the left of the cursor
+    LE_right=''
+
+    # Tell the terminal to show us every char inputted
+    stty -icanon -echo -isig min 3 time 1 -istrip
+    printf '%b%s' "$LE_prompt" "$LE_left"
+
+    # clear the output
+    [ -n "$LE_debug" ] && printf "" >outfile.debug
+    [ -n "$LE_debug" ] && printf "" >outfile.raw.debug
+
+    # The value needs to be split for it to work (and it's either way just numbers)
+    # shellcheck disable=2046
+    while set -- $(dd bs=3 count=1 2>/dev/null | od -vAn -to1); do
+        while [ "$#" -gt 0 ]; do
+            [ -n "$LE_debug" ] && printf "%b" "\0$1" >>outfile.debug
+            [ -n "$LE_debug" ] && printf "%s " "$1" >>outfile.raw.debug
+            LE_current_key=$1
+            shift
+
+            # 033 is ^[ (`printf "\\$1\n" | cat -v`)
+            if [ "$LE_current_key" = 033 ]; then
+                case "$1$2$3" in
+                # [ C | O C -> ^F forward
+                133103* | 117103*)
+                    shift 2
+                    LE_current_key=006
+                    ;;
+                # [ D | O D -> ^B backward
+                133104* | 117104*)
+                    shift 2
+                    LE_current_key=002
+                    ;;
+                # [ H | O H -> ^A beginning of line
+                133110* | 117110*)
+                    shift 2
+                    LE_current_key=001
+                    ;;
+                # [ P | O P -> ^D del char
+                133120* | 117120*)
+                    shift 2
+                    LE_current_key=004
+                    ;;
+                # [ F | O F -> ^E end of line
+                133106* | 117106*)
+                    shift 2
+                    LE_current_key=005
+                    ;;
+                # [ 1 ~ -> ^A beginning of line
+                133061176)
+                    shift 3
+                    LE_current_key=001
+                    ;;
+                # [ 4 ~ -> ^E end of line
+                133064176)
+                    shift 3
+                    LE_current_key=005
+                    ;;
+                # [ 3 ~ -> ^D del char
+                133063176)
+                    shift 3
+                    LE_current_key=004
+                    ;;
+                # [ | O
+                133* | 117*)
+                    shift
+                    # Is $1 in ge 0 AND le 9 OR eq ';'?
+                    # These are control sequences for things like colors; Ignore them
+                    while [ "0$1" -ge 060 ] && [ "0$1" -le 071 ] ||
+                        [ "0$1" -eq 073 ]; do
+                        shift
+                    done
+                    ;;
+                esac
+            fi
+
+            case "$LE_current_key" in
+            001) # ^A beginning of line
+                LE_backward "$LE_left"
+                LE_right="$LE_left$LE_right"
+                LE_left=
+                ;;
+            002) # ^B backward
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "backward with empty left"
+                else
+                    printf '\b'
+                    LE_tmp="${LE_left%?}"
+                    LE_right="${LE_left#"$LE_tmp"}$LE_right"
+                    LE_left="$LE_tmp"
+                fi ;;
+            003) # CTRL-C
+                break 2 ;;
+            004) # ^D del char
+                if [ "$LE_right" = "" ]; then
+                    # bell (tell the user that the line is empty)
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "delete with empty right"
+                else
+                    LE_right="${LE_right#?}"
+                    printf '%s\b' "$LE_right$LE_fill"
+                    LE_backward "$LE_right"
+                fi ;;
+            012 | 015) # NL or CR
+                LE_ret=0
+                break 2
+                ;;
+            005) # ^E end of line
+                printf '%s' "$LE_right"
+                LE_left="$LE_left$LE_right"
+                LE_right=
+                ;;
+            006) # ^F forward
+                if [ "$LE_right" = "" ]; then
+                    # bell (tell the user that the line is empty)
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "forward with empty right"
+                else
+                    LE_tmp="${LE_right#?}"
+                    LE_left="$LE_left${LE_right%"$LE_tmp"}"
+                    printf %s "${LE_right%"$LE_tmp"}"
+                    LE_right="$LE_tmp"
+                fi ;;
+            010 | 177) # backspace or del
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "backspace with empty left"
+                else
+                    printf '\b%s\b' "$LE_right$LE_fill"
+                    LE_backward "$LE_right"
+                    LE_left="${LE_left%?}"
+                fi ;;
+            013) # ^K kill to end of line
+                LE_fill "$LE_right"
+                LE_backward "$LE_right"
+                LE_right=""
+                ;;
+            014) # ^L redraw
+                printf '\r%b%s' "$LE_prompt" "$LE_left$LE_right"
+                LE_backward "$LE_right"
+                ;;
+            025) # ^U kill line
+                LE_backward "$LE_left"
+                LE_fill "$LE_left$LE_right"
+                LE_backward "$LE_left$LE_right"
+                LE_left=""
+                LE_right=""
+                ;;
+            027) # ^W kill word
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                else
+                    LE_tmp="${LE_left% *}"
+                    LE_backward "${LE_left#"$LE_tmp"}"
+                    LE_fill "${LE_left#"$LE_tmp"}"
+                    LE_backward "${LE_left#"$LE_tmp"}"
+                    LE_left="$LE_tmp"
+                fi ;;
+            # Print the received key, as it did not match a special key
+            [02][4-7]? | [13]??) # 040 -> 177, 240 -> 377
+                # was assuming iso8859-x at the time
+                if [ "$LE_max" -gt 0 ] && LE_tmp="$LE_left$LE_right" &&
+                    [ "${#LE_tmp}" -eq "$LE_max" ]; then
+                    # bell, when the user is trying to cross the line limit
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "max output reached"
+                else
+                    LE_left="$LE_left$(printf '%b' "\0$LE_current_key")"
+                    printf '%b%s' "\0$LE_current_key" "$LE_right"
+                    LE_backward "$LE_right"
+                fi ;;
+            *)
+                LE_print_debug "$LE_debug" "key not recognized: $(printf "%b" "\0$LE_current_key")"
+                printf '\a'
+                ;;
+            esac
+        done
+    done
+    eval "$LE_restore"
+    REPLY=$LE_left$LE_right
+    echo
+    return "$LE_ret"
+}
diff --git a/templates/rust/README.md b/templates/rust/README.md
index 79f2a41..46287a6 100644
--- a/templates/rust/README.md
+++ b/templates/rust/README.md
@@ -1,4 +1,5 @@
 # %INIT_APPLICATION_NAME_STYLIZED
+
 > %INIT_DESCRIPTION
 
 Some text about the project.
diff --git a/templates/rust/init b/templates/rust/init
new file mode 100755
index 0000000..787b663
--- /dev/null
+++ b/templates/rust/init
@@ -0,0 +1,71 @@
+#!/usr/bin/env sh
+
+. "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+
+replacement_file="$(mktemp)"
+
+trap cleanup INT
+trap "cleanup; remove" EXIT
+cleanup() {
+    rm "$replacement_file"
+}
+remove() {
+    rm "$(realpath "$0")"
+    rm "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+    git add .
+}
+
+# Prompt the user for a specific variable. The variable is the first
+# input, the second is an optional description.
+# The third argument can be a suggested answer, already pre populated.
+prompt() {
+    pr_variable_upper="$(echo "$1" | sed 's/\([a-z]\)/\U\1/')"
+    pr_description="$2"
+    pr_suggested_answer="$3"
+
+    printf "\033[94;1mEnter %s\033[0m" "$pr_variable_upper"
+    if [ -n "$pr_description" ];then
+        printf " (\033[93;1m%s\033[0m):\n" "$pr_description"
+    else
+        printf ":\n"
+    fi
+
+    # LE "> " 0 " " "$pr_suggested_answer" "yes_please_produce_debug_output"
+    LE "> " 0 " " "$pr_suggested_answer" ""
+
+    pr_new_variable="$(printf '%s="%s"' "$pr_variable_upper" "$REPLY")"
+
+    eval "$pr_new_variable"
+    printf "%s\n" "$pr_new_variable" >> "$replacement_file"
+}
+
+git init
+
+# necessary meta data
+prompt APPLICATION_NAME "The name of the application" "$(basename "$PWD")"
+prompt APPLICATION_NAME_STYLIZED "The stylized name of the application (for documentation)" "$(basename "$PWD" | sed 's/\([a-z]\)/\u\1/')"
+prompt AUTHOR_NAME "The name of the author (or authors)" "$(git config --get user.name)"
+prompt AUTHOR_EMAIL "The email of the author (or authors)" "$(git config --get user.email)"
+
+# cog change-log variables
+prompt REMOTE "The remote, this project will be pushed to" "codeberg.org"
+prompt REPOSITORY "The name of the repository in the remote" "$APPLICATION_NAME"
+prompt OWNER "The name of owner of the repository" "$AUTHOR_NAME"
+
+# nice meta data
+prompt DESCRIPTION "The description of this project" "[can be empty]"
+
+# LICENSE.spdx data (source: https://github.com/david-a-wheeler/spdx-tutorial)
+prompt APPLICATION_ORIGINATOR "The person or organization from whom the package originally came" "$AUTHOR_NAME"
+prompt APPLICATION_HOME_PAGE "The package's home page URL" "https://$REMOTE/$OWNER/$REPOSITORY"
+
+echo "$DESCRIPTION" > .git/description
+
+while read -r var; do
+    var_name="${var%=*}"
+    var_value="${var#*=\"}"
+    var_value="${var_value%\"}"
+
+    fd . --hidden --type file --exec sed --in-place "s|%\bINIT_$var_name\b|$var_value|"
+done < "$replacement_file"
+# vim: ft=sh
diff --git a/templates/rust/shell_line_editor.sh b/templates/rust/shell_line_editor.sh
new file mode 100644
index 0000000..8d6833a
--- /dev/null
+++ b/templates/rust/shell_line_editor.sh
@@ -0,0 +1,247 @@
+#! /usr/bin/env sh
+# Taken in verbatim from: https://unix.stackexchange.com/a/113450, and somewhat changed
+
+LE_print_debug() {
+    LE_debug="$1"
+    LE_debug_msg="$2"
+    [ -n "$LE_debug" ] && printf "\nDBG: (%s)\n" "$LE_debug_msg" >outfile.debug
+}
+
+LE() {
+    # Shell Line Editor. Extremely slow and stupid code. However it
+    # should work on ansi/vt100/linux derived terminals on POSIX
+    # systems.
+    # Understands some emacs key bindings: CTRL-(A,B,D,E,F,H,K,L)
+    # plus the CTRL-W and CTRL-U normal killword and kill.
+    # no Meta-X key, but handling of <Left>, <Right>, <Home>, <End>
+    # <Suppr>.
+    #
+    # Args:
+    #  [1]: prompt (\x sequences recognized, defaults to "")
+    #  [2]: max input length (unlimited if < 0, (default))
+    #  [3]: fill character when erasing (defaults to space)
+    #  [4]: initial value.
+    #  [5]: whether to output debugfiles (outfile.debug and outfile.raw.debug)
+    # Returns:
+    #  0: OK
+    #  1: od(d) error or CTRL-C hit
+
+    LE_prompt="$1"
+    LE_max=${2--1}
+    LE_fill=${3-" "}
+    LE_debug="$5"
+
+    LE_backward() {
+        LE_substract="$1"
+        while [ -n "$LE_substract" ]; do
+            printf '\b%s' "$2"
+            LE_substract=${LE_substract%?}
+        done
+    }
+
+    LE_fill() {
+        LE_substract="$1"
+        while [ -n "$LE_substract" ]; do
+            printf '%s' "$LE_fill"
+            LE_substract=${LE_substract%?}
+        done
+    }
+
+    # Used but not right now
+    # shellcheck disable=2016
+    LE_restore='stty "$LE_tty"
+              LC_COLLATE='${LC_COLLATE-"; unset LC_COLLATE"}
+
+    # LE_tty is used in the restore above
+    # shellcheck disable=2034
+    LE_ret=1 LE_tty=$(stty -g) LC_COLLATE=C
+
+    # text on the right of the cursor
+    LE_left=$4
+    # text on the left of the cursor
+    LE_right=''
+
+    # Tell the terminal to show us every char inputted
+    stty -icanon -echo -isig min 3 time 1 -istrip
+    printf '%b%s' "$LE_prompt" "$LE_left"
+
+    # clear the output
+    [ -n "$LE_debug" ] && printf "" >outfile.debug
+    [ -n "$LE_debug" ] && printf "" >outfile.raw.debug
+
+    # The value needs to be split for it to work (and it's either way just numbers)
+    # shellcheck disable=2046
+    while set -- $(dd bs=3 count=1 2>/dev/null | od -vAn -to1); do
+        while [ "$#" -gt 0 ]; do
+            [ -n "$LE_debug" ] && printf "%b" "\0$1" >>outfile.debug
+            [ -n "$LE_debug" ] && printf "%s " "$1" >>outfile.raw.debug
+            LE_current_key=$1
+            shift
+
+            # 033 is ^[ (`printf "\\$1\n" | cat -v`)
+            if [ "$LE_current_key" = 033 ]; then
+                case "$1$2$3" in
+                # [ C | O C -> ^F forward
+                133103* | 117103*)
+                    shift 2
+                    LE_current_key=006
+                    ;;
+                # [ D | O D -> ^B backward
+                133104* | 117104*)
+                    shift 2
+                    LE_current_key=002
+                    ;;
+                # [ H | O H -> ^A beginning of line
+                133110* | 117110*)
+                    shift 2
+                    LE_current_key=001
+                    ;;
+                # [ P | O P -> ^D del char
+                133120* | 117120*)
+                    shift 2
+                    LE_current_key=004
+                    ;;
+                # [ F | O F -> ^E end of line
+                133106* | 117106*)
+                    shift 2
+                    LE_current_key=005
+                    ;;
+                # [ 1 ~ -> ^A beginning of line
+                133061176)
+                    shift 3
+                    LE_current_key=001
+                    ;;
+                # [ 4 ~ -> ^E end of line
+                133064176)
+                    shift 3
+                    LE_current_key=005
+                    ;;
+                # [ 3 ~ -> ^D del char
+                133063176)
+                    shift 3
+                    LE_current_key=004
+                    ;;
+                # [ | O
+                133* | 117*)
+                    shift
+                    # Is $1 in ge 0 AND le 9 OR eq ';'?
+                    # These are control sequences for things like colors; Ignore them
+                    while [ "0$1" -ge 060 ] && [ "0$1" -le 071 ] ||
+                        [ "0$1" -eq 073 ]; do
+                        shift
+                    done
+                    ;;
+                esac
+            fi
+
+            case "$LE_current_key" in
+            001) # ^A beginning of line
+                LE_backward "$LE_left"
+                LE_right="$LE_left$LE_right"
+                LE_left=
+                ;;
+            002) # ^B backward
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "backward with empty left"
+                else
+                    printf '\b'
+                    LE_tmp="${LE_left%?}"
+                    LE_right="${LE_left#"$LE_tmp"}$LE_right"
+                    LE_left="$LE_tmp"
+                fi ;;
+            003) # CTRL-C
+                break 2 ;;
+            004) # ^D del char
+                if [ "$LE_right" = "" ]; then
+                    # bell (tell the user that the line is empty)
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "delete with empty right"
+                else
+                    LE_right="${LE_right#?}"
+                    printf '%s\b' "$LE_right$LE_fill"
+                    LE_backward "$LE_right"
+                fi ;;
+            012 | 015) # NL or CR
+                LE_ret=0
+                break 2
+                ;;
+            005) # ^E end of line
+                printf '%s' "$LE_right"
+                LE_left="$LE_left$LE_right"
+                LE_right=
+                ;;
+            006) # ^F forward
+                if [ "$LE_right" = "" ]; then
+                    # bell (tell the user that the line is empty)
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "forward with empty right"
+                else
+                    LE_tmp="${LE_right#?}"
+                    LE_left="$LE_left${LE_right%"$LE_tmp"}"
+                    printf %s "${LE_right%"$LE_tmp"}"
+                    LE_right="$LE_tmp"
+                fi ;;
+            010 | 177) # backspace or del
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "backspace with empty left"
+                else
+                    printf '\b%s\b' "$LE_right$LE_fill"
+                    LE_backward "$LE_right"
+                    LE_left="${LE_left%?}"
+                fi ;;
+            013) # ^K kill to end of line
+                LE_fill "$LE_right"
+                LE_backward "$LE_right"
+                LE_right=""
+                ;;
+            014) # ^L redraw
+                printf '\r%b%s' "$LE_prompt" "$LE_left$LE_right"
+                LE_backward "$LE_right"
+                ;;
+            025) # ^U kill line
+                LE_backward "$LE_left"
+                LE_fill "$LE_left$LE_right"
+                LE_backward "$LE_left$LE_right"
+                LE_left=""
+                LE_right=""
+                ;;
+            027) # ^W kill word
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                else
+                    LE_tmp="${LE_left% *}"
+                    LE_backward "${LE_left#"$LE_tmp"}"
+                    LE_fill "${LE_left#"$LE_tmp"}"
+                    LE_backward "${LE_left#"$LE_tmp"}"
+                    LE_left="$LE_tmp"
+                fi ;;
+            # Print the received key, as it did not match a special key
+            [02][4-7]? | [13]??) # 040 -> 177, 240 -> 377
+                # was assuming iso8859-x at the time
+                if [ "$LE_max" -gt 0 ] && LE_tmp="$LE_left$LE_right" &&
+                    [ "${#LE_tmp}" -eq "$LE_max" ]; then
+                    # bell, when the user is trying to cross the line limit
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "max output reached"
+                else
+                    LE_left="$LE_left$(printf '%b' "\0$LE_current_key")"
+                    printf '%b%s' "\0$LE_current_key" "$LE_right"
+                    LE_backward "$LE_right"
+                fi ;;
+            *)
+                LE_print_debug "$LE_debug" "key not recognized: $(printf "%b" "\0$LE_current_key")"
+                printf '\a'
+                ;;
+            esac
+        done
+    done
+    eval "$LE_restore"
+    REPLY=$LE_left$LE_right
+    echo
+    return "$LE_ret"
+}
diff --git a/templates/shell/README.md b/templates/shell/README.md
index 79f2a41..46287a6 100644
--- a/templates/shell/README.md
+++ b/templates/shell/README.md
@@ -1,4 +1,5 @@
 # %INIT_APPLICATION_NAME_STYLIZED
+
 > %INIT_DESCRIPTION
 
 Some text about the project.
diff --git a/templates/shell/init b/templates/shell/init
new file mode 100755
index 0000000..787b663
--- /dev/null
+++ b/templates/shell/init
@@ -0,0 +1,71 @@
+#!/usr/bin/env sh
+
+. "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+
+replacement_file="$(mktemp)"
+
+trap cleanup INT
+trap "cleanup; remove" EXIT
+cleanup() {
+    rm "$replacement_file"
+}
+remove() {
+    rm "$(realpath "$0")"
+    rm "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+    git add .
+}
+
+# Prompt the user for a specific variable. The variable is the first
+# input, the second is an optional description.
+# The third argument can be a suggested answer, already pre populated.
+prompt() {
+    pr_variable_upper="$(echo "$1" | sed 's/\([a-z]\)/\U\1/')"
+    pr_description="$2"
+    pr_suggested_answer="$3"
+
+    printf "\033[94;1mEnter %s\033[0m" "$pr_variable_upper"
+    if [ -n "$pr_description" ];then
+        printf " (\033[93;1m%s\033[0m):\n" "$pr_description"
+    else
+        printf ":\n"
+    fi
+
+    # LE "> " 0 " " "$pr_suggested_answer" "yes_please_produce_debug_output"
+    LE "> " 0 " " "$pr_suggested_answer" ""
+
+    pr_new_variable="$(printf '%s="%s"' "$pr_variable_upper" "$REPLY")"
+
+    eval "$pr_new_variable"
+    printf "%s\n" "$pr_new_variable" >> "$replacement_file"
+}
+
+git init
+
+# necessary meta data
+prompt APPLICATION_NAME "The name of the application" "$(basename "$PWD")"
+prompt APPLICATION_NAME_STYLIZED "The stylized name of the application (for documentation)" "$(basename "$PWD" | sed 's/\([a-z]\)/\u\1/')"
+prompt AUTHOR_NAME "The name of the author (or authors)" "$(git config --get user.name)"
+prompt AUTHOR_EMAIL "The email of the author (or authors)" "$(git config --get user.email)"
+
+# cog change-log variables
+prompt REMOTE "The remote, this project will be pushed to" "codeberg.org"
+prompt REPOSITORY "The name of the repository in the remote" "$APPLICATION_NAME"
+prompt OWNER "The name of owner of the repository" "$AUTHOR_NAME"
+
+# nice meta data
+prompt DESCRIPTION "The description of this project" "[can be empty]"
+
+# LICENSE.spdx data (source: https://github.com/david-a-wheeler/spdx-tutorial)
+prompt APPLICATION_ORIGINATOR "The person or organization from whom the package originally came" "$AUTHOR_NAME"
+prompt APPLICATION_HOME_PAGE "The package's home page URL" "https://$REMOTE/$OWNER/$REPOSITORY"
+
+echo "$DESCRIPTION" > .git/description
+
+while read -r var; do
+    var_name="${var%=*}"
+    var_value="${var#*=\"}"
+    var_value="${var_value%\"}"
+
+    fd . --hidden --type file --exec sed --in-place "s|%\bINIT_$var_name\b|$var_value|"
+done < "$replacement_file"
+# vim: ft=sh
diff --git a/templates/shell/shell_line_editor.sh b/templates/shell/shell_line_editor.sh
new file mode 100644
index 0000000..8d6833a
--- /dev/null
+++ b/templates/shell/shell_line_editor.sh
@@ -0,0 +1,247 @@
+#! /usr/bin/env sh
+# Taken in verbatim from: https://unix.stackexchange.com/a/113450, and somewhat changed
+
+LE_print_debug() {
+    LE_debug="$1"
+    LE_debug_msg="$2"
+    [ -n "$LE_debug" ] && printf "\nDBG: (%s)\n" "$LE_debug_msg" >outfile.debug
+}
+
+LE() {
+    # Shell Line Editor. Extremely slow and stupid code. However it
+    # should work on ansi/vt100/linux derived terminals on POSIX
+    # systems.
+    # Understands some emacs key bindings: CTRL-(A,B,D,E,F,H,K,L)
+    # plus the CTRL-W and CTRL-U normal killword and kill.
+    # no Meta-X key, but handling of <Left>, <Right>, <Home>, <End>
+    # <Suppr>.
+    #
+    # Args:
+    #  [1]: prompt (\x sequences recognized, defaults to "")
+    #  [2]: max input length (unlimited if < 0, (default))
+    #  [3]: fill character when erasing (defaults to space)
+    #  [4]: initial value.
+    #  [5]: whether to output debugfiles (outfile.debug and outfile.raw.debug)
+    # Returns:
+    #  0: OK
+    #  1: od(d) error or CTRL-C hit
+
+    LE_prompt="$1"
+    LE_max=${2--1}
+    LE_fill=${3-" "}
+    LE_debug="$5"
+
+    LE_backward() {
+        LE_substract="$1"
+        while [ -n "$LE_substract" ]; do
+            printf '\b%s' "$2"
+            LE_substract=${LE_substract%?}
+        done
+    }
+
+    LE_fill() {
+        LE_substract="$1"
+        while [ -n "$LE_substract" ]; do
+            printf '%s' "$LE_fill"
+            LE_substract=${LE_substract%?}
+        done
+    }
+
+    # Used but not right now
+    # shellcheck disable=2016
+    LE_restore='stty "$LE_tty"
+              LC_COLLATE='${LC_COLLATE-"; unset LC_COLLATE"}
+
+    # LE_tty is used in the restore above
+    # shellcheck disable=2034
+    LE_ret=1 LE_tty=$(stty -g) LC_COLLATE=C
+
+    # text on the right of the cursor
+    LE_left=$4
+    # text on the left of the cursor
+    LE_right=''
+
+    # Tell the terminal to show us every char inputted
+    stty -icanon -echo -isig min 3 time 1 -istrip
+    printf '%b%s' "$LE_prompt" "$LE_left"
+
+    # clear the output
+    [ -n "$LE_debug" ] && printf "" >outfile.debug
+    [ -n "$LE_debug" ] && printf "" >outfile.raw.debug
+
+    # The value needs to be split for it to work (and it's either way just numbers)
+    # shellcheck disable=2046
+    while set -- $(dd bs=3 count=1 2>/dev/null | od -vAn -to1); do
+        while [ "$#" -gt 0 ]; do
+            [ -n "$LE_debug" ] && printf "%b" "\0$1" >>outfile.debug
+            [ -n "$LE_debug" ] && printf "%s " "$1" >>outfile.raw.debug
+            LE_current_key=$1
+            shift
+
+            # 033 is ^[ (`printf "\\$1\n" | cat -v`)
+            if [ "$LE_current_key" = 033 ]; then
+                case "$1$2$3" in
+                # [ C | O C -> ^F forward
+                133103* | 117103*)
+                    shift 2
+                    LE_current_key=006
+                    ;;
+                # [ D | O D -> ^B backward
+                133104* | 117104*)
+                    shift 2
+                    LE_current_key=002
+                    ;;
+                # [ H | O H -> ^A beginning of line
+                133110* | 117110*)
+                    shift 2
+                    LE_current_key=001
+                    ;;
+                # [ P | O P -> ^D del char
+                133120* | 117120*)
+                    shift 2
+                    LE_current_key=004
+                    ;;
+                # [ F | O F -> ^E end of line
+                133106* | 117106*)
+                    shift 2
+                    LE_current_key=005
+                    ;;
+                # [ 1 ~ -> ^A beginning of line
+                133061176)
+                    shift 3
+                    LE_current_key=001
+                    ;;
+                # [ 4 ~ -> ^E end of line
+                133064176)
+                    shift 3
+                    LE_current_key=005
+                    ;;
+                # [ 3 ~ -> ^D del char
+                133063176)
+                    shift 3
+                    LE_current_key=004
+                    ;;
+                # [ | O
+                133* | 117*)
+                    shift
+                    # Is $1 in ge 0 AND le 9 OR eq ';'?
+                    # These are control sequences for things like colors; Ignore them
+                    while [ "0$1" -ge 060 ] && [ "0$1" -le 071 ] ||
+                        [ "0$1" -eq 073 ]; do
+                        shift
+                    done
+                    ;;
+                esac
+            fi
+
+            case "$LE_current_key" in
+            001) # ^A beginning of line
+                LE_backward "$LE_left"
+                LE_right="$LE_left$LE_right"
+                LE_left=
+                ;;
+            002) # ^B backward
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "backward with empty left"
+                else
+                    printf '\b'
+                    LE_tmp="${LE_left%?}"
+                    LE_right="${LE_left#"$LE_tmp"}$LE_right"
+                    LE_left="$LE_tmp"
+                fi ;;
+            003) # CTRL-C
+                break 2 ;;
+            004) # ^D del char
+                if [ "$LE_right" = "" ]; then
+                    # bell (tell the user that the line is empty)
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "delete with empty right"
+                else
+                    LE_right="${LE_right#?}"
+                    printf '%s\b' "$LE_right$LE_fill"
+                    LE_backward "$LE_right"
+                fi ;;
+            012 | 015) # NL or CR
+                LE_ret=0
+                break 2
+                ;;
+            005) # ^E end of line
+                printf '%s' "$LE_right"
+                LE_left="$LE_left$LE_right"
+                LE_right=
+                ;;
+            006) # ^F forward
+                if [ "$LE_right" = "" ]; then
+                    # bell (tell the user that the line is empty)
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "forward with empty right"
+                else
+                    LE_tmp="${LE_right#?}"
+                    LE_left="$LE_left${LE_right%"$LE_tmp"}"
+                    printf %s "${LE_right%"$LE_tmp"}"
+                    LE_right="$LE_tmp"
+                fi ;;
+            010 | 177) # backspace or del
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "backspace with empty left"
+                else
+                    printf '\b%s\b' "$LE_right$LE_fill"
+                    LE_backward "$LE_right"
+                    LE_left="${LE_left%?}"
+                fi ;;
+            013) # ^K kill to end of line
+                LE_fill "$LE_right"
+                LE_backward "$LE_right"
+                LE_right=""
+                ;;
+            014) # ^L redraw
+                printf '\r%b%s' "$LE_prompt" "$LE_left$LE_right"
+                LE_backward "$LE_right"
+                ;;
+            025) # ^U kill line
+                LE_backward "$LE_left"
+                LE_fill "$LE_left$LE_right"
+                LE_backward "$LE_left$LE_right"
+                LE_left=""
+                LE_right=""
+                ;;
+            027) # ^W kill word
+                if [ "$LE_left" = "" ]; then
+                    # bell
+                    printf '\a'
+                else
+                    LE_tmp="${LE_left% *}"
+                    LE_backward "${LE_left#"$LE_tmp"}"
+                    LE_fill "${LE_left#"$LE_tmp"}"
+                    LE_backward "${LE_left#"$LE_tmp"}"
+                    LE_left="$LE_tmp"
+                fi ;;
+            # Print the received key, as it did not match a special key
+            [02][4-7]? | [13]??) # 040 -> 177, 240 -> 377
+                # was assuming iso8859-x at the time
+                if [ "$LE_max" -gt 0 ] && LE_tmp="$LE_left$LE_right" &&
+                    [ "${#LE_tmp}" -eq "$LE_max" ]; then
+                    # bell, when the user is trying to cross the line limit
+                    printf '\a'
+                    LE_print_debug "$LE_debug" "max output reached"
+                else
+                    LE_left="$LE_left$(printf '%b' "\0$LE_current_key")"
+                    printf '%b%s' "\0$LE_current_key" "$LE_right"
+                    LE_backward "$LE_right"
+                fi ;;
+            *)
+                LE_print_debug "$LE_debug" "key not recognized: $(printf "%b" "\0$LE_current_key")"
+                printf '\a'
+                ;;
+            esac
+        done
+    done
+    eval "$LE_restore"
+    REPLY=$LE_left$LE_right
+    echo
+    return "$LE_ret"
+}