diff --git a/.licensure.yml b/.licensure.yml new file mode 100644 index 0000000..7e18334 --- /dev/null +++ b/.licensure.yml @@ -0,0 +1,172 @@ +--- +# 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: + # 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: MIT + # + # A list of authors who hold copyright over these files + authors: + - name: "The Trinitrix Project" + email: "bpeetz@b-peetz.de, antifallobst@systemausfall.org" + + # 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 . If multiple authors are provided the + # list is concatenated together with commas. + template: | + Copyright (C) 2024 - [year]: + [name of author] + SPDX-License-Identifier: MIT + + This file is part of Trinitrix. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the “Software”), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + # 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 + - pest + # 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" + 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/Cargo.toml b/Cargo.toml index cf7fd9e..a9b3cec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "trinitrix" +description = "A multi protocol chat client" version = "0.1.0" edition = "2021" license = "MIT" diff --git a/LICENSE.spdx b/LICENSE.spdx new file mode 100644 index 0000000..54e0087 --- /dev/null +++ b/LICENSE.spdx @@ -0,0 +1,7 @@ +SPDXVersion: SPDX-2.3 +DataLicense: CC0-1.0 +Creator: flake template init +PackageName: trinitrix +PackageOriginator: The Trinitrix Project +PackageHomePage: https://git.nerdcult.net/trinitrix/core +PackageLicenseDeclared: MIT diff --git a/cog.toml b/cog.toml new file mode 100644 index 0000000..6e15915 --- /dev/null +++ b/cog.toml @@ -0,0 +1,25 @@ +tag_prefix = "v" +branch_whitelist = ["master"] +ignore_merge_commits = false + +pre_bump_hooks = [ + # "nix flake check", # verify the project builds + "./scripts/renew_copyright_header.sh", # update the license header in each file + "cargo set-version {{version}}", # bump version in Cargo.toml + "nix fmt", # format +] +post_bump_hooks = [ + "git push", + "cargo publish", + "git push origin v{{version}}", # push the new tag to origin +] + +[bump_profiles] + +[changelog] +path = "NEWS.md" +template = "remote" +remote = "git.nerdcult.net" +repository = "core" +owner = "trinitrix" +authors = [{ signature = "The Trinitrix Project", username = "trinitrix" }] diff --git a/docs/trinitrix.1.md b/docs/trinitrix.1.md new file mode 100644 index 0000000..9f7e64d --- /dev/null +++ b/docs/trinitrix.1.md @@ -0,0 +1,64 @@ +% TRINITRIX(1) trinitrix 0.1.0 +% The Trinitrix Project +% May 2024 + +# NAME + +trinitrix - A multi protocol chat client + +# SYNOPSIS + +**trinitrix** \[*--help*|*--version*\] + +# DESCRIPTION + +Trinitrix is a multi protocol client. That is implemented via cbs and plugins. + +# OPTIONS + +**--help**, **-h** +: Displays a help message and exit. + +**--version**, **-v** +: Displays the software version and exit. + +**--plugin-path \**, **-p \** +: The SHARED_OBJECT to load as a dynamic library. The `plugin_main` function will be + executed. + +# EXAMPLES + +**trinitrix repl** +: Start a repl with evaluation of trinitry commands. + +# FILES + +*plugin.so* +: Shared object file of a plugin, to be loaded with **--plugin-path** + +# BUGS + +Report bugs to . + +# COPYRIGHT + +Copyright (C) 2024 The Trinitrix Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/flake.lock b/flake.lock index 58316d9..ca7d44c 100644 --- a/flake.lock +++ b/flake.lock @@ -38,7 +38,9 @@ }, "flake-utils": { "inputs": { - "systems": "systems" + "systems": [ + "systems" + ] }, "locked": { "lastModified": 1710146030, @@ -76,7 +78,9 @@ "flake-compat": "flake-compat", "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", - "rust-overlay": "rust-overlay" + "rust-overlay": "rust-overlay", + "systems": "systems", + "treefmt-nix": "treefmt-nix" } }, "rust-overlay": { @@ -104,16 +108,36 @@ }, "systems": { "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "lastModified": 1680978846, + "narHash": "sha256-Gtqg8b/v49BFDpDetjclCYXm8mAnTrUzR0JnE2nv5aw=", "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "repo": "x86_64-linux", + "rev": "2ecfcac5e15790ba6ce360ceccddb15ad16d08a8", "type": "github" }, "original": { "owner": "nix-systems", - "repo": "default", + "repo": "x86_64-linux", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1714058656, + "narHash": "sha256-Qv4RBm4LKuO4fNOfx9wl40W2rBbv5u5m+whxRYUMiaA=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "c6aaf729f34a36c445618580a9f95a48f5e4e03f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", "type": "github" } } diff --git a/flake.nix b/flake.nix index ab9b5fb..fe7b4ff 100644 --- a/flake.nix +++ b/flake.nix @@ -1,13 +1,14 @@ { - description = "A terminal UI client for the matrix chat protocol"; + description = "A multi protocol chat client"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - # inputs for following - flake-compat = { - url = "github:edolstra/flake-compat"; - flake = false; + treefmt-nix = { + url = "github:numtide/treefmt-nix"; + inputs = { + nixpkgs.follows = "nixpkgs"; + }; }; crane = { @@ -16,10 +17,6 @@ nixpkgs.follows = "nixpkgs"; }; }; - flake-utils = { - url = "github:numtide/flake-utils"; - inputs = {}; - }; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs = { @@ -27,13 +24,29 @@ flake-utils.follows = "flake-utils"; }; }; + + # inputs for following + systems = { + url = "github:nix-systems/x86_64-linux"; # only evaluate for this system + }; + flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; + }; + flake-utils = { + url = "github:numtide/flake-utils"; + inputs = { + systems.follows = "systems"; + }; + }; }; outputs = { self, nixpkgs, - crane, flake-utils, + treefmt-nix, + crane, rust-overlay, ... }: @@ -44,26 +57,20 @@ }; nightly = false; - rust = + rust_minimal = if nightly then - (pkgs.rust-bin.selectLatestNightlyWith (toolchain: - toolchain.default)) - .override { - extensions = ["rustc-codegen-cranelift-preview"]; - } - else pkgs.rust-bin.stable.latest.default; - rust_min = - if nightly - then - (pkgs.rust-bin.selectLatestNightlyWith (toolchain: - toolchain.minimal)) - .override { + (pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.minimal)).override { extensions = ["rustc-codegen-cranelift-preview"]; } else pkgs.rust-bin.stable.latest.minimal; - - craneLib = (crane.mkLib pkgs).overrideToolchain rust_min; + rust_default = + if nightly + then + (pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default)).override { + extensions = ["rustc-codegen-cranelift-preview"]; + } + else pkgs.rust-bin.stable.latest.default; nativeBuildInputs = with pkgs; [ pkg-config @@ -76,34 +83,61 @@ lua54Packages.lua ]; + cargo_toml = craneLib.cleanCargoToml {cargoToml = ./Cargo.toml;}; + pname = cargo_toml.package.name; + + craneLib = (crane.mkLib pkgs).overrideToolchain rust_minimal; craneBuild = craneLib.buildPackage { + inherit nativeBuildInputs buildInputs; + src = craneLib.cleanCargoSource ./.; doCheck = true; - inherit nativeBuildInputs buildInputs; - }; - in { - checks.default = craneBuild; - packages = { - default = craneBuild; }; - app.default = { - type = "app"; - program = "${self.packages.${system}.default}/bin/trinitix"; + manual = pkgs.stdenv.mkDerivation { + name = "${pname}-manual"; + inherit (cargo_toml.package) version; + + src = ./docs; + nativeBuildInputs = with pkgs; [pandoc]; + + buildPhase = '' + mkdir --parents $out/docs; + + pandoc "./${pname}.1.md" -s -t man > $out/docs/${pname}.1 + ''; + + installPhase = '' + install -D $out/docs/${pname}.1 $out/share/man/man1/${pname}; + ''; }; + treefmtEval = import ./treefmt.nix {inherit treefmt-nix pkgs;}; + in { + packages.default = pkgs.symlinkJoin { + inherit (cargo_toml.package) name; + + paths = [manual craneBuild]; + }; + + checks = { + inherit craneBuild; + formatting = treefmtEval.config.build.check self; + }; + + formatter = treefmtEval.config.build.wrapper; + devShells.default = pkgs.mkShell { packages = with pkgs; [ - alejandra + cocogitto - rust + rust_default cargo-edit - cargo-expand valgrind + licensure ]; - inherit nativeBuildInputs buildInputs; }; }); } diff --git a/scripts/renew_copyright_header.sh b/scripts/renew_copyright_header.sh new file mode 100755 index 0000000..4f424c3 --- /dev/null +++ b/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/src/cli.rs b/src/cli.rs index d2da450..94abb9b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -2,9 +2,7 @@ use std::path::PathBuf; use clap::{Parser, Subcommand}; -// TODO: The description is wrong - -/// A terminal client for the matrix chat protocol +/// A multi protocol chat client #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] pub struct Args { diff --git a/treefmt.nix b/treefmt.nix new file mode 100644 index 0000000..1cbab40 --- /dev/null +++ b/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"]; + }; + }; + }; + } +) diff --git a/update.sh b/update.sh index 1e69bf0..0dfd573 100755 --- a/update.sh +++ b/update.sh @@ -2,6 +2,4 @@ cargo update && cargo upgrade -git add Cargo.lock Cargo.toml flake.lock - # vim: ft=sh