about summary refs log tree commit diff stats
path: root/common/files
diff options
context:
space:
mode:
Diffstat (limited to 'common/files')
-rw-r--r--common/files/.licensure.yml186
-rw-r--r--common/files/docs/TODO.1.md54
-rwxr-xr-xcommon/files/init84
-rwxr-xr-xcommon/files/scripts/renew_copyright_header.sh92
-rw-r--r--common/files/shell_line_editor.sh247
-rw-r--r--common/files/treefmt.nix73
6 files changed, 736 insertions, 0 deletions
diff --git a/common/files/.licensure.yml b/common/files/.licensure.yml
new file mode 100644
index 0000000..60ef45c
--- /dev/null
+++ b/common/files/.licensure.yml
@@ -0,0 +1,186 @@
+---
+# Regexes which if matched by a file path will always be excluded from
+# getting a license header
+excludes:
+  - .*lock
+  - \.git/.*
+  - LICENSE.spdx
+  - LICENSE
+  - COPYING
+  - COPYING.LESSER
+  - .*\.(rst|txt|pdf)
+# Definition of the licenses used on this project and to what files
+# they should apply.
+#
+# No default license configuration is provided. This section must be
+# configured by the user.
+licenses:
+  - files: \.tex
+    ident: CC-BY-SA-4.0
+    authors:
+      - name: "%INIT_AUTHOR_NAME"
+        email: "%INIT_AUTHOR_EMAIL"
+
+    template: |
+      %INIT_APPLIACATION_NAME_STYLIZED %INIT_YEAR - [year] (C) by [name of author]
+      SPDX-License-Identifier: CC-BY-SA-4.0
+
+      %INIT_APPLIACATION_NAME_STYLIZED is licensed under a
+      Creative Commons Attribution-ShareAlike 4.0 International License.
+
+      You should have received a copy of the license along with this
+      work.  If not, see <https://creativecommons.org/licenses/by-sa/4.0/>.
+
+    unwrap_text: false
+
+  # Either a regex or the string "any" to determine to what files this
+  # license should apply. It is common for projects to have files
+  # under multiple licenses or with multiple copyright holders. This
+  # provides the ability to automatically license files correctly
+  # based on their file paths.
+  #
+  # If "any" is provided all files will match this license.
+  - files: any
+    #
+    #   The license identifier, a list of common identifiers can be
+    #   found at: https://spdx.org/licenses/ but existence of the ident
+    #   in this list it is not enforced unless auto_template is set to
+    #   true.
+    ident: GPL-3.0-or-later
+    #
+    #   A list of authors who hold copyright over these files
+    authors:
+      # Provide either your full name or company name for copyright purposes
+      - name: "%INIT_AUTHOR_NAME"
+        # Optionally provide email for copyright purposes
+        email: "%INIT_AUTHOR_EMAIL"
+
+    #   The template that will be rendered to generate the header before
+    #   comment characters are applied. Available variables are:
+    #    - [year]: substituted with the current year.
+    #    - [name of author]: Substituted with name of the author and email
+    #      if provided. If email is provided the output appears as Full
+    #      Name <email@example.com>. If multiple authors are provided the
+    #      list is concatenated together with commas.
+    template: |
+        Copyright (C) %INIT_YEAR - [year]:
+        [name of author]
+        SPDX-License-Identifier: GPL-3.0-or-later
+
+        This file is part of %INIT_APPLICATION_NAME_STYLIZED.
+
+        %INIT_APPLICATION_NAME_STYLIZED is free software: you can redistribute it and/or modify
+        it under the terms of the Lesser GNU General Public License as
+        published by the Free Software Foundation, either version 3 of
+        the License, or (at your option) any later version.
+
+        This program is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        GNU General Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        and the Lesser GNU General Public License along with this program.
+        If not, see <https://www.gnu.org/licenses/>.
+
+
+    #   If auto_template is true then template is ignored and the SPDX
+    #   API will be queried with the ident value to automatically
+    #   determine the license header template. auto_template works best
+    #   with licenses that have a standardLicenseHeader field defined in
+    #   their license info JSON, if it is not then we will use the full
+    #   licenseText to generate the header which works fine for short
+    #   licenses like MIT but can be quite lengthy for other licenses
+    #   like BSD-4-Clause. The above default template is valid for most
+    #   licenses and is recommended for MIT, and BSD licenses. Common
+    #   licenses that work well with the auto_template feature are GPL
+    #   variants, and the Apache 2.0 license.
+    #
+    #   Important Note: this means the ident must be a valid SPDX identifier
+    # auto_template: true
+
+    #   If true try to detect the text wrapping of the template, and unwrap it
+    unwrap_text: false
+
+# Define type of comment characters to apply based on file extensions.
+comments:
+  # The extensions (or singular extension) field defines which file
+  # extensions to apply the commenter to.
+  - extensions:
+      - js
+      - go
+    # The commenter field defines the kind of commenter to
+    # generate. There are two types of commenters: line and block.
+    #
+    # This demonstrates a line commenter configuration. A line
+    # commenter type will apply the comment_char to the beginning of
+    # each line in the license header. It will then apply a number of
+    # empty newlines to the end of the header equal to trailing_lines.
+    #
+    # If trailing_lines is omitted it is assumed to be 0.
+    commenter:
+      type: line
+      comment_char: "//"
+      trailing_lines: 1
+
+  - extensions:
+      - rs
+      - tri
+      - css
+      - cpp
+      - c
+      - h
+    # This demonstrates a block commenter configuration. A block
+    # commenter type will add start_block_char as the first character
+    # in the license header and add end_block_char as the last character
+    # in the license header. If per_line_char is provided each line of
+    # the header between the block start and end characters will be
+    # line commented with the per_line_char
+    #
+    # trailing_lines works the same for both block and line commenter
+    # types
+    commenter:
+      type: block
+      start_block_char: "/*\n"
+      end_block_char: "*/\n"
+      per_line_char: "*"
+      trailing_lines: 1
+
+  - extension:
+      - html
+      - md
+    commenter:
+      type: block
+      start_block_char: "<!--\n"
+      end_block_char: "-->\n"
+      trailing_lines: 1
+
+  - extensions:
+      - el
+      - lisp
+    commenter:
+      type: line
+      comment_char: ";;;"
+      trailing_lines: 1
+
+  - extensions:
+      - tex
+      - bib
+    commenter:
+      type: line
+      comment_char: "%"
+      trailing_lines: 1
+
+  # The extension string "any" is special and so will match any file
+  # extensions. Commenter configurations are always checked in the
+  # order they are defined, so if any is used it should be the last
+  # commenter configuration or else it will override all others.
+  #
+  # In this configuration if we can't match the file extension we fall
+  # back to the popular '#' line comment used in most scripting
+  # languages.
+  - extension: any
+    commenter:
+      type: line
+      comment_char: '#'
+      trailing_lines: 1
diff --git a/common/files/docs/TODO.1.md b/common/files/docs/TODO.1.md
new file mode 100644
index 0000000..15d5072
--- /dev/null
+++ b/common/files/docs/TODO.1.md
@@ -0,0 +1,54 @@
+% %INIT_APPLICATION_NAME_CAPITALIZED(1) %INIT_APPLICATION_NAME %INIT_APPLICATION_VERSION
+% %INIT_AUTHOR_NAME
+% %INIT_CURRENT_DATE
+
+# NAME
+
+%INIT_APPLICATION_NAME - %INIT_DESCRIPTION
+
+# SYNOPSIS
+
+**%INIT_APPLICATION_NAME** \[*--help*|*--version*\]
+
+# DESCRIPTION
+
+TODO
+
+# OPTIONS
+
+**--help**, **-h**
+: Displays a help message and exit.
+
+**--version**, **-v**
+: Displays the software version and exit.
+
+# EXAMPLES
+
+**%INIT_APPLICATION_NAME**
+: TODO. See the Description section for further details.
+
+# FILES
+
+*name.file*
+: This file is important because it does x.
+
+# BUGS
+
+Report bugs to <https://%INIT_REMOTE/%INIT_OWNER/%INIT_REPOSITORY/issues>.
+
+# COPYRIGHT
+
+Copyright (C) %INIT_YEAR  %INIT_AUTOHR_NAME
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
diff --git a/common/files/init b/common/files/init
new file mode 100755
index 0000000..1b7c86b
--- /dev/null
+++ b/common/files/init
@@ -0,0 +1,84 @@
+#!/usr/bin/env sh
+
+. "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+
+replacement_file="$(mktemp)"
+
+trap cleanup INT
+trap "cleanup; remove_self" EXIT
+cleanup() {
+    rm "$replacement_file"
+}
+remove_self() {
+    rm "$(realpath "$0")"
+    rm "$(realpath "$(dirname "$0")")/shell_line_editor.sh"
+}
+
+# Prompt the user for a specific variable.
+# ## Args:
+# [1]: Name of the variable to populate the answer to
+# [2]: An optional description
+# [3]: An optionally suggested answer
+# [4]: If this is set, the user is not even asked.
+prompt() {
+    pr_variable_upper="$(echo "$1" | sed 's/\([a-z]\)/\U\1/')"
+    pr_description="$2"
+    pr_suggested_answer="$3"
+    pr_ask="$4"
+
+    if [ -n "$pr_ask" ]; then
+        REPLY="$pr_suggested_answer";
+    else
+        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" ""
+    fi
+
+    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)" "$(echo "$APPLICATION_NAME" | sed 's/\([a-z]\)/\u\1/')"
+prompt APPLICATION_NAME_CAPITALIZED "The capitalized name of the application (for documentation)" "$(echo "$APPLICATION_NAME" | sed 's/\([a-z]\)/\U\1/')" "dont_ask"
+prompt APPLICATION_VERSION "The version of this program, without the prefix" "0.1.0"
+
+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]"
+prompt CURRENT_DATE "The stylized version of the current date" "$(date +'%b %Y')"
+prompt YEAR "The year the work on this has begun (for copyright reasons)" "$(date +'%Y')"
+
+# 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/common/files/scripts/renew_copyright_header.sh b/common/files/scripts/renew_copyright_header.sh
new file mode 100755
index 0000000..4f424c3
--- /dev/null
+++ b/common/files/scripts/renew_copyright_header.sh
@@ -0,0 +1,92 @@
+#! /usr/bin/env sh
+
+# NOTE: This is the line length of the .licensure.yml header template **plus** the extra
+# line after the template comment.
+TEMPLATE_LINE_LENGTH=20
+LATEX_TEMPLATE_LINE_LENGTH=9
+
+PROJECT_ROOT="$(git rev-parse --show-toplevel)"
+
+remove() {
+    extension="$1"
+    file="$2"
+
+    # We need to differentiate, when removing the old copyright header, as some
+    # formatters do weird things to the file
+    case "$extension" in
+    # normal '#' comments (these are $TEMPLATE_LINE_LENGTH lines long)
+    "Makefile" | "toml" | "envrc" | "yml" | "gitignore" | "awk")
+        sed --in-place "1,${TEMPLATE_LINE_LENGTH}d" "$file"
+        ;;
+    # LaTeX files (or TeX files in general) have a different license, use the
+    # $LATEX_TEMPLATE_LINE_LENGTH variable.
+    "tex")
+        sed --in-place "1,${LATEX_TEMPLATE_LINE_LENGTH}d" "$file"
+        ;;
+    # normal '/* ... */' like comments (these are $TEMPLATE_LINE_LENGTH + 2 lines long)
+    "c" | "h" | "md" | "rs")
+        length="$((TEMPLATE_LINE_LENGTH + 2))"
+        sed --in-place "1,${length}d;" "$file"
+        ;;
+    # alejandra (the nix formatter) removes the blank line after the comment,
+    # thus only $TEMPLATE_LINE_LENGTH - 1 lines
+    "nix")
+        length="$((TEMPLATE_LINE_LENGTH - 1))"
+        sed --in-place "1,${length}d;" "$file"
+        ;;
+    # Shell needs a shebang on the first line, only after the first line can we
+    # remove the $TEMPLATE_LINE_LENGTH lines
+    "sh")
+        sed --in-place "2,${TEMPLATE_LINE_LENGTH}d;" "$file"
+        licensure --in-place "$file"
+
+        TEMPLATE_LINE_LENGTH_NEW="$(($(yq --raw-output '.licenses | map(.template) | join("")' "$PROJECT_ROOT/.licensure.yml" | wc -l) + $(yq '.comments | last | .commenter.trailing_lines' "$PROJECT_ROOT/.licensure.yml")))"
+
+        # delete the current shebang
+        to="$((TEMPLATE_LINE_LENGTH_NEW + 1))"
+        sed --in-place "${TEMPLATE_LINE_LENGTH_NEW},${to}d;" "$file"
+
+        # add a new one
+        sed --in-place "1i#! /usr/bin/env sh" "$file"
+        ;;
+    *)
+        echo "File '$file' with extension '$extension' is not know yet, please add it!"
+        ;;
+    esac
+}
+
+list() {
+    echo "$extension -> $file"
+}
+
+if [ -f "$1" ]; then
+    file="$(realpath "$1")"
+    filename="$(basename -- "$file")"
+    extension="${filename##*.}"
+    filename="${filename%.*}"
+
+    if [ -n "$DRY_RUN" ]; then
+        list "$extension" "$file"
+    else
+        remove "$extension" "$file"
+    fi
+else
+    fd --type file --hidden . | while read -r file; do
+        if grep --quiet 'SPDX-License-Identifier' "$file"; then
+            filename="$(basename -- "$file")"
+            extension="${filename##*.}"
+            filename="${filename%.*}"
+
+            if [ -n "$DRY_RUN" ]; then
+                list "$extension" "$file"
+            else
+                remove "$extension" "$file"
+            fi
+        fi
+    done
+
+    if [ -z "$DRY_RUN" ]; then
+        licensure --in-place --project
+        nix fmt
+    fi
+fi
diff --git a/common/files/shell_line_editor.sh b/common/files/shell_line_editor.sh
new file mode 100644
index 0000000..8d6833a
--- /dev/null
+++ b/common/files/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/common/files/treefmt.nix b/common/files/treefmt.nix
new file mode 100644
index 0000000..1cbab40
--- /dev/null
+++ b/common/files/treefmt.nix
@@ -0,0 +1,73 @@
+{
+  treefmt-nix,
+  pkgs,
+}:
+treefmt-nix.lib.evalModule pkgs (
+  {pkgs, ...}: {
+    # Used to find the project root
+    projectRootFile = "flake.nix";
+
+    programs = {
+      alejandra.enable = true;
+      rustfmt.enable = true;
+      clang-format.enable = true;
+      mdformat.enable = true;
+      shfmt = {
+        enable = true;
+        indent_size = 4;
+      };
+      shellcheck.enable = true;
+      prettier = {
+        settings = {
+          arrowParens = "always";
+          bracketSameLine = false;
+          bracketSpacing = true;
+          editorconfig = true;
+          embeddedLanguageFormatting = "auto";
+          endOfLine = "lf";
+          # experimentalTernaries = false;
+          htmlWhitespaceSensitivity = "css";
+          insertPragma = false;
+          jsxSingleQuote = true;
+          printWidth = 80;
+          proseWrap = "always";
+          quoteProps = "consistent";
+          requirePragma = false;
+          semi = true;
+          singleAttributePerLine = true;
+          singleQuote = true;
+          trailingComma = "all";
+          useTabs = false;
+          vueIndentScriptAndStyle = false;
+
+          tabWidth = 4;
+          overrides = {
+            files = ["*.js"];
+            options.tabwidth = 2;
+          };
+        };
+      };
+      stylua.enable = true;
+      ruff = {
+        enable = true;
+        format = true;
+      };
+      taplo.enable = true;
+    };
+
+    settings = {
+      global.excludes = [
+        "CHANGELOG.md"
+        "NEWS.md"
+      ];
+      formatter = {
+        clang-format = {
+          options = ["--style" "GNU"];
+        };
+        shfmt = {
+          includes = ["*.bash"];
+        };
+      };
+    };
+  }
+)