diff --git a/.chezmoitemplates/zshrc_darwin.tmpl b/.chezmoitemplates/zshrc_darwin.tmpl index 3d6554e..5f67466 100644 --- a/.chezmoitemplates/zshrc_darwin.tmpl +++ b/.chezmoitemplates/zshrc_darwin.tmpl @@ -130,3 +130,7 @@ export PATH export EDITOR=vim source <(/opt/homebrew/bin/starship init zsh --print-full-init) + +if [ -x "$(command -v tmux)" ] && [ -n "${DISPLAY}" ] && [ -z "${TMUX}" ]; then + exec tmux new-session -A -s ${USER} >/dev/null 2>&1 +fi diff --git a/.chezmoitemplates/zshrc_linux.tmpl b/.chezmoitemplates/zshrc_linux.tmpl index 2ae8fb1..198f243 100644 --- a/.chezmoitemplates/zshrc_linux.tmpl +++ b/.chezmoitemplates/zshrc_linux.tmpl @@ -130,3 +130,7 @@ export EDITOR=vim eval "$(starship init zsh)" test -e "$HOME/.shellfishrc" && source "$HOME/.shellfishrc" + +if [ -x "$(command -v tmux)" ] && [ -n "${DISPLAY}" ] && [ -z "${TMUX}" ]; then + exec tmux new-session -A -s ${USER} >/dev/null 2>&1 +fi diff --git a/README.md b/README.md new file mode 100644 index 0000000..0b43fd0 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +https://gist.github.com/rbudiharso/53821b3222c4e7a5f7695d8d13cc6058 + +For Install new tmux addons run this +~~~ +TMUX_PLUGIN_MANAGER_PATH=~/.tmux/plugins .tmux/plugins/tpm/scripts/install_plugins.sh +~~~ diff --git a/dot_tmux.conf b/dot_tmux.conf deleted file mode 100644 index 207d7e8..0000000 --- a/dot_tmux.conf +++ /dev/null @@ -1 +0,0 @@ -set -g mouse on diff --git a/dot_tmux.conf.tmpl b/dot_tmux.conf.tmpl new file mode 100644 index 0000000..23f9b14 --- /dev/null +++ b/dot_tmux.conf.tmpl @@ -0,0 +1,38 @@ +set -g mouse on + +set -g default-terminal "tmux-256color" +set -sa terminal-overrides ",xterm-termite:Tc" + +set -g history-limit 10000 + +set -g @plugin 'tmux-plugins/tpm' +set -g @plugin 'tmux-plugins/tmux-sensible' +set -g @plugin 'tmux-plugins/tmux-pain-control' +set -g @plugin 'tmux-plugins/tmux-copycat' +set -g @plugin 'tmux-plugins/tmux-yank' +set -g @plugin 'tmux-plugins/tmux-prefix-highlight' +set -g @plugin 'soyuka/tmux-current-pane-hostname' +set -g @plugin "arcticicestudio/nord-tmux" + +run -b '~/.tmux/plugins/tpm/tpm' + +set -g @nord_tmux_no_patched_font "1" +set -g @nord_tmux_show_status_content "0" +set -g status-style "bg=#4c566a,fg=#eceff4" +set -g status-left "#[fg=#bf616a,bg=#ebcb8b,bold] #S " +set -g status-right "#{prefix_highlight} #[bg=#a3be8c,fg=black,bold] #U #[bg=#ebcb8b,fg=#bf616a,bold] #h " +setw -g window-status-format "#[fg=#81a1c1,bg=#4c566a] #I:#W " +setw -g window-status-current-format "#[fg=#2e3440,bg=#81a1c1,bold] #I:#W " +setw -g window-status-separator "" + +{{ if eq .chezmoi.os "darwin" -}} +bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "wl-copy && wl-paste -n | wl-copy -p" +bind-key p run "wl-paste -n | tmux load-buffer - ; tmux paste-buffer" +{{ else if eq .chezmoi.os "linux" -}} +bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "wl-copy && wl-paste -n | wl-copy -p" +bind-key p run "wl-paste -n | tmux load-buffer - ; tmux paste-buffer" +{{ end -}} + +# More friendly split pane +bind-key h split-window -h +bind-key v split-window -v diff --git a/dot_tmux/plugins/nord-tmux/changelog.md b/dot_tmux/plugins/nord-tmux/changelog.md new file mode 100644 index 0000000..0cd971d --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/changelog.md @@ -0,0 +1,140 @@ +

+ +

+ +

Changelog for Nord tmux — An arctic, north-bluish clean and elegant tmux color theme.

+ + + +# 0.3.0 + +![Release Date: 2019-06-03](https://img.shields.io/badge/Release_Date-2019--06--03-88C0D0.svg?style=flat-square) [![Project Board](https://img.shields.io/badge/Project_Board-0.03.0-88C0D0.svg?style=flat-square)](https://github.com/orgs/nordtheme/projects/1/views/10) [![Milestone](https://img.shields.io/badge/Milestone-0.03.0-88C0D0.svg?style=flat-square)](https://github.com/nordtheme/tmux/milestone/4) + +## Features + +**Nord Docs Transition** — #36 ⇄ #37 (⊶ 6101cf85) +↠ Transferred all documentations, assets and from „Nord tmux“ to [Nord Docs][nord] +Please see the [corresponding issue in the Nord Docs repository][nord-docs#153] to get an overview of what has changed for Nord tmux and what has been done to migrate to Nord Docs. + +###### Landing Page + +

Preview: Nord tmux Port Project Landing Page

+ +###### Landing Page Docs + +

Preview: Nord tmux Docs Landing Page

+ +###### Installation & Activation Docs + +

Preview: Nord tmux Installation & Activation Docs Page

+ +###### Configuration Docs + +

Preview: Nord tmux Configuration Docs Page

+ +###### Plugin Support Docs + +

Preview: Nord tmux Plugin Support Docs Page

+ +**Patched Font Characters** — #5 ⇄ #11 (⊶ 0809657f) by [@petrhosek][gh-user-petrhosek] +↠ Added a new theme configuration to [disable patched fonts for the default status content][nord-docs-config-font-no-patched] by setting the `@nord_tmux_no_patched_font` variable to `1`. +It can be used facing rendering problems with incompatible terminals or fonts. + +```sh +set -g @nord_tmux_no_patched_font "1" +``` + +

+ +**Optional Status Bar Content** — #7, #10 ⇄ #8, #12 (⊶ 27754979) by [@tsroten][gh-user-tsroten] and [@rgcr][gh-user-rgcr] +↠ Added a new theme configuration to [disable the default predefined status bar content][nord-docs-config-default-content], allowing to customize the status content, e.g. adding other plugins or adjust the layout, by setting the `@nord_tmux_show_status_content` variable to `0`: + +```sh +set -g @nord_tmux_show_status_content "0" +``` + +

+ +## Improvements + +**Respect User's Status Bar Positioning** — #13 ⇄ #14 (⊶ ee5542c5) by [@drzel][gh-user-drzel] +↠ Removed the `status-position` property in order to respect the user's preferred status bar positioning configuration instead of overriding it. + +**More Spacing** — #16 (⊶ 2da9466c) by [@dylnmc][gh-user-dylnmc] +↠ Added a space character to the first and last status bar element in order to improve the visual appearance to make it look not so squeezed together. + +

Before

+ +

+ +

After

+ +

+ +## Bug Fixes + +### Documentation + +**Typo In `source-file` Command** — #32 (⊶ 72b0b3fb) by [@rememberYou][gh-user-rememberyou] +↠ Fixed a typo in the README for the `source-file` command. + +## Tasks + +### Documentation + +**More Spacing** — #16 (⊶ 2da9466c) by [@dylnmc][gh-user-dylnmc] +↠ Added a space character to the first and last status bar element in order to improve the visual appearance to make it look not so squeezed together. + +**MIT License** — #19 ⇄ #20 (⊶ 4d39639a) +↠ Adapted to the MIT license migration of the Nord project. Detailed information can be found in the main task ticket [nordtheme/nord#55][]. + +# 0.2.0 + +_2017-04-22_ + +## Features + +### Plugin Support + +❯ Implemented support for the [tmux-prefix-highlight](https://github.com/tmux-plugins/tmux-prefix-highlight) _prefix_- and `copy-mode` status indicator. (@kepbod, #3, 166c8956) + +


+ +# 0.1.1 + +_2017-04-21_ + +## Bug Fixes + +❯ Fixed the plugin to be not loadable due to the missing `#!/usr/bin/env bash` hashbang and `+x` permission flag for the plugin loader [`nord.tmux`](https://github.com/nordtheme/tmux/blob/develop/nord.tmux) which caused `tpm` to exit with code `126`. (@svengreb, #4, c049da5e) + +# 0.1.0 + +_2017-04-20_ + +## Features + +Detailed information about features and install instructions can be found in the [README](https://github.com/nordtheme/tmux/blob/develop/readme.md#installation). + +❯ Implemented the main color theme file [`nord.conf`](https://github.com/nordtheme/tmux/blob/develop/src/nord.conf). (@svengreb, #1, e759aedc) + +

+ +❯ Implemented the [`tpm`](https://github.com/tmux-plugins/tpm) plugin loader [`nord.tmux`](https://github.com/nordtheme/tmux/blob/develop/nord.tmux). (@svengreb, #2, e58b52e9) + +# 0.0.0 + +_2016-04-20_ +❯ **Project Initialization** + +[nordtheme/nord#55]: https://github.com/nordtheme/nord/issues/55 +[gh-user-drzel]: https://github.com/drzel +[gh-user-dylnmc]: https://github.com/dylnmc +[gh-user-petrhosek]: https://github.com/petrhosek +[gh-user-rememberyou]: https://github.com/rememberYou +[gh-user-rgcr]: https://github.com/rgcr +[gh-user-tsroten]: https://github.com/tsroten +[nord-docs-config-default-content]: https://www.nordtheme.com/docs/ports/tmux/configuration#default-status-bar-content +[nord-docs-config-font-no-patched]: https://www.nordtheme.com/docs/ports/tmux/configuration#patched-font-characters +[nord-docs#153]: https://github.com/nordtheme/web/pull/153 +[nord]: https://www.nordtheme.com diff --git a/dot_tmux/plugins/nord-tmux/dot_editorconfig b/dot_tmux/plugins/nord-tmux/dot_editorconfig new file mode 100644 index 0000000..f160665 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_editorconfig @@ -0,0 +1,27 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +# Configurations for EditorConfig. +# See https://editorconfig.org/#file-format-details for more details. + +# +--------------------+ +# + Base Configuration + +# +--------------------+ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +max_line_length = 160 +trim_trailing_whitespace = true + +# +-----------+ +# + Languages + +# +-----------+ +# +--- Markdown ---+ +[*.{md}] +max_line_length = off +trim_trailing_whitespace = false diff --git a/dot_tmux/plugins/nord-tmux/dot_eslintignore b/dot_tmux/plugins/nord-tmux/dot_eslintignore new file mode 100644 index 0000000..b96f5c4 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_eslintignore @@ -0,0 +1,14 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +# Path match pattern to ignore (i.e. not lint) certain files and folders. +# References: +# 1. https://eslint.org/docs/latest/use/configure/ignore + +node_modules/ + +# Explicitly include specific "dotfiles". +# ESLint automatically applies ignore pattern for "dotfiles" by default to prevent accidentally lint over paths like +# `.git` or any other critical paths. +!**/.eslintrc.js +!.remarkrc.mjs diff --git a/dot_tmux/plugins/nord-tmux/dot_eslintrc.js b/dot_tmux/plugins/nord-tmux/dot_eslintrc.js new file mode 100644 index 0000000..9f38844 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_eslintrc.js @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016-present Sven Greb + * This source code is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license found in the license file. + */ + +/** + * Configurations for ESLint. + * @see https://eslint.org/docs/latest/use/configure + * @see https://eslint.org/docs/latest/use/configure/#using-configuration-files + * @see https://eslint.org/docs/latest/use/configure/#specifying-environments + * @see https://eslint.org/docs/latest/rules + */ +module.exports = { + root: true, + extends: [ + "@svengreb/eslint-config-base", + /* + * Enable support for projects using Prettier. + * Note that this must always be placed after the `@svengreb/eslint-config-base` preset to take precedence, otherwise it won't prevent errors + * due to useless and possibly conflicting rules! + */ + "@svengreb/eslint-config-base/prettier", + ], + overrides: [ + { + files: ["*.js"], + rules: { + "capitalized-comments": "off", + }, + }, + ], +}; diff --git a/dot_tmux/plugins/nord-tmux/dot_git/HEAD b/dot_tmux/plugins/nord-tmux/dot_git/HEAD new file mode 100644 index 0000000..7ee7e4f --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/develop diff --git a/dot_tmux/plugins/nord-tmux/dot_git/branches/.keep b/dot_tmux/plugins/nord-tmux/dot_git/branches/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/nord-tmux/dot_git/config b/dot_tmux/plugins/nord-tmux/dot_git/config new file mode 100644 index 0000000..97aaf4a --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[submodule] + active = . +[remote "origin"] + url = https://git::@github.com/arcticicestudio/nord-tmux + fetch = +refs/heads/develop:refs/remotes/origin/develop +[branch "develop"] + remote = origin + merge = refs/heads/develop diff --git a/dot_tmux/plugins/nord-tmux/dot_git/description b/dot_tmux/plugins/nord-tmux/dot_git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_applypatch-msg.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_applypatch-msg.sample new file mode 100644 index 0000000..a5d7b84 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_commit-msg.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_commit-msg.sample new file mode 100644 index 0000000..b58d118 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_fsmonitor-watchman.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_fsmonitor-watchman.sample new file mode 100644 index 0000000..23e856f --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_post-update.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_post-update.sample new file mode 100644 index 0000000..ec17ec1 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-applypatch.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-applypatch.sample new file mode 100644 index 0000000..4142082 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-commit.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-commit.sample new file mode 100644 index 0000000..e144712 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-merge-commit.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-merge-commit.sample new file mode 100644 index 0000000..399eab1 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-push.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-push.sample new file mode 100644 index 0000000..4ce688d --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-rebase.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-rebase.sample new file mode 100644 index 0000000..6cbef5c --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-receive.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-receive.sample new file mode 100644 index 0000000..a1fd29e --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_prepare-commit-msg.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_prepare-commit-msg.sample new file mode 100644 index 0000000..10fa14c --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_push-to-checkout.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_push-to-checkout.sample new file mode 100644 index 0000000..af5a0c0 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_update.sample b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_update.sample new file mode 100644 index 0000000..c4d426b --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/hooks/executable_update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/dot_tmux/plugins/nord-tmux/dot_git/index b/dot_tmux/plugins/nord-tmux/dot_git/index new file mode 100644 index 0000000..cc8b9af Binary files /dev/null and b/dot_tmux/plugins/nord-tmux/dot_git/index differ diff --git a/dot_tmux/plugins/nord-tmux/dot_git/info/exclude b/dot_tmux/plugins/nord-tmux/dot_git/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/dot_tmux/plugins/nord-tmux/dot_git/logs/HEAD b/dot_tmux/plugins/nord-tmux/dot_git/logs/HEAD new file mode 100644 index 0000000..a09af9c --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 f7b6da07ab55fe32ee5f7d62da56d8e5ac691a92 Simon Rieger 1699878736 +0100 clone: from https://github.com/arcticicestudio/nord-tmux diff --git a/dot_tmux/plugins/nord-tmux/dot_git/logs/refs/heads/develop b/dot_tmux/plugins/nord-tmux/dot_git/logs/refs/heads/develop new file mode 100644 index 0000000..a09af9c --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/logs/refs/heads/develop @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 f7b6da07ab55fe32ee5f7d62da56d8e5ac691a92 Simon Rieger 1699878736 +0100 clone: from https://github.com/arcticicestudio/nord-tmux diff --git a/dot_tmux/plugins/nord-tmux/dot_git/logs/refs/remotes/origin/HEAD b/dot_tmux/plugins/nord-tmux/dot_git/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..a09af9c --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 f7b6da07ab55fe32ee5f7d62da56d8e5ac691a92 Simon Rieger 1699878736 +0100 clone: from https://github.com/arcticicestudio/nord-tmux diff --git a/dot_tmux/plugins/nord-tmux/dot_git/objects/info/.keep b/dot_tmux/plugins/nord-tmux/dot_git/objects/info/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/nord-tmux/dot_git/objects/pack/readonly_pack-5b3ea1cd6f644781eb97ba77791615e9278aa441.idx b/dot_tmux/plugins/nord-tmux/dot_git/objects/pack/readonly_pack-5b3ea1cd6f644781eb97ba77791615e9278aa441.idx new file mode 100644 index 0000000..578ab39 Binary files /dev/null and b/dot_tmux/plugins/nord-tmux/dot_git/objects/pack/readonly_pack-5b3ea1cd6f644781eb97ba77791615e9278aa441.idx differ diff --git a/dot_tmux/plugins/nord-tmux/dot_git/objects/pack/readonly_pack-5b3ea1cd6f644781eb97ba77791615e9278aa441.pack b/dot_tmux/plugins/nord-tmux/dot_git/objects/pack/readonly_pack-5b3ea1cd6f644781eb97ba77791615e9278aa441.pack new file mode 100644 index 0000000..cc36680 Binary files /dev/null and b/dot_tmux/plugins/nord-tmux/dot_git/objects/pack/readonly_pack-5b3ea1cd6f644781eb97ba77791615e9278aa441.pack differ diff --git a/dot_tmux/plugins/nord-tmux/dot_git/objects/pack/readonly_pack-5b3ea1cd6f644781eb97ba77791615e9278aa441.rev b/dot_tmux/plugins/nord-tmux/dot_git/objects/pack/readonly_pack-5b3ea1cd6f644781eb97ba77791615e9278aa441.rev new file mode 100644 index 0000000..94c652a Binary files /dev/null and b/dot_tmux/plugins/nord-tmux/dot_git/objects/pack/readonly_pack-5b3ea1cd6f644781eb97ba77791615e9278aa441.rev differ diff --git a/dot_tmux/plugins/nord-tmux/dot_git/packed-refs b/dot_tmux/plugins/nord-tmux/dot_git/packed-refs new file mode 100644 index 0000000..840f910 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +f7b6da07ab55fe32ee5f7d62da56d8e5ac691a92 refs/remotes/origin/develop diff --git a/dot_tmux/plugins/nord-tmux/dot_git/refs/heads/develop b/dot_tmux/plugins/nord-tmux/dot_git/refs/heads/develop new file mode 100644 index 0000000..d13d451 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/refs/heads/develop @@ -0,0 +1 @@ +f7b6da07ab55fe32ee5f7d62da56d8e5ac691a92 diff --git a/dot_tmux/plugins/nord-tmux/dot_git/refs/remotes/origin/HEAD b/dot_tmux/plugins/nord-tmux/dot_git/refs/remotes/origin/HEAD new file mode 100644 index 0000000..45cfece --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/develop diff --git a/dot_tmux/plugins/nord-tmux/dot_git/refs/tags/v0.1.0 b/dot_tmux/plugins/nord-tmux/dot_git/refs/tags/v0.1.0 new file mode 100644 index 0000000..7b94dba --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_git/refs/tags/v0.1.0 @@ -0,0 +1 @@ +4279c6531d50413299746fb5621799dd7eabd7ec diff --git a/dot_tmux/plugins/nord-tmux/dot_gitattributes b/dot_tmux/plugins/nord-tmux/dot_gitattributes new file mode 100644 index 0000000..c2894df --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_gitattributes @@ -0,0 +1,12 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +# Configuration to define attributes per path. +# +# References: +# 1. https://git-scm.com/docs/gitattributes +# 2. https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes#Keyword-Expansion + +# Automatically perform line feed (LF) normalization for files detected as text and +# leave all files detected as binary untouched. +* text=auto eol=lf diff --git a/dot_tmux/plugins/nord-tmux/dot_github/codeowners b/dot_tmux/plugins/nord-tmux/dot_github/codeowners new file mode 100644 index 0000000..84b72ae --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_github/codeowners @@ -0,0 +1,14 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +# Configuration for the GitHub feature to automatically request reviews from the code owners +# when a pull request changes any owned files. +# +# References: +# 1. https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-file-location +# 2. https://github.com/blog/2392-introducing-code-owners + +# +----------------------+ +# + Core Team Code Owner + +# +----------------------+ +* @svengreb diff --git a/dot_tmux/plugins/nord-tmux/dot_gitignore b/dot_tmux/plugins/nord-tmux/dot_gitignore new file mode 100644 index 0000000..b080a12 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_gitignore @@ -0,0 +1,10 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +# Path match pattern to intentionally ignore untracked files and directories. +# See https://git-scm.com/docs/gitignore for more details. + +# +---------+ +# + Node.js + +# +---------+ +node_modules/ diff --git a/dot_tmux/plugins/nord-tmux/dot_husky/executable_pre-commit b/dot_tmux/plugins/nord-tmux/dot_husky/executable_pre-commit new file mode 100644 index 0000000..6d5dae8 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_husky/executable_pre-commit @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license found in the license file. + +# Git "pre-commit" hook for husky. +# References: +# 1. https://github.com/typicode/husky +# 2. https://git-scm.com/docs/githooks#_pre_commit + +. "$(dirname "$0")/_/husky.sh" + +npm exec lint-staged diff --git a/dot_tmux/plugins/nord-tmux/dot_mailmap b/dot_tmux/plugins/nord-tmux/dot_mailmap new file mode 100644 index 0000000..df88d05 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_mailmap @@ -0,0 +1,8 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +# Configuration for the Git mail mapping feature to coalesce together commits by the same person in the shortlog, +# where their name and/or email address was spelled differently or has been changed. +# See https://git-scm.com/docs/git-shortlog#_mapping_authors for more details. +Sven Greb +Sven Greb diff --git a/dot_tmux/plugins/nord-tmux/dot_npmrc b/dot_tmux/plugins/nord-tmux/dot_npmrc new file mode 100644 index 0000000..145947b --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_npmrc @@ -0,0 +1,25 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +# Configurations for npm. +# See https://docs.npmjs.com/cli/v7/configuring-npm/npmrc for more details. + +# Disable the vulnerability auditing and checks which includes often way too many false-positives, insignificant +# problems that are only for local development, and many other warnings that are overhelming. +# Use dedicated vulnerability tools instead to filter and identify issue that really impact the project. +# References: +# 1. https://docs.npmjs.com/cli/v9/commands/npm-audit +audit=false + +# Only use a lockfile for single-consumer projects, like applications, but not for multi-consumer projects like +# libraries. +# It helps to pin dependency versions, improves the security through integrity checksums, prevents possible errors +# caused by updated transitive dependencies and allows to get deterministic build results, but it can hide problems in +# multi-consumer projects when any later versions of a used dependency, or its transitive dependencies, is not +# compatible with the own project anymore. +package-lock=true + +# Do not resolve to the latest minor and patch updates. +# Automatically pin dependencies to exact versions instead of resolving to latest minor and patch updates. +# This prevents possible errors caused by updated transitive dependencies. +save-exact=true diff --git a/dot_tmux/plugins/nord-tmux/dot_prettierignore b/dot_tmux/plugins/nord-tmux/dot_prettierignore new file mode 100644 index 0000000..cdb9786 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_prettierignore @@ -0,0 +1,8 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +# Path match pattern to ignore (i.e. not reformat) certain files and folders. +# See https://prettier.io/docs/en/ignore for more details. + +.husky/_/ +node_modules/ diff --git a/dot_tmux/plugins/nord-tmux/dot_remarkignore b/dot_tmux/plugins/nord-tmux/dot_remarkignore new file mode 100644 index 0000000..188f1f8 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_remarkignore @@ -0,0 +1,8 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +# Path match pattern to ignore when searching for files. +# See https://github.com/unifiedjs/unified-engine/blob/HEAD/doc/ignore.md for more details. + +node_modules/ +license diff --git a/dot_tmux/plugins/nord-tmux/dot_remarkrc.mjs b/dot_tmux/plugins/nord-tmux/dot_remarkrc.mjs new file mode 100644 index 0000000..7435198 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/dot_remarkrc.mjs @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2016-present Sven Greb + * This source code is licensed under the MIT license found in the license file. + */ + +/** + * Configurations for remark-lint. + * @see https://github.com/remarkjs/remark-lint + * @see https://remark.js.org + */ +export default { + plugins: ["@svengreb/remark-preset-lint"], +}; diff --git a/dot_tmux/plugins/nord-tmux/executable_nord.tmux b/dot_tmux/plugins/nord-tmux/executable_nord.tmux new file mode 100644 index 0000000..3da21a0 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/executable_nord.tmux @@ -0,0 +1,53 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +NORD_TMUX_COLOR_THEME_FILE=src/nord.conf +NORD_TMUX_VERSION=0.3.0 +NORD_TMUX_STATUS_CONTENT_FILE="src/nord-status-content.conf" +NORD_TMUX_STATUS_CONTENT_NO_PATCHED_FONT_FILE="src/nord-status-content-no-patched-font.conf" +NORD_TMUX_STATUS_CONTENT_OPTION="@nord_tmux_show_status_content" +NORD_TMUX_STATUS_CONTENT_DATE_FORMAT="@nord_tmux_date_format" +NORD_TMUX_NO_PATCHED_FONT_OPTION="@nord_tmux_no_patched_font" +_current_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +__cleanup() { + unset -v NORD_TMUX_COLOR_THEME_FILE NORD_TMUX_VERSION + unset -v NORD_TMUX_STATUS_CONTENT_FILE NORD_TMUX_STATUS_CONTENT_NO_PATCHED_FONT_FILE + unset -v NORD_TMUX_STATUS_CONTENT_OPTION NORD_TMUX_NO_PATCHED_FONT_OPTION + unset -v NORD_TMUX_STATUS_CONTENT_DATE_FORMAT + unset -v _current_dir + unset -f __load __cleanup + tmux set-environment -gu NORD_TMUX_STATUS_TIME_FORMAT + tmux set-environment -gu NORD_TMUX_STATUS_DATE_FORMAT +} + +__load() { + tmux source-file "$_current_dir/$NORD_TMUX_COLOR_THEME_FILE" + + local status_content=$(tmux show-option -gqv "$NORD_TMUX_STATUS_CONTENT_OPTION") + local no_patched_font=$(tmux show-option -gqv "$NORD_TMUX_NO_PATCHED_FONT_OPTION") + local date_format=$(tmux show-option -gqv "$NORD_TMUX_STATUS_CONTENT_DATE_FORMAT") + + if [ "$(tmux show-option -gqv "clock-mode-style")" == '12' ]; then + tmux set-environment -g NORD_TMUX_STATUS_TIME_FORMAT "%I:%M %p" + else + tmux set-environment -g NORD_TMUX_STATUS_TIME_FORMAT "%H:%M" + fi + + if [ -z "$date_format" ]; then + tmux set-environment -g NORD_TMUX_STATUS_DATE_FORMAT "%Y-%m-%d" + else + tmux set-environment -g NORD_TMUX_STATUS_DATE_FORMAT "$date_format" + fi + + if [ "$status_content" != "0" ]; then + if [ "$no_patched_font" != "1" ]; then + tmux source-file "$_current_dir/$NORD_TMUX_STATUS_CONTENT_FILE" + else + tmux source-file "$_current_dir/$NORD_TMUX_STATUS_CONTENT_NO_PATCHED_FONT_FILE" + fi + fi +} + +__load +__cleanup diff --git a/dot_tmux/plugins/nord-tmux/license b/dot_tmux/plugins/nord-tmux/license new file mode 100644 index 0000000..996f8fb --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/license @@ -0,0 +1,21 @@ +MIT License (MIT) + +Copyright (c) 2016-present Sven Greb (https://www.svengreb.de) + +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/dot_tmux/plugins/nord-tmux/lint-staged.config.js b/dot_tmux/plugins/nord-tmux/lint-staged.config.js new file mode 100644 index 0000000..c8d4ec6 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/lint-staged.config.js @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016-present Sven Greb + * This source code is licensed under the MIT license found in the license file. + */ + +/** + * Configurations for lint-staged. + * @see https://github.com/okonet/lint-staged#configuration + */ +module.exports = { + "*.{json,tmux}": "prettier --check --ignore-unknown --no-editorconfig", + "*.{js,mjs}": ["eslint", "prettier --check --ignore-unknown --no-editorconfig"], + "*.md": ["remark --no-stdout", "prettier --check --ignore-unknown --no-editorconfig"], + ".husky/pre-*": "prettier --check --ignore-unknown --no-editorconfig", +}; diff --git a/dot_tmux/plugins/nord-tmux/package-lock.json b/dot_tmux/plugins/nord-tmux/package-lock.json new file mode 100644 index 0000000..ccd2f03 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/package-lock.json @@ -0,0 +1,7354 @@ +{ + "name": "@nordtheme/tmux", + "version": "0.3.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@nordtheme/tmux", + "version": "0.3.0", + "license": "MIT", + "devDependencies": { + "@svengreb/eslint-config-base": ">=0.12.0 <=1.0.0", + "@svengreb/remark-preset-lint": ">=0.5.0 <1.0.0", + "eslint": "8.39.0", + "eslint-config-prettier": "8.8.0", + "eslint-plugin-import": "2.27.5", + "eslint-plugin-prettier": "4.2.1", + "husky": "8.0.3", + "lint-staged": "13.2.2", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "prettier-plugin-sh": "0.12.8", + "remark-cli": "11.0.0" + }, + "engines": { + "node": ">=15.13", + "npm": ">=7.7" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", + "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.1", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz", + "integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/config": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@npmcli/config/-/config-6.1.6.tgz", + "integrity": "sha512-TM5dwgaz3Un2T5rdHQ6lX+Jj3TQxK6aV1U5OLByZiUS5qnA0NgC6U0aSESQVy80emToz8dtX3aniXD24wRnBaw==", + "dev": true, + "dependencies": { + "@npmcli/map-workspaces": "^3.0.2", + "ini": "^4.1.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/config/node_modules/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/map-workspaces": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-3.0.4.tgz", + "integrity": "sha512-Z0TbvXkRbacjFFLpVpV0e2mheCh+WzQpcqL+4xp49uNJOxOnIAPZyXtUxZ5Qn3QBTGKA11Exjd9a5411rBrhDg==", + "dev": true, + "dependencies": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/glob": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz", + "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.0", + "minipass": "^5.0.0", + "path-scurry": "^1.7.0" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", + "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/name-from-folder": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz", + "integrity": "sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/utils": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", + "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "is-glob": "^4.0.3", + "open": "^8.4.0", + "picocolors": "^1.0.0", + "tiny-glob": "^0.2.9", + "tslib": "^2.4.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@svengreb/eslint-config-base": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@svengreb/eslint-config-base/-/eslint-config-base-0.12.0.tgz", + "integrity": "sha512-kGZq/4uvZE3pzbUI3HZhlOqU4WJ/G3mArq/7RYPht6Fz60ST29UdeC7X7xuFiW4ffFt1dCQRLcETTdb4QEzmhA==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "1.0.11" + }, + "engines": { + "node": ">=15.13", + "npm": ">=7.7" + }, + "peerDependencies": { + "eslint": "^8.39.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-prettier": "^4.2.1" + } + }, + "node_modules/@svengreb/remark-preset-lint": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@svengreb/remark-preset-lint/-/remark-preset-lint-0.5.0.tgz", + "integrity": "sha512-6tCvB/o0F9pDVJz0jnR63MgsPIssbwfbXWvEQF6iGk2+XFTZ83SOM4Yd6CStM32IMPNaUMpDuw98uIsVrhZfvQ==", + "dev": true, + "dependencies": { + "remark-footnotes": "^4.0.1", + "remark-frontmatter": "^4.0.1", + "remark-gfm": "^3.0.1", + "remark-lint": "^9.1.1", + "remark-lint-blockquote-indentation": "^3.1.1", + "remark-lint-checkbox-character-style": "^4.1.1", + "remark-lint-checkbox-content-indent": "^4.1.1", + "remark-lint-code-block-style": "^3.1.0", + "remark-lint-definition-case": "^3.1.1", + "remark-lint-definition-spacing": "^3.1.1", + "remark-lint-emphasis-marker": "^3.1.1", + "remark-lint-fenced-code-flag": "^3.1.1", + "remark-lint-fenced-code-marker": "^3.1.1", + "remark-lint-file-extension": "^2.1.1", + "remark-lint-final-definition": "^3.1.1", + "remark-lint-final-newline": "^2.1.1", + "remark-lint-first-heading-level": "^3.1.1", + "remark-lint-hard-break-spaces": "^3.1.1", + "remark-lint-heading-increment": "^3.1.1", + "remark-lint-heading-style": "^3.1.1", + "remark-lint-linebreak-style": "^3.1.1", + "remark-lint-link-title-style": "^3.1.1", + "remark-lint-list-item-bullet-indent": "^4.1.1", + "remark-lint-list-item-content-indent": "^3.1.1", + "remark-lint-list-item-indent": "^3.1.1", + "remark-lint-list-item-spacing": "^4.1.1", + "remark-lint-maximum-heading-length": "^3.1.1", + "remark-lint-maximum-line-length": "^3.1.2", + "remark-lint-no-auto-link-without-protocol": "^3.1.1", + "remark-lint-no-blockquote-without-marker": "^5.1.1", + "remark-lint-no-consecutive-blank-lines": "^4.1.2", + "remark-lint-no-duplicate-defined-urls": "^2.1.1", + "remark-lint-no-duplicate-definitions": "^3.1.1", + "remark-lint-no-duplicate-headings": "^3.1.1", + "remark-lint-no-duplicate-headings-in-section": "^3.1.1", + "remark-lint-no-emphasis-as-heading": "^3.1.1", + "remark-lint-no-empty-url": "^3.1.1", + "remark-lint-no-file-name-articles": "^2.1.1", + "remark-lint-no-file-name-consecutive-dashes": "^2.1.1", + "remark-lint-no-file-name-irregular-characters": "^2.1.1", + "remark-lint-no-file-name-mixed-case": "^2.1.1", + "remark-lint-no-file-name-outer-dashes": "^2.1.1", + "remark-lint-no-heading-content-indent": "^4.1.1", + "remark-lint-no-heading-indent": "^4.1.1", + "remark-lint-no-heading-like-paragraph": "^3.1.1", + "remark-lint-no-heading-punctuation": "^3.1.1", + "remark-lint-no-html": "^3.1.1", + "remark-lint-no-inline-padding": "^4.1.1", + "remark-lint-no-literal-urls": "^3.1.1", + "remark-lint-no-missing-blank-lines": "^3.1.1", + "remark-lint-no-multiple-toplevel-headings": "^3.1.1", + "remark-lint-no-paragraph-content-indent": "^4.1.1", + "remark-lint-no-reference-like-url": "^3.1.1", + "remark-lint-no-shell-dollars": "^3.1.1", + "remark-lint-no-shortcut-reference-image": "^3.1.1", + "remark-lint-no-shortcut-reference-link": "^3.1.1", + "remark-lint-no-table-indentation": "^4.1.1", + "remark-lint-no-tabs": "^3.1.1", + "remark-lint-no-undefined-references": "^4.2.0", + "remark-lint-no-unneeded-full-reference-image": "^3.1.1", + "remark-lint-no-unneeded-full-reference-link": "^3.1.1", + "remark-lint-no-unused-definitions": "^3.1.1", + "remark-lint-ordered-list-marker-style": "^3.1.1", + "remark-lint-ordered-list-marker-value": "^3.1.1", + "remark-lint-rule-style": "^3.1.1", + "remark-lint-strikethrough-marker": "^2.1.1", + "remark-lint-strong-marker": "^3.1.1", + "remark-lint-table-cell-padding": "^4.1.2", + "remark-lint-table-pipe-alignment": "^3.1.1", + "remark-lint-table-pipes": "^4.1.1", + "remark-lint-unordered-list-marker-style": "^3.1.1" + }, + "engines": { + "node": ">=15.13", + "npm": ">=7.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/svengreb" + }, + "peerDependencies": { + "remark-cli": "^11.0.0" + } + }, + "node_modules/@types/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-t3YCerNM7NTVjLuICZo5gYAXYoDvpuuTceCcFQWcDQz26kxUR5uIWolxbIR5jRNIXpMqhOpW/b8imCR1LEmuJw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "dev": true + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.0.tgz", + "integrity": "sha512-3qvGd0z8F2ENTGr/GG1yViqfiKmRfrXVx5sJyHGFu3z7m5g5utCQtGp/g29JnjflhtQJBv1WDQukHiT58xPcYQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", + "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/is-empty": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/is-empty/-/is-empty-1.2.1.tgz", + "integrity": "sha512-a3xgqnFTuNJDm1fjsTjHocYJ40Cz3t8utYpi5GNaxzrJC2HSD08ym+whIL7fNqiqBCdM9bcqD1H/tORWAFXoZw==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/mdast": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", + "integrity": "sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.16.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.3.tgz", + "integrity": "sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==", + "dev": true + }, + "node_modules/@types/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==", + "dev": true + }, + "node_modules/@types/text-table": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@types/text-table/-/text-table-0.2.2.tgz", + "integrity": "sha512-dGoI5Af7To0R2XE8wJuc6vwlavWARsCh3UKJPjWs1YEqGUqfgBI/j/4GX0yf19/DsDPPf0YAXWAp8psNeIehLg==", + "dev": true + }, + "node_modules/@types/unist": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", + "dev": true + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dev": true, + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz", + "integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.2", + "@eslint/js": "8.39.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.0", + "espree": "^9.5.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", + "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", + "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "dev": true, + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", + "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globalyzer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", + "dev": true + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-meta-resolve": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-2.2.2.tgz", + "integrity": "sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.0.tgz", + "integrity": "sha512-HLR38RSF2iulAzc3I/sma4CoYxQP844rPYCNfzGDOHqa/YqVlwuuZgBx6M50/X8dKgzk0cm1qRg3+47mK2N+cQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-empty": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", + "integrity": "sha512-F2FnH/otLNJv0J6wc73A5Xo7oHLNnqplYqZhUu01tD54DIPvxIRSTSLkrUB/M0nHO4vo1O9PDfN4KoTxCzLh/w==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.1.5.tgz", + "integrity": "sha512-NeK3mbF9vwNS3SjhzlEfO6WREJqoKtCwLoUPoUVtGJrpecxN3ZxlDuF22MzNSbOk/AA/VFWi+nFMV89xkXh2og==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-sdsl": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/lint-staged": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.2.tgz", + "integrity": "sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA==", + "dev": true, + "dependencies": { + "chalk": "5.2.0", + "cli-truncate": "^3.1.0", + "commander": "^10.0.0", + "debug": "^4.3.4", + "execa": "^7.0.0", + "lilconfig": "2.1.0", + "listr2": "^5.0.7", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.3", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.2.2" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/listr2": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", + "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.19", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.8.0", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-plugin": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/load-plugin/-/load-plugin-5.1.0.tgz", + "integrity": "sha512-Lg1CZa1CFj2CbNaxijTL6PCbzd4qGTlZov+iH2p5Xwy/ApcZJh+i6jMN2cYePouTfjJfrNu3nXFdEw8LvbjPFQ==", + "dev": true, + "dependencies": { + "@npmcli/config": "^6.0.0", + "import-meta-resolve": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/markdown-table": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", + "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-comment-marker": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-comment-marker/-/mdast-comment-marker-2.1.2.tgz", + "integrity": "sha512-HED3ezseRVkBzZ0uK4q6RJMdufr/2p3VfVZstE3H1N9K8bwtspztWo6Xd7rEatuGNoCXaBna8oEqMwUn0Ve1bw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-mdx-expression": "^1.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.2.tgz", + "integrity": "sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-footnote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/mdast-util-footnote/-/mdast-util-footnote-1.1.1.tgz", + "integrity": "sha512-Y8JiA5fZm0kCqvugmSfaSvaVU2trhAmhCYXJOgPKVfmDa8isqzb5Tf7uWvCq4s8I+dll09GZjboItwZFSsD4JQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.0.tgz", + "integrity": "sha512-HN3W1gRIuN/ZW295c7zi7g9lVBllMgZE40RxCX37wrTPWXCWtpvOZdfnuK+1WNpvZje6XuJeI3Wnb4TJEUem+g==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "mdast-util-to-string": "^3.1.0", + "micromark": "^3.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-decode-string": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "unist-util-stringify-position": "^3.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-1.0.1.tgz", + "integrity": "sha512-JjA2OjxRqAa8wEG8hloD0uTU0kdn8kbtOWpPP94NBkfAlbxn4S8gCGf/9DwFtEeGPXrDcNXdiDjVaRdUFqYokw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.3.0", + "micromark-extension-frontmatter": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.2.tgz", + "integrity": "sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==", + "dev": true, + "dependencies": { + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-gfm-autolink-literal": "^1.0.0", + "mdast-util-gfm-footnote": "^1.0.0", + "mdast-util-gfm-strikethrough": "^1.0.0", + "mdast-util-gfm-table": "^1.0.0", + "mdast-util-gfm-task-list-item": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.3.tgz", + "integrity": "sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "ccount": "^2.0.0", + "mdast-util-find-and-replace": "^2.0.0", + "micromark-util-character": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.2.tgz", + "integrity": "sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.3.0", + "micromark-util-normalize-identifier": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.3.tgz", + "integrity": "sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.7.tgz", + "integrity": "sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-to-markdown": "^1.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.2.tgz", + "integrity": "sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-heading-style": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-heading-style/-/mdast-util-heading-style-2.0.1.tgz", + "integrity": "sha512-0L5rthU4xKDVbw+UQ7D8Y8xOEsX4JXZvemWoEAsL+WAaeSH+TvVVwFnTb3G/OrjyP4VYQULoNWU+PdZfkmNu4A==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz", + "integrity": "sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==", + "dev": true, + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^2.0.0", + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "mdast-util-to-markdown": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz", + "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "micromark-util-decode-string": "^1.0.0", + "unist-util-visit": "^4.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", + "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromark": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.1.0.tgz", + "integrity": "sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "micromark-core-commonmark": "^1.0.1", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz", + "integrity": "sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-factory-destination": "^1.0.0", + "micromark-factory-label": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-factory-title": "^1.0.0", + "micromark-factory-whitespace": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-html-tag-name": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-subtokenize": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.1", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-extension-footnote": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-footnote/-/micromark-extension-footnote-1.0.2.tgz", + "integrity": "sha512-sD7t/hooONLnbPYgcQpBcTjh7mPEcD2R/jRS5DLYDNm0XbngbaJZ01F1aI3v6VXVMdAu3XtFKUecNRlXbgGk/Q==", + "dev": true, + "dependencies": { + "micromark-core-commonmark": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-chunked": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-frontmatter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-1.1.0.tgz", + "integrity": "sha512-0nLelmvXR5aZ+F2IL6/Ed4cDnHLpL/VD/EELKuclsTWHrLI8UgxGHEmeoumeX2FXiM6z2WrBIOEcbKUZR8RYNg==", + "dev": true, + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.1.tgz", + "integrity": "sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA==", + "dev": true, + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^1.0.0", + "micromark-extension-gfm-footnote": "^1.0.0", + "micromark-extension-gfm-strikethrough": "^1.0.0", + "micromark-extension-gfm-table": "^1.0.0", + "micromark-extension-gfm-tagfilter": "^1.0.0", + "micromark-extension-gfm-task-list-item": "^1.0.0", + "micromark-util-combine-extensions": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.4.tgz", + "integrity": "sha512-WCssN+M9rUyfHN5zPBn3/f0mIA7tqArHL/EKbv3CZK+LT2rG77FEikIQEqBkv46fOqXQK4NEW/Pc7Z27gshpeg==", + "dev": true, + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.0.tgz", + "integrity": "sha512-RWYce7j8+c0n7Djzv5NzGEGitNNYO3uj+h/XYMdS/JinH1Go+/Qkomg/rfxExFzYTiydaV6GLeffGO5qcJbMPA==", + "dev": true, + "dependencies": { + "micromark-core-commonmark": "^1.0.0", + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.5.tgz", + "integrity": "sha512-X0oI5eYYQVARhiNfbETy7BfLSmSilzN1eOuoRnrf9oUNsPRrWOAe9UqSizgw1vNxQBfOwL+n2610S3bYjVNi7w==", + "dev": true, + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-classify-character": "^1.0.0", + "micromark-util-resolve-all": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.5.tgz", + "integrity": "sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg==", + "dev": true, + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.2.tgz", + "integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==", + "dev": true, + "dependencies": { + "micromark-util-types": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.4.tgz", + "integrity": "sha512-9XlIUUVnYXHsFF2HZ9jby4h3npfX10S1coXTnV035QGPgrtNYQq3J6IfIvcCIUAJrrqBVi5BqA/LmaOMJqPwMQ==", + "dev": true, + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz", + "integrity": "sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz", + "integrity": "sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz", + "integrity": "sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz", + "integrity": "sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz", + "integrity": "sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.1.0.tgz", + "integrity": "sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz", + "integrity": "sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz", + "integrity": "sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz", + "integrity": "sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz", + "integrity": "sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz", + "integrity": "sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^1.0.0", + "micromark-util-decode-numeric-character-reference": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz", + "integrity": "sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-html-tag-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz", + "integrity": "sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz", + "integrity": "sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz", + "integrity": "sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.1.0.tgz", + "integrity": "sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-encode": "^1.0.0", + "micromark-util-symbol": "^1.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz", + "integrity": "sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^1.0.0", + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0", + "uvu": "^0.5.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz", + "integrity": "sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.0.2.tgz", + "integrity": "sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mvdan-sh": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/mvdan-sh/-/mvdan-sh-0.10.1.tgz", + "integrity": "sha512-kMbrH0EObaKmK3nVRKUIIya1dpASHIEusM13S4V1ViHFuxuNxCo+arxoa6j/dbV22YBGjl7UKJm9QQKJ2Crzhg==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/nopt": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.1.0.tgz", + "integrity": "sha512-ZFPLe9Iu0tnx7oWhFxAo4s7QTn8+NNDDxYNaKLjE7Dp0tbakQ3M1QhQzsnzXHQBTUO3K9BmwaxnyO8Ayn2I95Q==", + "dev": true, + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.0.tgz", + "integrity": "sha512-g+DPQSkusnk7HYXr75NtzkIP4+N81i3RPsGFidF3DzHd9MT9wWngmqoeg/fnHFz5MNdtG4w03s+QnhewSLTT2Q==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/npm-run-all/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", + "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", + "dev": true, + "dependencies": { + "lru-cache": "^9.0.0", + "minipass": "^5.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", + "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prettier-plugin-sh": { + "version": "0.12.8", + "resolved": "https://registry.npmjs.org/prettier-plugin-sh/-/prettier-plugin-sh-0.12.8.tgz", + "integrity": "sha512-VOq8h2Gn5UzrCIKm4p/nAScXJbN09HdyFDknAcxt6Qu/tv/juu9bahxSrcnM9XWYA+Spz1F1ANJ4LhfwB7+Q1Q==", + "dev": true, + "dependencies": { + "mvdan-sh": "^0.10.1", + "sh-syntax": "^0.3.6", + "synckit": "^0.8.1" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + }, + "peerDependencies": { + "prettier": "^2.0.0" + } + }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/remark": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/remark/-/remark-14.0.2.tgz", + "integrity": "sha512-A3ARm2V4BgiRXaUo5K0dRvJ1lbogrbXnhkJRmD0yw092/Yl0kOCZt1k9ZeElEwkZsWGsMumz6qL5MfNJH9nOBA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "remark-parse": "^10.0.0", + "remark-stringify": "^10.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-cli": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-cli/-/remark-cli-11.0.0.tgz", + "integrity": "sha512-8JEWwArXquRq1/In4Ftz7gSG9Scwb1ijT2/dEuBETW9omqhmMRxcfjZ3iKqrak3BnCJeZSXCdWEmPhFKC8+RUQ==", + "dev": true, + "dependencies": { + "remark": "^14.0.0", + "unified-args": "^10.0.0" + }, + "bin": { + "remark": "cli.js" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-footnotes": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-4.0.1.tgz", + "integrity": "sha512-He6YzQFk/Wu2KgfjI80EyPXjt/G+WFaYfUH+xapqPQBdm3aTdEyzosXXv9a2FbTxGqgOfJ4q/TCB46v+wofRpQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-footnote": "^1.0.0", + "micromark-extension-footnote": "^1.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-frontmatter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-4.0.1.tgz", + "integrity": "sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-frontmatter": "^1.0.0", + "micromark-extension-frontmatter": "^1.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", + "integrity": "sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-gfm": "^2.0.0", + "micromark-extension-gfm": "^2.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-9.1.1.tgz", + "integrity": "sha512-zhe6twuqgkx/9KgZyNyaO0cceA4jQuJcyzMOBC+JZiAzMN6mFUmcssWZyY30ko8ut9vQDMX/pyQnolGn+Fg/Tw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "remark-message-control": "^7.0.0", + "unified": "^10.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-blockquote-indentation": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-blockquote-indentation/-/remark-lint-blockquote-indentation-3.1.1.tgz", + "integrity": "sha512-u9cjedM6zcK8vRicis5n/xeOSDIC3FGBCKc3K9pqw+nNrOjY85FwxDQKZZ/kx7rmkdRZEhgyHak+wzPBllcxBQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "pluralize": "^8.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-checkbox-character-style": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-checkbox-character-style/-/remark-lint-checkbox-character-style-4.1.1.tgz", + "integrity": "sha512-KPSW3wfHfB8m9hzrtHiBHCTUIsOPX5nZR7VM+2pMjwqnhI6Mp94DKprkNo1ekNZALNeoZIDWZUSYxSiiwFfmVQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-checkbox-content-indent": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-checkbox-content-indent/-/remark-lint-checkbox-content-indent-4.1.1.tgz", + "integrity": "sha512-apkM6sqCwAHwNV0v6KuEbq50fH3mTAV4wKTwI1nWgEj33/nf4+RvLLPgznoc2olZyeAIHR69EKPQiernjCXPOw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0", + "vfile-location": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-code-block-style": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/remark-lint-code-block-style/-/remark-lint-code-block-style-3.1.0.tgz", + "integrity": "sha512-Hv4YQ8ueLGpjItla4CkcOkcfGj+nlquqylDgCm1/xKnW+Ke2a4qVTMVJrP9Krp4FWmXgktJLDHjhRH+pzhDXLg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-definition-case": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-definition-case/-/remark-lint-definition-case-3.1.1.tgz", + "integrity": "sha512-dirX0BSfbm1Ixx4Hv4xRQliEP1rw8dDitw2Om3XcO2QqF8bWrzF06/xeMlDNAaT77Cxqb9S7bODo/q+CYUxyWQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-definition-spacing": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-definition-spacing/-/remark-lint-definition-spacing-3.1.1.tgz", + "integrity": "sha512-PR+cYvc0FMtFWjkaXePysW88r7Y7eIwbpUGPFDIWE48fiRiz8U3VIk05P3loQCpCkbmUeInAAYD8tIFPTg4Jlg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-emphasis-marker": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-emphasis-marker/-/remark-lint-emphasis-marker-3.1.1.tgz", + "integrity": "sha512-VduuT+KAr0vA78xBLJdIcenCQja4mAd81aNACfdz7BUPLphIQa84D5uzl+nZatSaCXLebCNp5jP/bzVUsBmRKw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-fenced-code-flag": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-fenced-code-flag/-/remark-lint-fenced-code-flag-3.1.1.tgz", + "integrity": "sha512-FFVZmYsBccKIIEgOtgdZEpQdARtAat1LTLBydnIpyNIvcntzWwtrtlj9mtjL8ZoSRre8HtwmEnBFyOfmM/NWaA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-fenced-code-marker": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-fenced-code-marker/-/remark-lint-fenced-code-marker-3.1.1.tgz", + "integrity": "sha512-x/t8sJWPvE46knKz6zW03j9VX5477srHUmRFbnXhZ3K8e37cYVUIvfbPhcPCAosSsOki9+dvGfZsWQiKuUNNfQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-file-extension": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-file-extension/-/remark-lint-file-extension-2.1.1.tgz", + "integrity": "sha512-r6OMe27YZzr2NFjPMbBxgm8RZxigRwzeFSjapPlqcxk0Q0w/6sosJsceBNlGGlk00pltvv7NPqSexbXUjirrQQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-final-definition": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-final-definition/-/remark-lint-final-definition-3.1.1.tgz", + "integrity": "sha512-94hRV+EBIuLVFooiimsZwh5ZPEcTqjy5wr7LgqxoUUWy+srTanndaLoki7bxQJeIcWUnomZncsJAyL0Lo7toxw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-final-newline": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-final-newline/-/remark-lint-final-newline-2.1.1.tgz", + "integrity": "sha512-cgKYaI7ujUse/kV4KajLv2j1kmi1CxpAu+w7wIU0/Faihhb3sZAf4a5ACf2Wu8NoTSIr1Q//3hDysG507PIoDg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-first-heading-level": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-first-heading-level/-/remark-lint-first-heading-level-3.1.1.tgz", + "integrity": "sha512-Z2+gn9sLyI/sT2c1JMPf1dj9kQkFCpL1/wT5Skm5nMbjI8/dIiTF2bKr9XKsFZUFP7GTA57tfeZvzD1rjWbMwg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-hard-break-spaces": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-hard-break-spaces/-/remark-lint-hard-break-spaces-3.1.1.tgz", + "integrity": "sha512-UfwFvESpX32qwyHJeluuUuRPWmxJDTkmjnWv2r49G9fC4Jrzm4crdJMs3sWsrGiQ3mSex6bgp/8rqDgtBng2IA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-heading-increment": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-heading-increment/-/remark-lint-heading-increment-3.1.1.tgz", + "integrity": "sha512-DtiMwZNAE/iAZWuZGjTXxYjNDQ375r59C99aVeVp1nKaovIufKuHWAm9U/9FAGBJNgBx6Ovfdej4YwIxd0yAPw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-heading-style": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-heading-style/-/remark-lint-heading-style-3.1.1.tgz", + "integrity": "sha512-Qm7ZAF+s46ns0Wo5TlHGIn/PPMMynytn8SSLEdMIo6Uo/+8PAcmQ3zU1pj57KYxfyDoN5iQPgPIwPYMLYQ2TSQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-heading-style": "^2.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-linebreak-style": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-linebreak-style/-/remark-lint-linebreak-style-3.1.1.tgz", + "integrity": "sha512-zE6Ku/j6gAT12uFzsmxSaJyD1SAFwQWvAS+83wp6BmdokiU7ruuM3cgUShhQ8PPe9e3crJLEGDaa1Tu3ejxdSg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "vfile-location": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-link-title-style": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-link-title-style/-/remark-lint-link-title-style-3.1.1.tgz", + "integrity": "sha512-JWWiuUFy/N2iwQ3eWIxFy6olX8D7xCFw8LoM0vZI2CHTZJrmDMaWwnl8jziP+HHHheFX3wkVqsoaYod536ArRw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0", + "vfile-location": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-list-item-bullet-indent": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-bullet-indent/-/remark-lint-list-item-bullet-indent-4.1.1.tgz", + "integrity": "sha512-NFvXVj1Nm12+Ma48NOjZCGb/D0IhmUcxyrTCpPp+UNJhEWrmFxM8nSyIiZgXadgXErnuv+xm2Atw7TAcZ9a1Cg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "pluralize": "^8.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-list-item-content-indent": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-content-indent/-/remark-lint-list-item-content-indent-3.1.1.tgz", + "integrity": "sha512-gcZhAXLd1onkutTEqQTybyANjdxvlOlu0y/AU4H3f6L99UGC85ymRhEeu5vGSkvsKKPR1FrMTEH6G2nNgtavgg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "pluralize": "^8.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-list-item-indent": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-indent/-/remark-lint-list-item-indent-3.1.1.tgz", + "integrity": "sha512-OSTG64e52v8XBmmeT0lefpiAfCMYHJxMMUrMnhTjLVyWAbEO0vqqR5bLvfLwzK+P4nY2D/8XKku0hw35dM86Rw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "pluralize": "^8.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-list-item-spacing": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-spacing/-/remark-lint-list-item-spacing-4.1.1.tgz", + "integrity": "sha512-MqXmahPgYrvfA7SPqmcAC6fI40jIgXG33EeE/MhFvMLWh04k+fqGf2O2aH1KT664MlwM4oETbTI4xj3/KCIHZA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-maximum-heading-length": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-maximum-heading-length/-/remark-lint-maximum-heading-length-3.1.1.tgz", + "integrity": "sha512-hTOvRDnULpu0S+k51lovT28TLBgtw8XR0qq+mECSsoyuT4C38UBjQRic5OPo68AZMH0ad/93uj6yvfFtH0K8Lg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-maximum-line-length": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/remark-lint-maximum-line-length/-/remark-lint-maximum-line-length-3.1.2.tgz", + "integrity": "sha512-KwddpVmNifTHNXwTQQgVufuUvv0hhu9kJVvmpNdEvfEc7tc3wBkaavyi3kKsUB8WwMhGtZuXVWy6OdPC1axzhw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-auto-link-without-protocol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-auto-link-without-protocol/-/remark-lint-no-auto-link-without-protocol-3.1.1.tgz", + "integrity": "sha512-lCjBuoSUWjN1kO0J7vqQgn7HUF/WeOHOqc3oiq9LMRXIovKWqPCBi77o8Npv8KfV+JXeRl+hrupfbhJXlLturA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-blockquote-without-marker": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-blockquote-without-marker/-/remark-lint-no-blockquote-without-marker-5.1.1.tgz", + "integrity": "sha512-7jL7eKS25kKRhQ7SKKB5eRfNleDMWKWAmZ5Y/votJdDoM+6qsopLLumPWaSzP0onyV3dyHRhPfBtqelt3hvcyA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0", + "vfile-location": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-consecutive-blank-lines": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/remark-lint-no-consecutive-blank-lines/-/remark-lint-no-consecutive-blank-lines-4.1.2.tgz", + "integrity": "sha512-wRsR3kFgHaZ4mO3KASU43oXGLGezNZ64yNs1ChPUacKh0Bm7cwGnxN9GHGAbOXspwrYrN2eCDxzCbdPEZi2qKw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "pluralize": "^8.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-duplicate-defined-urls": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-defined-urls/-/remark-lint-no-duplicate-defined-urls-2.1.1.tgz", + "integrity": "sha512-iMiJVabYt22vxfinDkf6xOSCJ9N6kDfnqjM4U8cFOHIui6Oo5rjlfl2qYHl7uRFaIjwKIZBho4NL07vOcxp+KQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-stringify-position": "^3.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-duplicate-definitions": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-definitions/-/remark-lint-no-duplicate-definitions-3.1.1.tgz", + "integrity": "sha512-9p+nBz8VvV+t4g/ALNLVN8naV+ffAzC4ADyg9QivzmKwLjyF93Avt4HYNlb2GZ+aoXRQSVG1wjjWFeDC9c7Tdg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-stringify-position": "^3.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-duplicate-headings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-headings/-/remark-lint-no-duplicate-headings-3.1.1.tgz", + "integrity": "sha512-gSO/BngGkxF35Fsctzt3YMwGEZ8F7f71zx7h0Y97DylyL6WXVuWP4saCmQTlbB4FpD0UXEnRROJ6fBFDvJlzOA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-stringify-position": "^3.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-duplicate-headings-in-section": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-headings-in-section/-/remark-lint-no-duplicate-headings-in-section-3.1.1.tgz", + "integrity": "sha512-hv8GJXcPmpMdIxyQUuem7OUe9pR475Tmq+7ocyRDGODMpgBfMSO6gvNGJkdZin1zeGba0EF8ku3ksvkyodKX1Q==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-stringify-position": "^3.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-emphasis-as-heading": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-emphasis-as-heading/-/remark-lint-no-emphasis-as-heading-3.1.1.tgz", + "integrity": "sha512-F45yuLsYVP4r6OjVtePKk7Aymnf3rBLHXYjnSJggEaYn0j+72xOBLrqmj6ii5YGfDsBwG2pDNTBx4vm3xM7P0Q==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-empty-url": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-empty-url/-/remark-lint-no-empty-url-3.1.1.tgz", + "integrity": "sha512-zxIkDMggf6R/NCDkYAsaVHaFhklkp6WvV/wdeJAzT3BverGFnM8QIHUAv8YIQvCGqYWov275SVN1eu81DoU95g==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-file-name-articles": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-articles/-/remark-lint-no-file-name-articles-2.1.1.tgz", + "integrity": "sha512-7fiHKQUGvP4WOsieZ1dxm8WQWWjXjPj0Uix6pk2dSTJqxvaosjKH1AV0J/eVvliat0BGH8Cz4SUbuz5vG6YbdQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-file-name-consecutive-dashes": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-consecutive-dashes/-/remark-lint-no-file-name-consecutive-dashes-2.1.1.tgz", + "integrity": "sha512-tM4IpURGuresyeIBsXT5jsY3lZakgO6IO59ixcFt015bFjTOW54MrBvdJxA60QHhf5DAyHzD8wGeULPSs7ZQfg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-file-name-irregular-characters": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-irregular-characters/-/remark-lint-no-file-name-irregular-characters-2.1.1.tgz", + "integrity": "sha512-rVeCv1XRdLtp/rxLaiFKElaIHuIlokypV/c2aCG3VVYcQ4+ZmJxq018kEsolR2+Dv9m3vKp8Fy1482US4g4WKA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-file-name-mixed-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-mixed-case/-/remark-lint-no-file-name-mixed-case-2.1.1.tgz", + "integrity": "sha512-mJU3hYzyXNo8NkoSafPcsgr+Gema+vDCzNWlLw05UdFXJK/cVy+6DVsbrEFjrz8L+WF7uQmUHBtTvd91SqoItg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-file-name-outer-dashes": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-file-name-outer-dashes/-/remark-lint-no-file-name-outer-dashes-2.1.1.tgz", + "integrity": "sha512-2kRcVNzZb0zS3jE+Iaa6MEpplhqXSdsHBILS+BxJ4cDGAAIdeipY8hKaDLdZi+34wvrfnDxNgvNLcHpgqO+OZA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-heading-content-indent": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-heading-content-indent/-/remark-lint-no-heading-content-indent-4.1.1.tgz", + "integrity": "sha512-W4zF7MA72IDC5JB0qzciwsnioL5XlnoE0r1F7sDS0I5CJfQtHYOLlxb3UAIlgRCkBokPWCp0E4o1fsY/gQUKVg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-heading-style": "^2.0.0", + "pluralize": "^8.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-heading-indent": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-heading-indent/-/remark-lint-no-heading-indent-4.1.1.tgz", + "integrity": "sha512-3vIfT7gPdpE9D7muIQ6YzSF1q27H9SbsDD7ClJRkEWxMiAzBg0obOZFOIBYukUkmGWdOR5P1EDn5n9TEzS1Fyg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "pluralize": "^8.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-heading-like-paragraph": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-heading-like-paragraph/-/remark-lint-no-heading-like-paragraph-3.1.1.tgz", + "integrity": "sha512-eDQkw1ir0j2VVmZd60Hy3CUAj85U7zKf59bGEBdXr2OQYJQhvme7XqKwY8QfMlBqn9lYg1/DxsGWt0+5ESIogw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-heading-punctuation": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-heading-punctuation/-/remark-lint-no-heading-punctuation-3.1.1.tgz", + "integrity": "sha512-ZexHx4rmsjKVF1/Fvdig0yOgpWl0wFa43+sqg880HT3PW9KmEczjSRkwlMaTlVgDzC0paNn2FXfQMuEQW4YDLg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-html": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-html/-/remark-lint-no-html-3.1.1.tgz", + "integrity": "sha512-hTaw6Ul3iAXvesWzvl+ev1tVf1SNm7hG3l7A2pj8r+1MlklKDFeaMWsxKnDh+8Rh6pj+mRnwzsbwtQxKiKs9Cw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-inline-padding": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-inline-padding/-/remark-lint-no-inline-padding-4.1.1.tgz", + "integrity": "sha512-++IMm6ohOPKNOrybqjP9eiclEtVX/Rd2HpF2UD9icrC1X5nvrI6tlfN55tePaFvWAB7pe6MW4LzNEMnWse61Lw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-literal-urls": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-literal-urls/-/remark-lint-no-literal-urls-3.1.1.tgz", + "integrity": "sha512-tZZ4gtZMA//ZAf7GJTE8S9yjzqXUfUTlR/lvU7ffc7NeSurqCBwAtHqeXVCHiD39JnlHVSW2MLYhvHp53lBGvA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-missing-blank-lines": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-missing-blank-lines/-/remark-lint-no-missing-blank-lines-3.1.1.tgz", + "integrity": "sha512-QF1gXD/jhC7NsQuRK3Ho8KAxak01s6eJRruYkNjYeqdtAzZrRu2dR1ySKFGGyDKpmfY56kb0fqIKB6V1dSAqNA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-multiple-toplevel-headings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-multiple-toplevel-headings/-/remark-lint-no-multiple-toplevel-headings-3.1.1.tgz", + "integrity": "sha512-bM//SIBvIkoGUpA8hR5QibJ+7C2R50PTIRrc4te93YNRG+ie8bJzjwuO9jIMedoDfJB6/+7EqO9FYBivjBZ3MA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-stringify-position": "^3.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-paragraph-content-indent": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-paragraph-content-indent/-/remark-lint-no-paragraph-content-indent-4.1.1.tgz", + "integrity": "sha512-yIjMGz8YClzois639AJ9PRvA+9thRdwKIaFaMRFAEL7Q6U2IuwOvsBDe6Y/x1gnE8sBTwiwKYDgeF6rnBsUYrQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0", + "vfile-location": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-reference-like-url": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-reference-like-url/-/remark-lint-no-reference-like-url-3.1.1.tgz", + "integrity": "sha512-ELO2uez1NO9wEb2nNRY4uVBfw4TYYUHWOnLajExGY92+i3Ylt3EmMwRONT2maJX5qKj4cu8uPi7HAkMIxq8jFg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-shell-dollars": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-shell-dollars/-/remark-lint-no-shell-dollars-3.1.1.tgz", + "integrity": "sha512-Q3Ad1TaOPxbYog5+Of/quPG3Fy+dMKiHjT8KsU7NDiHG6YJOnAJ3f3w+y13CIlNIaKc/MrisgcthhrZ7NsgXfA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-shortcut-reference-image": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-image/-/remark-lint-no-shortcut-reference-image-3.1.1.tgz", + "integrity": "sha512-m8tH+loDagd1JUns/T4eyulVXgVvE+ZSs7owRUOmP+dgsKJuO5sl1AdN9eyKDVMEvxHF3Pm5WqE62QIRNM48mA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-shortcut-reference-link": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-link/-/remark-lint-no-shortcut-reference-link-3.1.1.tgz", + "integrity": "sha512-oDJ92/jXQ842HgrBGgZdP7FA+N2jBMCBU2+jRElkS+OWVut0UaDILtNavNy/e85B3SLPj3RoXKF96M4vfJ7B2A==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-table-indentation": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-table-indentation/-/remark-lint-no-table-indentation-4.1.1.tgz", + "integrity": "sha512-eklvBxUSrkVbJxeokepOvFZ3n2V6zaJERIiOowR+y/Bz4dRHDMij1Ojg55AMO9yUMvxWPV3JPOeThliAcPmrMg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0", + "vfile-location": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-tabs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-tabs/-/remark-lint-no-tabs-3.1.1.tgz", + "integrity": "sha512-+MjXoHSSqRFUUz6XHgB1z7F5zIETxhkY+lC5LsOYb1r2ZdujZQWzBzNW5ya4HH5JiDVBPhp8MrqM9cP1v7tB5g==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "vfile-location": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-undefined-references": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/remark-lint-no-undefined-references/-/remark-lint-no-undefined-references-4.2.0.tgz", + "integrity": "sha512-EDV9B1ZXMLcKVtMQFvfvtbag4AkLcu8aUNGXoez5GJLcCAQ8Q+sG74yOtIW4xNVlVubEjl0vdkFhaKYLxvn2Sw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0", + "vfile-location": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-unneeded-full-reference-image": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-unneeded-full-reference-image/-/remark-lint-no-unneeded-full-reference-image-3.1.1.tgz", + "integrity": "sha512-jXKCNrMVPHG03N87MtgNAd9j4i9LInUXMpfylrXyUw9JT4VSH5OoMzhzp1Ra2442kQRQ6Z/gd3cClPyox01BQg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-unneeded-full-reference-link": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-unneeded-full-reference-link/-/remark-lint-no-unneeded-full-reference-link-3.1.1.tgz", + "integrity": "sha512-SWSUdP9dVChVWaIxE5qkm9Uxa82BRaGWlUmGMJfUAS9y9ceOZjVcmgJ3FMW5JZrlrw0jmihR7yLRr0d2uB86sg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "micromark-util-normalize-identifier": "^1.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-no-unused-definitions": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-3.1.1.tgz", + "integrity": "sha512-/GtyBukhAxi5MEX/g/m+FzDEflSbTe2/cpe2H+tJZyDmiLhjGXRdwWnPRDp+mB9g1iIZgVRCk7T4v90RbQX/mw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-ordered-list-marker-style": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-style/-/remark-lint-ordered-list-marker-style-3.1.1.tgz", + "integrity": "sha512-IWcWaJoaSb4yoSOuvDbj9B2uXp9kSj58DqtrMKo8MoRShmbj1onVfulTxoTLeLtI11NvW+mj3jPSpqjMjls+5Q==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-ordered-list-marker-value": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-value/-/remark-lint-ordered-list-marker-value-3.1.1.tgz", + "integrity": "sha512-+bQZbo+v/A8CuLrO71gobJuKR4/sfnPgWyEggSa+zq+LXPK1HiMDjap0Wr07uYgcUXsXIPh+HD/5J5by6JL+vg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-rule-style": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-rule-style/-/remark-lint-rule-style-3.1.1.tgz", + "integrity": "sha512-+oZe0ph4DWHGwPkQ/FpqiGp4WULTXB1edftnnNbizYT+Wr+/ux7GNTx78oXH/PHwlnOtVIExMc4W/vDXrUj/DQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-strikethrough-marker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-strikethrough-marker/-/remark-lint-strikethrough-marker-2.1.1.tgz", + "integrity": "sha512-Yjy0LCZLMX7yLZO1+8qnDi1guxHUhKoHcWWwHPDyCPiuiStbWEbcOn152yEn8401csU0mryOfwM1EDBjzHWbOg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-strong-marker": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-strong-marker/-/remark-lint-strong-marker-3.1.1.tgz", + "integrity": "sha512-tX9Os2C48Hh8P8CouY4dcnAhGnR3trL+NCDqIvJvFDR9Rvm9yfNQaY2N4ZHWVY0iUicq9DpqEiJTgUsT8AGv/w==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-table-cell-padding": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/remark-lint-table-cell-padding/-/remark-lint-table-cell-padding-4.1.2.tgz", + "integrity": "sha512-cx5BXjHtpACa7Z51Vuqzy9BI4Z8Hnxz7vklhhrubkoB7mbctP/mR+Nh4B8eE5VtgFYJNHFwIltl96PuoctFCeQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-table-pipe-alignment": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-table-pipe-alignment/-/remark-lint-table-pipe-alignment-3.1.1.tgz", + "integrity": "sha512-WOHv2yL4ZwXHM06MIyQNnGFYKz9m2k/GFIA/6hpArF8Ph/3v8CF0J/Hb3Yyfg39e5nODw3D2G3okCO+xgyGQGA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-table-pipes": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-table-pipes/-/remark-lint-table-pipes-4.1.1.tgz", + "integrity": "sha512-mJnB2FpjJTE4s9kE1JX8gcCjCFvtGPjzXUiQy0sbPHn2YM9EWG7kvFWYoqWK4w569CEQJyxZraEPltmhDjQTjg==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-lint-unordered-list-marker-style": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-lint-unordered-list-marker-style/-/remark-lint-unordered-list-marker-style-3.1.1.tgz", + "integrity": "sha512-JwH8oIDi9f5Z8cTQLimhJ/fkbPwI3OpNSifjYyObNNuc4PG4/NUoe5ZuD10uPmPYHZW+713RZ8S5ucVCkI8dDA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "unified": "^10.0.0", + "unified-lint-rule": "^2.0.0", + "unist-util-generated": "^2.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-message-control": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/remark-message-control/-/remark-message-control-7.1.1.tgz", + "integrity": "sha512-xKRWl1NTBOKed0oEtCd8BUfH5m4s8WXxFFSoo7uUwx6GW/qdCy4zov5LfPyw7emantDmhfWn5PdIZgcbVcWMDQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-comment-marker": "^2.0.0", + "unified": "^10.0.0", + "unified-message-control": "^4.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz", + "integrity": "sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-from-markdown": "^1.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-10.0.2.tgz", + "integrity": "sha512-6wV3pvbPvHkbNnWB0wdDvVFHOe1hBRAx1Q/5g/EpH4RppAII6J8Gnwe7VbHuXaoKIF6LAg6ExTel/+kNqSQ7lw==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-markdown": "^1.0.0", + "unified": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/sh-syntax": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/sh-syntax/-/sh-syntax-0.3.7.tgz", + "integrity": "sha512-xIB/uRniZ9urxAuXp1Ouh/BKSI1VK8RSqfwGj7cV57HvGrFo3vHdJfv8Tdp/cVcxJgXQTkmHr5mG5rqJW8r4wQ==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", + "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/tiny-glob": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", + "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", + "dev": true, + "dependencies": { + "globalyzer": "0.1.0", + "globrex": "^0.1.2" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-vfile": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/to-vfile/-/to-vfile-7.2.4.tgz", + "integrity": "sha512-2eQ+rJ2qGbyw3senPI0qjuM7aut8IYXK6AEoOWb+fJx/mQYzviTckm1wDjq91QYHAPBTYzmdJXxMFA6Mk14mdw==", + "dev": true, + "dependencies": { + "is-buffer": "^2.0.0", + "vfile": "^5.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/trough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", + "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unified": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", + "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "bail": "^2.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified-args": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/unified-args/-/unified-args-10.0.0.tgz", + "integrity": "sha512-PqsqxwkXpGSLiMkbjNnKU33Ffm6gso6rAvz1TlBGzMBx3gpx7ewIhViBX8HEWmy0v7pebA5PM6RkRWWaYmtfYw==", + "dev": true, + "dependencies": { + "@types/text-table": "^0.2.0", + "camelcase": "^7.0.0", + "chalk": "^5.0.0", + "chokidar": "^3.0.0", + "fault": "^2.0.0", + "json5": "^2.0.0", + "minimist": "^1.0.0", + "text-table": "^0.2.0", + "unified-engine": "^10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified-args/node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/unified-args/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/unified-engine": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/unified-engine/-/unified-engine-10.1.0.tgz", + "integrity": "sha512-5+JDIs4hqKfHnJcVCxTid1yBoI/++FfF/1PFdSMpaftZZZY+qg2JFruRbf7PaIwa9KgLotXQV3gSjtY0IdcFGQ==", + "dev": true, + "dependencies": { + "@types/concat-stream": "^2.0.0", + "@types/debug": "^4.0.0", + "@types/is-empty": "^1.0.0", + "@types/node": "^18.0.0", + "@types/unist": "^2.0.0", + "concat-stream": "^2.0.0", + "debug": "^4.0.0", + "fault": "^2.0.0", + "glob": "^8.0.0", + "ignore": "^5.0.0", + "is-buffer": "^2.0.0", + "is-empty": "^1.0.0", + "is-plain-obj": "^4.0.0", + "load-plugin": "^5.0.0", + "parse-json": "^6.0.0", + "to-vfile": "^7.0.0", + "trough": "^2.0.0", + "unist-util-inspect": "^7.0.0", + "vfile-message": "^3.0.0", + "vfile-reporter": "^7.0.0", + "vfile-statistics": "^2.0.0", + "yaml": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified-engine/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/unified-engine/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/unified-engine/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/unified-engine/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/unified-engine/node_modules/parse-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-6.0.2.tgz", + "integrity": "sha512-SA5aMiaIjXkAiBrW/yPgLgQAQg42f7K3ACO+2l/zOvtQBwX58DMUsFJXelW2fx3yMBmWOVkR6j1MGsdSbCA4UA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.0", + "error-ex": "^1.3.2", + "json-parse-even-better-errors": "^2.3.1", + "lines-and-columns": "^2.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unified-lint-rule": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-2.1.1.tgz", + "integrity": "sha512-vsLHyLZFstqtGse2gvrGwasOmH8M2y+r2kQMoDSWzSqUkQx2MjHjvZuGSv5FUaiv4RQO1bHRajy7lSGp7XWq5A==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "trough": "^2.0.0", + "unified": "^10.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified-message-control": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unified-message-control/-/unified-message-control-4.0.0.tgz", + "integrity": "sha512-1b92N+VkPHftOsvXNOtkJm4wHlr+UDmTBF2dUzepn40oy9NxanJ9xS1RwUBTjXJwqr2K0kMbEyv1Krdsho7+Iw==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit": "^3.0.0", + "vfile": "^5.0.0", + "vfile-location": "^4.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified-message-control/node_modules/unist-util-visit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-3.1.0.tgz", + "integrity": "sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified-message-control/node_modules/unist-util-visit-parents": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz", + "integrity": "sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-generated": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", + "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-inspect": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/unist-util-inspect/-/unist-util-inspect-7.0.2.tgz", + "integrity": "sha512-Op0XnmHUl6C2zo/yJCwhXQSm/SmW22eDZdWP2qdf4WpGrgO1ZxFodq+5zFyeRGasFjJotAnLgfuD1jkcKqiH1Q==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/uvu": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", + "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", + "dev": true, + "dependencies": { + "dequal": "^2.0.0", + "diff": "^5.0.0", + "kleur": "^4.0.3", + "sade": "^1.7.3" + }, + "bin": { + "uvu": "bin.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vfile": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", + "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", + "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "vfile": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", + "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-reporter": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-7.0.5.tgz", + "integrity": "sha512-NdWWXkv6gcd7AZMvDomlQbK3MqFWL1RlGzMn++/O2TI+68+nqxCPTvLugdOtfSzXmjh+xUyhp07HhlrbJjT+mw==", + "dev": true, + "dependencies": { + "@types/supports-color": "^8.0.0", + "string-width": "^5.0.0", + "supports-color": "^9.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile": "^5.0.0", + "vfile-message": "^3.0.0", + "vfile-sort": "^3.0.0", + "vfile-statistics": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-reporter/node_modules/supports-color": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.3.1.tgz", + "integrity": "sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/vfile-sort": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-3.0.1.tgz", + "integrity": "sha512-1os1733XY6y0D5x0ugqSeaVJm9lYgj0j5qdcZQFyxlZOSy1jYarL77lLyb5gK4Wqr1d5OxmuyflSO3zKyFnTFw==", + "dev": true, + "dependencies": { + "vfile": "^5.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-statistics": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-2.0.1.tgz", + "integrity": "sha512-W6dkECZmP32EG/l+dp2jCLdYzmnDBIw6jwiLZSER81oR5AHRcVqL+k3Z+pfH1R73le6ayDkJRMk0sutj1bMVeg==", + "dev": true, + "dependencies": { + "vfile": "^5.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/walk-up-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", + "dev": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", + "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/dot_tmux/plugins/nord-tmux/package.json b/dot_tmux/plugins/nord-tmux/package.json new file mode 100644 index 0000000..ab78b9d --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/package.json @@ -0,0 +1,51 @@ +{ + "name": "@nordtheme/tmux", + "version": "0.3.0", + "description": "An arctic, north-bluish clean and elegant tmux color theme", + "author": { + "name": "Sven Greb", + "email": "development@svengreb.de", + "url": "https://www.svengreb.de" + }, + "homepage": "https://www.nordtheme.com/ports/tmux", + "repository": { + "type": "git", + "url": "git+https://github.com/nordtheme/tmux.git" + }, + "bugs": { + "url": "https://github.com/nordtheme/tmux/issues" + }, + "license": "MIT", + "private": true, + "engines": { + "node": ">=15.13", + "npm": ">=7.7" + }, + "scripts": { + "format": "run-s format:*", + "format:js": "eslint --fix .", + "format:pretty": "prettier --ignore-unknown --no-editorconfig --write \"**\"", + "lint": "run-s lint:js lint:md lint:pretty", + "lint:ci": "run-s --continue-on-error lint:js lint:md lint:ci:pretty", + "lint:ci:pretty": "prettier --check --ignore-unknown --loglevel silent --no-editorconfig --no-error-on-unmatched-pattern \"**\"", + "lint:js": "eslint .", + "lint:md": "remark --no-stdout . .github/", + "lint:pretty": "prettier --check --ignore-unknown --no-editorconfig \"**\"", + "prepare:husky": "husky install", + "prepare": "run-s prepare:*" + }, + "devDependencies": { + "@svengreb/eslint-config-base": ">=0.12.0 <=1.0.0", + "@svengreb/remark-preset-lint": ">=0.5.0 <1.0.0", + "eslint": "8.39.0", + "eslint-config-prettier": "8.8.0", + "eslint-plugin-import": "2.27.5", + "eslint-plugin-prettier": "4.2.1", + "husky": "8.0.3", + "lint-staged": "13.2.2", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "prettier-plugin-sh": "0.12.8", + "remark-cli": "11.0.0" + } +} diff --git a/dot_tmux/plugins/nord-tmux/prettier.config.js b/dot_tmux/plugins/nord-tmux/prettier.config.js new file mode 100644 index 0000000..4d92c27 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/prettier.config.js @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016-present Sven Greb + * This source code is licensed under the MIT license found in the license file. + */ + +/** + * Configurations for Prettier. + * @see https://prettier.io/docs/en/configuration.html + * @see https://prettier.io/docs/en/options.html + * @see https://prettier.io/docs/en/options.html#parser + * @see https://prettier.io/docs/en/plugins.html + * @see https://github.com/un-ts/prettier/tree/master/packages/sh + */ +module.exports = { + printWidth: 160, + overrides: [ + { + files: [".husky/*", "*.tmux"], + options: { + parser: "sh", + }, + }, + ], +}; diff --git a/dot_tmux/plugins/nord-tmux/readme.md b/dot_tmux/plugins/nord-tmux/readme.md new file mode 100644 index 0000000..92de3e5 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/readme.md @@ -0,0 +1,169 @@ +

+ + + + + + +

+ +

+ + + + + + + + + +

+ +

+ + + + + + + + + +

+ +

+ + + +

+ +

An arctic, north-bluish clean and elegant tmux color theme.

+ +

Designed for a fluent and clear workflow based on the Nord color palette.

+ +

+ + + +

+ +## Getting Started + +Visit the [official website][nord-home] to learn all about the [fluidly merging appearance][nord-home#intro] features, details and elements of [UI elements][nord-home#ui-elements], the [various theme configurations][nord-home#configurations] and the [support for plugins][nord-home#plugin-support]. + +Learn about the [installation and activation][nord-docs-home-install], how to [configure][nord-docs-home-config] the theme and [supported plugins][nord-docs-home-plugins] from the [official documentations][nord-docs-home]. + +### Quick Start + +Thanks to existing plugin managers for tmux, Nord tmux can be installed for all platforms in a uniform way within a few lines of codes. The recommended manager is [tpm][gh-tmux-plugins/tpm], but any other manager like [tundle][gh-javier-lopez/tundle] can also be used. + +To automatically download and activate Nord tmux, follow the install instructions for [tpm][gh-tmux-plugins/tpm] and + +1. add `set -g @plugin "nordtheme/tmux"` to your [`tmux.conf`][tmux-man-tmux.conf], by default `.tmux.conf` located in your [home directory][wiki-home_dir] +2. press the default key binding `prefix` + I to fetch- and install the plugin + +

+ + + +

+ +See the Nord tmux's documentation for [more installation options][nord-docs-home-install] and how to [set it up manually][nord-docs-home-install#manual]. +Also see [_tpm's_ install instructions][gh-tpm-docs-install-plugins] for more details. + +## Features + +
+

Your terminal. Your style.

+

The unified UI element design provides a clutter-free and fluidly merging appearance.

+
+ +

+ + + +

+ +

+ + + +

+ +
+

Uniform design with beautiful UI elements.

+

The themed UI elements provide a fluid and unobtrusive transition from the terminal to the tmux status bar.

+
+ +

+ + + +

+ +

Take your favorite plugins with you.

The theme supports popular plugins for a fluid and unobtrusive user interface transition.

+ +

+ + + +

+ +## Contributing + +Nord is an open source project and we love to receive contributions from the [community][nord-comm]! + +There are many ways to contribute, from [writing- and improving documentation and tutorials][nord-contrib-guide-docs], [reporting bugs][nord-contrib-guide-bugs], [submitting enhancement suggestions][nord-contrib-guide-enhance] that can be added to Nord by [submitting pull requests][nord-contrib-guide-pr]. + +Please take a moment to read Nord's full [contributing guide][nord-contrib-guide] to learn about the development process, the project's used [styleguides][nord-contrib-guide-styles], [branch organization][nord-contrib-guide-branching] and [versioning][nord-contrib-guide-versioning] model. + +The guide also includes information about [minimal, complete, and verifiable examples][nord-contrib-guide-mcve] and other ways to contribute to the project like [improving existing issues][nord-contrib-guide-impr-issues] and [giving feedback on issues and pull requests][nord-contrib-guide-feedback]. + +

+ + + + + +

+ +

+ Copyright © 2016-present Sven Greb +

+ +

+ + + + + + +

+ +[gh-javier-lopez/tundle]: https://github.com/javier-lopez/tundle +[gh-tmux-plugins/tpm]: https://github.com/tmux-plugins/tpm +[gh-tpm-docs-install-plugins]: https://github.com/tmux-plugins/tpm#installing-plugins +[nord-comm]: https://www.nordtheme.com/community +[nord-contrib-guide-branching]: https://github.com/nordtheme/.github/blob/main/contributing.md#branch-organization +[nord-contrib-guide-bugs]: https://github.com/nordtheme/.github/blob/main/contributing.md#bug-reports +[nord-contrib-guide-docs]: https://github.com/nordtheme/.github/blob/main/contributing.md#documentations +[nord-contrib-guide-enhance]: https://github.com/nordtheme/.github/blob/main/contributing.md#enhancement-suggestions +[nord-contrib-guide-feedback]: https://github.com/nordtheme/.github/blob/main/contributing.md#feedback +[nord-contrib-guide-impr-issues]: https://github.com/nordtheme/.github/blob/main/contributing.md#improve-issues +[nord-contrib-guide-mcve]: https://github.com/nordtheme/.github/blob/main/contributing.md#mcve +[nord-contrib-guide-pr]: https://github.com/nordtheme/.github/blob/main/contributing.md#pull-requests +[nord-contrib-guide-styles]: https://github.com/nordtheme/.github/blob/main/contributing.md#style-guides +[nord-contrib-guide-versioning]: https://github.com/nordtheme/.github/blob/main/contributing.md#versioning +[nord-contrib-guide]: https://github.com/nordtheme/.github/blob/main/contributing.md +[nord-docs-home-config]: https://www.nordtheme.com/docs/ports/tmux/configuration +[nord-docs-home-install]: https://www.nordtheme.com/docs/ports/tmux/installation +[nord-docs-home-install#manual]: https://www.nordtheme.com/docs/ports/tmux/installation#manual +[nord-docs-home-plugins]: https://www.nordtheme.com/docs/ports/tmux/plugin-support +[nord-docs-home]: https://www.nordtheme.com/docs/ports/tmux +[nord-home]: https://www.nordtheme.com/ports/tmux +[nord-home#configurations]: https://www.nordtheme.com/ports/tmux#configurations +[nord-home#intro]: https://www.nordtheme.com/ports/tmux#intro +[nord-home#plugin-support]: https://www.nordtheme.com/ports/tmux#plugin-support +[nord-home#ui-elements]: https://www.nordtheme.com/ports/tmux#ui-elements +[tmux-man-tmux.conf]: http://man.openbsd.org/OpenBSD-current/man1/tmux.1#FILES +[wiki-home_dir]: https://en.wikipedia.org/wiki/Home_directory diff --git a/dot_tmux/plugins/nord-tmux/src/nord-status-content-no-patched-font.conf b/dot_tmux/plugins/nord-tmux/src/nord-status-content-no-patched-font.conf new file mode 100644 index 0000000..62ae584 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/src/nord-status-content-no-patched-font.conf @@ -0,0 +1,20 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +#+----------------+ +#+ Plugin Support + +#+----------------+ +#+--- tmux-prefix-highlight ---+ +set -g @prefix_highlight_copy_mode_attr "fg=black,bg=brightcyan" + +#+--------+ +#+ Status + +#+--------+ +#+--- Bars ---+ +set -g status-left "#[fg=black,bg=blue,bold] #S " +set -g status-right "#{prefix_highlight}#[fg=white,bg=brightblack] ${NORD_TMUX_STATUS_DATE_FORMAT} #[fg=white,bg=brightblack,nobold,noitalics,nounderscore]|#[fg=white,bg=brightblack] ${NORD_TMUX_STATUS_TIME_FORMAT} #[fg=cyan,bg=brightblack,nobold,noitalics,nounderscore] #[fg=black,bg=cyan,bold] #H " + +#+--- Windows ---+ +set -g window-status-format " #[fg=white,bg=brightblack]#I #[fg=white,bg=brightblack]#W #F" +set -g window-status-current-format " #[fg=black,bg=cyan]#I#[fg=black,bg=cyan,nobold,noitalics,nounderscore] #[fg=black,bg=cyan]#W #F" +set -g window-status-separator "" diff --git a/dot_tmux/plugins/nord-tmux/src/nord-status-content.conf b/dot_tmux/plugins/nord-tmux/src/nord-status-content.conf new file mode 100644 index 0000000..11980e1 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/src/nord-status-content.conf @@ -0,0 +1,22 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +#+----------------+ +#+ Plugin Support + +#+----------------+ +#+--- tmux-prefix-highlight ---+ +set -g @prefix_highlight_output_prefix "#[fg=brightcyan]#[bg=black]#[nobold]#[noitalics]#[nounderscore]#[bg=brightcyan]#[fg=black]" +set -g @prefix_highlight_output_suffix "" +set -g @prefix_highlight_copy_mode_attr "fg=brightcyan,bg=black,bold" + +#+--------+ +#+ Status + +#+--------+ +#+--- Bars ---+ +set -g status-left "#[fg=black,bg=blue,bold] #S #[fg=blue,bg=black,nobold,noitalics,nounderscore]" +set -g status-right "#{prefix_highlight}#[fg=brightblack,bg=black,nobold,noitalics,nounderscore]#[fg=white,bg=brightblack] ${NORD_TMUX_STATUS_DATE_FORMAT} #[fg=white,bg=brightblack,nobold,noitalics,nounderscore]#[fg=white,bg=brightblack] ${NORD_TMUX_STATUS_TIME_FORMAT} #[fg=cyan,bg=brightblack,nobold,noitalics,nounderscore]#[fg=black,bg=cyan,bold] #H " + +#+--- Windows ---+ +set -g window-status-format "#[fg=black,bg=brightblack,nobold,noitalics,nounderscore] #[fg=white,bg=brightblack]#I #[fg=white,bg=brightblack,nobold,noitalics,nounderscore] #[fg=white,bg=brightblack]#W #F #[fg=brightblack,bg=black,nobold,noitalics,nounderscore]" +set -g window-status-current-format "#[fg=black,bg=cyan,nobold,noitalics,nounderscore] #[fg=black,bg=cyan]#I #[fg=black,bg=cyan,nobold,noitalics,nounderscore] #[fg=black,bg=cyan]#W #F #[fg=cyan,bg=black,nobold,noitalics,nounderscore]" +set -g window-status-separator "" diff --git a/dot_tmux/plugins/nord-tmux/src/nord.conf b/dot_tmux/plugins/nord-tmux/src/nord.conf new file mode 100644 index 0000000..3dd5eb0 --- /dev/null +++ b/dot_tmux/plugins/nord-tmux/src/nord.conf @@ -0,0 +1,43 @@ +# Copyright (c) 2016-present Sven Greb +# This source code is licensed under the MIT license found in the license file. + +#+----------------+ +#+ Plugin Support + +#+----------------+ +#+--- tmux-prefix-highlight ---+ +set -g @prefix_highlight_fg black +set -g @prefix_highlight_bg brightcyan + +#+---------+ +#+ Options + +#+---------+ +set -g status-interval 1 +set -g status on + +#+--------+ +#+ Status + +#+--------+ +#+--- Layout ---+ +set -g status-justify left + +#+--- Colors ---+ +set -g status-style bg=black,fg=white + +#+-------+ +#+ Panes + +#+-------+ +set -g pane-border-style bg=default,fg=brightblack +set -g pane-active-border-style bg=default,fg=blue +set -g display-panes-colour black +set -g display-panes-active-colour brightblack + +#+------------+ +#+ Clock Mode + +#+------------+ +setw -g clock-mode-colour cyan + +#+----------+ +#+ Messages + +#+---------+ +set -g message-style bg=brightblack,fg=cyan +set -g message-command-style bg=brightblack,fg=cyan diff --git a/dot_tmux/plugins/tmux-copycat/CHANGELOG.md b/dot_tmux/plugins/tmux-copycat/CHANGELOG.md new file mode 100644 index 0000000..635d68a --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/CHANGELOG.md @@ -0,0 +1,88 @@ +# Changelog + +### master + +### v3.0.0, Nov 01, 2017 +- if installed use `gawk` instead of `awk` (@metcalfc) +- add stored search for matching git SHAs (@jbnicolai) +- move documentation from github wiki to `docs/` folder +- support for tmux 2.4+, not compatible with tmux 2.3 and earlier (@thalesmello) + +### v2.1.0, Jan 01, 2015 +- combine send-keys calls to reduce flickering (@toupeira) +- add `file:///` prefix for local file url's (@vellvisher) +- add `git://` type url + +### v2.0.0, Oct 16, 2014 +- add tmux options for default searches +- use `session_id` instead of `session_name` in the copycat file name (solution + provided by @toupeira) +- use `grep -E` and remove eval (@toupeira) + +### v1.1.0, Sep 29, 2014 +- add IP address search +- enhance url search with git and ftp urls + +### v1.0.0, Aug 31, 2014 +- simplify file search stored regex +- match files starting with dot +- improve README - add more relevant related plugins +- do not use `copycat_clear_search` method when in copycat mode. It was causing + mysterious issues for some users. +- update `README.md` - warning about a breaking mapping +- remove rails request stored search `C-r` + +### v0.1.0, Aug 02, 2014 +- remove note about git history issue +- url saved search includes `#` character +- improve stored search handling +- update README and document addding custom stored searches + +### v0.0.7, Jul 31, 2014 +- add customization section to the readme (@soli) +- remove screencast from the project. The video is too bit and plugin download + is slow because of that. The video is moved to the separate `screencast` + branch. +- run test suite on 2 vagrant VMs: ubuntu and centos + +### v0.0.6, Jul 28, 2014 +- update video script +- update readme and invite for code contributions +- update dockerfile with it's purpose +- add test suite `README` file +- add screencast original document to git +- add video directory `README` file +- update readme to reflect github organization change +- add a screencast link to the readme + +### v0.0.5, Jul 24, 2014 +- improve stored file matching search +- fix wrong result highlighting for lines that have \r, \n chars +- another improvement to file matching search: changed regex strategy to be + "inclusive" +- add test suite +- update readme to show how test suite is started + +### v0.0.4, Jul 9, 2014 +- bugfix for incorrect result highlighting +- optimize and improve the function that centers the result vertically on the + screen +- fix OS X awk bug: awk variable content can't start with `=` char +- fix a bug with wrong result highlighting caused by using `printf` +- fix a bug with wrong result highlighting caused by a bug in OSX `grep` +- improve URL matching regex. Matches don't include quotes anymore. + +### v0.0.3, Jun 29, 2014 +- add notifications about the first and last match +- improve "jump correction" handling by fetching the precise window height +- improve result vertical centering & fix a related bug + +### v0.0.2, Jun 26, 2014 +- search results are always at the bottom of the page. If possible center the + result, or provide maximum possible padding. +- refactoring in `copycat_jump.sh` - extract 2 constants to file global variables +- improve file matching regex. `master...origin/master` is not detected as a + string. + +### v0.0.1, Jun 25, 2014 +- first version, plugin working diff --git a/dot_tmux/plugins/tmux-copycat/LICENSE.md b/dot_tmux/plugins/tmux-copycat/LICENSE.md new file mode 100644 index 0000000..40f6ddd --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/LICENSE.md @@ -0,0 +1,19 @@ +Copyright (C) 2014 Bruno Sutic + +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/dot_tmux/plugins/tmux-copycat/README.md b/dot_tmux/plugins/tmux-copycat/README.md new file mode 100644 index 0000000..ad9a921 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/README.md @@ -0,0 +1,146 @@ +# Tmux copycat + +[![Build Status](https://travis-ci.org/tmux-plugins/tmux-copycat.svg?branch=master)](https://travis-ci.org/tmux-plugins/tmux-copycat) + +**NOTE: [tmux 3.1 adds support for native regex searches](https://raw.githubusercontent.com/tmux/tmux/3.1/CHANGES). +This is great news because it means a big part of 'tmux-copycat' is now +available natively! Use this plugin only if you need its other features.** + +This plugin enables: + +- regex searches (native support added in tmux 3.1) +- search result highlighting +- predefined searches + +Predefined searches are plugin killer feature. It speeds the workflow and +reduces mouse usage with Tmux. + +It works even better when paired with +[tmux yank](https://github.com/tmux-plugins/tmux-yank). Tested and working on +Linux, OSX and Cygwin. + +### Screencast + +[![screencast screenshot](/video/screencast_img.png)](https://vimeo.com/101867689) + +#### Search + +- `prefix + /` - regex search (strings work too) + +Example search entries: + +- `foo` - searches for string `foo` +- `[0-9]+` - regex search for numbers + +Grep is used for searching.
+Searches are case insensitive.
+ +#### Predefined searches + +- `prefix + ctrl-f` - simple *f*ile search +- `prefix + ctrl-g` - jumping over *g*it status files (best used after `git status` command) +- `prefix + alt-h` - jumping over SHA-1/SHA-256 hashes (best used after `git log` command) +- `prefix + ctrl-u` - *u*rl search (http, ftp and git urls) +- `prefix + ctrl-d` - number search (mnemonic d, as digit) +- `prefix + alt-i` - *i*p address search + +These start "copycat mode" and jump to first match. + +#### "Copycat mode" bindings + +These are enabled when you search with copycat: + +- `n` - jumps to the next match +- `N` - jumps to the previous match + +To copy a highlighted match: + +- `Enter` - if you're using Tmux `vi` mode +- `ctrl-w` or `alt-w` - if you're using Tmux `emacs` mode + +Copying a highlighted match will take you "out" of copycat mode. Paste with +`prefix + ]` (this is Tmux default paste). + +Copying highlighted matches can be enhanced with +[tmux yank](https://github.com/tmux-plugins/tmux-yank). + +### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended) + +Add plugin to the list of TPM plugins in `.tmux.conf`: + + set -g @plugin 'tmux-plugins/tmux-copycat' + +Hit `prefix + I` to fetch the plugin and source it. You should now be able to +use the plugin. + +Optional (but recommended) install `gawk` via your package manager of choice +for better UTF-8 character support. + +### Manual Installation + +Clone the repo: + + $ git clone https://github.com/tmux-plugins/tmux-copycat ~/clone/path + +Add this line to the bottom of `.tmux.conf`: + + run-shell ~/clone/path/copycat.tmux + +Reload TMUX environment with: `$ tmux source-file ~/.tmux.conf`. You should now +be able to use the plugin. + +Optional (but recommended) install `gawk` via your package manager of choice +for better UTF-8 character support. + +### Installation for Tmux 2.3 and earlier + +Due to the changes in tmux, the latest version of this plugin doesn't support +tmux 2.3 and earlier. It is recommended you upgrade to tmux version 2.4 or +later. If you must continue using older version, please follow +[these steps for installation](docs/installation_for_tmux_2.3.md). + +### Limitations + +This plugin has some known limitations. Please read about it +[here](docs/limitations.md). + +### Docs + +- Most of the behavior of tmux-copycat can be customized via tmux options. + [Check out the full options list](docs/customizations.md). +- To speed up the workflow you can define new bindings in `.tmux.conf` for + searches you use often, more info [here](docs/defining_new_stored_searches.md) + +### Other goodies + +`tmux-copycat` works great with: + +- [tmux-yank](https://github.com/tmux-plugins/tmux-yank) - enables copying + highlighted text to system clipboard +- [tmux-open](https://github.com/tmux-plugins/tmux-open) - a plugin for quickly + opening a highlighted file or a url +- [tmux-continuum](https://github.com/tmux-plugins/tmux-continuum) - automatic + restoring and continuous saving of tmux env + +### Test suite + +This plugin has a pretty extensive integration test suite that runs on +[travis](https://travis-ci.org/tmux-plugins/tmux-copycat). + +When run locally, it depends on `vagrant`. Run it with: + + # within project top directory + $ ./run-tests + +### Contributions and new features + +Bug fixes and contributions are welcome. + +Feel free to suggest new features, via github issues. + +If you have a bigger idea you'd like to work on, please get in touch, also via +github issues. + +### License + +[MIT](LICENSE.md) diff --git a/dot_tmux/plugins/tmux-copycat/Vagrantfile b/dot_tmux/plugins/tmux-copycat/Vagrantfile new file mode 100644 index 0000000..ac74c7f --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/Vagrantfile @@ -0,0 +1,8 @@ +VAGRANTFILE_API_VERSION = '2' + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.define :ubuntu_two_five do |ubuntu| + ubuntu.vm.box = 'hashicorp/precise32' + ubuntu.vm.provision 'shell', path: 'vagrant_ubuntu_provisioning_two_five.sh' + end +end diff --git a/dot_tmux/plugins/tmux-copycat/docs/customizations.md b/dot_tmux/plugins/tmux-copycat/docs/customizations.md new file mode 100644 index 0000000..ea20518 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/docs/customizations.md @@ -0,0 +1,26 @@ +# Customizations + +Most of the behavior of tmux-copycat can be customized via tmux options.
+To set a value, just put `set -g @option 'value'` in your `.tmux.conf` before +loading the tmux-copycat plugin. + +Other options: + +- `@copycat_search` (default `/`) defines the key-binding used (after prefix) to + start an interactive search. +- `@copycat_next` (default `n`) defines the key (without prefix) used to jump to + next search result. +- `@copycat_prev` (default `N`) defines the key (without prefix) used to jump to + previous search result. + +Options for predefined searches: + +- `@copycat_git_special` (default `C-g`) git status search +- `@copycat_file_search` (default `C-f`) file search +- `@copycat_url_search` (default `C-u`) url search +- `@copycat_digit_search` (default `C-d`) digit search +- `@copycat_hash_search` (default `M-h`) SHA-1 hash search +- `@copycat_ip_search` (default `M-i`) IP address search + +Example: to remap default file search to use `C-t` put +`set -g @copycat_file_search 'C-t'` in `.tmux.conf`. diff --git a/dot_tmux/plugins/tmux-copycat/docs/defining_new_stored_searches.md b/dot_tmux/plugins/tmux-copycat/docs/defining_new_stored_searches.md new file mode 100644 index 0000000..7b52e21 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/docs/defining_new_stored_searches.md @@ -0,0 +1,40 @@ +# Defining new stored searches + +To speed up the workflow you can define new bindings in `.tmux.conf` for +searches you use often. + +After adding any of the below snippets, make sure to reload your tmux +configuration: + + # type this in the terminal + $ tmux source-file ~/.tmux.conf + +Dummy examples (just for testing): + +* `prefix + ctrl-t` example string search + + set -g @copycat_search_C-t 'search me' + +* `prefix + alt-t` example regex search + + set -g @copycat_search_M-t 'regex search[[:alnum:]]\*' + +### Useful searches + +* `prefix + ctrl-e` in the Rails log output searches for previous request start + + set -g @copycat_search_C-e '^Processing[[:space:]]by[[:space:]][^[:space:]]*' + +* `prefix + D` searches for numbers at the *beginning* of line.
+ Useful with `$ pgrep -lf process` command to quickly select process PID. + + set -g @copycat_search_D '^[[:digit:]]+' + +* `prefix + G` searches for git commit SHA1.
+ Works for both the short (5 chars) and full (40 chars) versions. + + set -g @copycat_search_G '\b[0-9a-f]{5,40}\b' + + +Have your own custom search? Please share it in +[the discussion](https://github.com/tmux-plugins/tmux-copycat/issues/57). diff --git a/dot_tmux/plugins/tmux-copycat/docs/installation_for_tmux_2.3.md b/dot_tmux/plugins/tmux-copycat/docs/installation_for_tmux_2.3.md new file mode 100644 index 0000000..015f04b --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/docs/installation_for_tmux_2.3.md @@ -0,0 +1,20 @@ +# Installation for Tmux 2.3 and earlier + +The installation steps for Tmux 2.3 are based on +[manual installation](https://github.com/tmux-plugins/tmux-copycat#manual-installation) +steps, with the addition of using `tmux-23` branch. + +Create tmux plugins dir: + + $ mkdir -p ~/.tmux/plugins + +Clone the repo: + + $ git clone -b tmux-23 https://github.com/tmux-plugins/tmux-copycat ~/.tmux/plugins/tmux-copycat + +Add this line to the bottom of `.tmux.conf`: + + run-shell ~/clone/path/copycat.tmux + +Reload TMUX environment with: `$ tmux source-file ~/.tmux.conf`. You should now +be able to use the plugin. diff --git a/dot_tmux/plugins/tmux-copycat/docs/limitations.md b/dot_tmux/plugins/tmux-copycat/docs/limitations.md new file mode 100644 index 0000000..0bfb659 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/docs/limitations.md @@ -0,0 +1,24 @@ +# Limitations + +- This plugin tries hard to consistently enable "marketed" features. It uses some + hacks to go beyond the APIs Tmux provides. Because of this, it might have some + "rough edges" and there's nothing that can be done. + + Examples: non-perfect file and url matching and selection. That said, usage + should be fine in +90% cases. + +- feel free to report search cases you think should work, but are not + (provide examples pls!). I'm open to the idea of adding more saved searches. + +- Tmux `vi` copy mode works faster than `emacs`. If you don't have a preference + yet and to speed up `tmux_copycat`, I recommend putting this in `.tmux.conf` + to set Tmux copy mode to `vi`: + + set -g mode-keys vi + +- remapping `Escape` key in copy mode will break the plugin. If you have this + in your `.tmux.conf`, please consider removing it: + + bind -t vi-copy Escape cancel + + After removing this key binding, don't forget to restart tmux server! diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/HEAD b/dot_tmux/plugins/tmux-copycat/dot_git/HEAD new file mode 100644 index 0000000..cb089cd --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/branches/.keep b/dot_tmux/plugins/tmux-copycat/dot_git/branches/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/config b/dot_tmux/plugins/tmux-copycat/dot_git/config new file mode 100644 index 0000000..70bf919 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[submodule] + active = . +[remote "origin"] + url = https://git::@github.com/tmux-plugins/tmux-copycat + fetch = +refs/heads/master:refs/remotes/origin/master +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/description b/dot_tmux/plugins/tmux-copycat/dot_git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_applypatch-msg.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_applypatch-msg.sample new file mode 100644 index 0000000..a5d7b84 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_commit-msg.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_commit-msg.sample new file mode 100644 index 0000000..b58d118 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_fsmonitor-watchman.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_fsmonitor-watchman.sample new file mode 100644 index 0000000..23e856f --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_post-update.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_post-update.sample new file mode 100644 index 0000000..ec17ec1 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-applypatch.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-applypatch.sample new file mode 100644 index 0000000..4142082 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-commit.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-commit.sample new file mode 100644 index 0000000..e144712 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-merge-commit.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-merge-commit.sample new file mode 100644 index 0000000..399eab1 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-push.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-push.sample new file mode 100644 index 0000000..4ce688d --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-rebase.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-rebase.sample new file mode 100644 index 0000000..6cbef5c --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-receive.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-receive.sample new file mode 100644 index 0000000..a1fd29e --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_prepare-commit-msg.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_prepare-commit-msg.sample new file mode 100644 index 0000000..10fa14c --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_push-to-checkout.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_push-to-checkout.sample new file mode 100644 index 0000000..af5a0c0 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_update.sample b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_update.sample new file mode 100644 index 0000000..c4d426b --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/hooks/executable_update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/index b/dot_tmux/plugins/tmux-copycat/dot_git/index new file mode 100644 index 0000000..b159cbc Binary files /dev/null and b/dot_tmux/plugins/tmux-copycat/dot_git/index differ diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/info/exclude b/dot_tmux/plugins/tmux-copycat/dot_git/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/logs/HEAD b/dot_tmux/plugins/tmux-copycat/dot_git/logs/HEAD new file mode 100644 index 0000000..ec03878 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 d7f7e6c1de0bc0d6915f4beea5be6a8a42045c09 Simon Rieger 1699878732 +0100 clone: from https://github.com/tmux-plugins/tmux-copycat diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/logs/refs/heads/master b/dot_tmux/plugins/tmux-copycat/dot_git/logs/refs/heads/master new file mode 100644 index 0000000..ec03878 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 d7f7e6c1de0bc0d6915f4beea5be6a8a42045c09 Simon Rieger 1699878732 +0100 clone: from https://github.com/tmux-plugins/tmux-copycat diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/logs/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-copycat/dot_git/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..ec03878 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 d7f7e6c1de0bc0d6915f4beea5be6a8a42045c09 Simon Rieger 1699878732 +0100 clone: from https://github.com/tmux-plugins/tmux-copycat diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/objects/info/.keep b/dot_tmux/plugins/tmux-copycat/dot_git/objects/info/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/objects/pack/readonly_pack-e769ce283000b4b24f4f1b37ce35debdb100cd0b.idx b/dot_tmux/plugins/tmux-copycat/dot_git/objects/pack/readonly_pack-e769ce283000b4b24f4f1b37ce35debdb100cd0b.idx new file mode 100644 index 0000000..68000f9 Binary files /dev/null and b/dot_tmux/plugins/tmux-copycat/dot_git/objects/pack/readonly_pack-e769ce283000b4b24f4f1b37ce35debdb100cd0b.idx differ diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/objects/pack/readonly_pack-e769ce283000b4b24f4f1b37ce35debdb100cd0b.pack b/dot_tmux/plugins/tmux-copycat/dot_git/objects/pack/readonly_pack-e769ce283000b4b24f4f1b37ce35debdb100cd0b.pack new file mode 100644 index 0000000..0dbaf9f Binary files /dev/null and b/dot_tmux/plugins/tmux-copycat/dot_git/objects/pack/readonly_pack-e769ce283000b4b24f4f1b37ce35debdb100cd0b.pack differ diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/objects/pack/readonly_pack-e769ce283000b4b24f4f1b37ce35debdb100cd0b.rev b/dot_tmux/plugins/tmux-copycat/dot_git/objects/pack/readonly_pack-e769ce283000b4b24f4f1b37ce35debdb100cd0b.rev new file mode 100644 index 0000000..8a6f399 Binary files /dev/null and b/dot_tmux/plugins/tmux-copycat/dot_git/objects/pack/readonly_pack-e769ce283000b4b24f4f1b37ce35debdb100cd0b.rev differ diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/packed-refs b/dot_tmux/plugins/tmux-copycat/dot_git/packed-refs new file mode 100644 index 0000000..fe4442b --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +d7f7e6c1de0bc0d6915f4beea5be6a8a42045c09 refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/heads/master b/dot_tmux/plugins/tmux-copycat/dot_git/refs/heads/master new file mode 100644 index 0000000..20411c5 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/heads/master @@ -0,0 +1 @@ +d7f7e6c1de0bc0d6915f4beea5be6a8a42045c09 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-copycat/dot_git/refs/remotes/origin/HEAD new file mode 100644 index 0000000..6efe28f --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.1 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.1 new file mode 100644 index 0000000..4c4d6f2 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.1 @@ -0,0 +1 @@ +695404b910484c742eec5c920d393963a0270997 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.2 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.2 new file mode 100644 index 0000000..fdfd690 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.2 @@ -0,0 +1 @@ +5d66a57b6f014663d5618cfaf5d21b590e2b4595 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.3 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.3 new file mode 100644 index 0000000..71e4872 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.3 @@ -0,0 +1 @@ +de224a5b0c82124bd91afbd00411c89374963bf6 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.4 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.4 new file mode 100644 index 0000000..7caf9dc --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.4 @@ -0,0 +1 @@ +6bc93920406c8f4d0ff832f9eee7ea5a95f02068 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.5 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.5 new file mode 100644 index 0000000..d0c8f6b --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.5 @@ -0,0 +1 @@ +e81eaaca057524c95cca2e330392e1b8da4ca979 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.6 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.6 new file mode 100644 index 0000000..197387f --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.6 @@ -0,0 +1 @@ +6d4fd32498119c3129303f3dc15ab9e8f4091a0b diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.7 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.7 new file mode 100644 index 0000000..1108204 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.0.7 @@ -0,0 +1 @@ +b78252363f42fab918abfa3769d1ba9f65a37b6d diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.1.0 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.1.0 new file mode 100644 index 0000000..e72a07d --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v0.1.0 @@ -0,0 +1 @@ +5ab01f3d873b162003318443b70aa8279538c120 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v1.0.0 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v1.0.0 new file mode 100644 index 0000000..b3b3017 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v1.0.0 @@ -0,0 +1 @@ +706fa12453609e9ea7167b683044aafefe9d3989 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v1.1.0 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v1.1.0 new file mode 100644 index 0000000..1d2a7b1 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v1.1.0 @@ -0,0 +1 @@ +ccd660493a61395994ce1ccbf1f233297d56d83b diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v2.0.0 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v2.0.0 new file mode 100644 index 0000000..db99932 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v2.0.0 @@ -0,0 +1 @@ +1c360908ffa090e64d101f9989e885d2aef83644 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v2.1.0 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v2.1.0 new file mode 100644 index 0000000..7ffd339 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v2.1.0 @@ -0,0 +1 @@ +a30c93896bb86faceb64f86846463ec047e4d9f7 diff --git a/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v3.0.0 b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v3.0.0 new file mode 100644 index 0000000..fc1ea36 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_git/refs/tags/v3.0.0 @@ -0,0 +1 @@ +70a6bff389e3ccae6feeaa1bfa2869960dd046b4 diff --git a/dot_tmux/plugins/tmux-copycat/dot_gitattributes b/dot_tmux/plugins/tmux-copycat/dot_gitattributes new file mode 100644 index 0000000..cc060c3 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_gitattributes @@ -0,0 +1,9 @@ +# Force text files to have unix eols, so Windows/Cygwin does not break them +*.* eol=lf + +# These files are unfortunately not recognized as text files so +# explicitly listing them here +Vagrantfile eol=lf +run-tests eol=lf +test/run-tests-within-vm eol=lf +*.png binary diff --git a/dot_tmux/plugins/tmux-copycat/dot_gitignore b/dot_tmux/plugins/tmux-copycat/dot_gitignore new file mode 100644 index 0000000..a977916 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_gitignore @@ -0,0 +1 @@ +.vagrant/ diff --git a/dot_tmux/plugins/tmux-copycat/dot_travis.yml b/dot_tmux/plugins/tmux-copycat/dot_travis.yml new file mode 100644 index 0000000..f1596e8 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/dot_travis.yml @@ -0,0 +1,29 @@ +# generic packages +before_install: + - sudo apt-get update + - sudo apt-get install -y git-core expect gawk + - sudo apt-get install -y python-software-properties software-properties-common + +# install Tmux 2.5 +install: + - VERSION=2.5 + - sudo apt-get -y remove tmux + - sudo apt-get -y install wget tar libevent-dev libncurses-dev make + - wget https://github.com/tmux/tmux/releases/download/${VERSION}/tmux-${VERSION}.tar.gz + - tar xf tmux-${VERSION}.tar.gz + - rm -f tmux-${VERSION}.tar.gz + - cd tmux-${VERSION} + - ./configure + - make + - sudo make install + - cd - + - sudo rm -rf /usr/local/src/tmux-* + - sudo mv tmux-${VERSION} /usr/local/src + +# override PS1 and irb prompt, fetch a git repo used for testing +before_script: + - echo 'export PS1="\$ "' >> ~/.bashrc + - echo 'IRB.conf[:PROMPT_MODE] = :SIMPLE' >> ~/.irbrc + - git clone https://github.com/tmux-plugins/tmux-example-plugin ~/tmux-example-plugin + +script: ./test/run-tests-within-vm diff --git a/dot_tmux/plugins/tmux-copycat/executable_copycat.tmux b/dot_tmux/plugins/tmux-copycat/executable_copycat.tmux new file mode 100644 index 0000000..be59a59 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/executable_copycat.tmux @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source "$CURRENT_DIR/scripts/variables.sh" +source "$CURRENT_DIR/scripts/helpers.sh" +source "$CURRENT_DIR/scripts/stored_search_helpers.sh" + +# this function defines default stored searches +set_default_stored_searches() { + local file_search="$(get_tmux_option "$copycat_file_search_option" "$default_file_search_key")" + local url_search="$(get_tmux_option "$copycat_url_search_option" "$default_url_search_key")" + local digit_search="$(get_tmux_option "$copycat_digit_search_option" "$default_digit_search_key")" + local hash_search="$(get_tmux_option "$copycat_hash_search_option" "$default_hash_search_key")" + local ip_search="$(get_tmux_option "$copycat_ip_search_option" "$default_ip_search_key")" + + if stored_search_not_defined "$url_search"; then + tmux set-option -g "${COPYCAT_VAR_PREFIX}_${url_search}" "(https?://|git@|git://|ssh://|ftp://|file:///)[[:alnum:]?=%/_.:,;~@!#$&()*+-]*" + fi + if stored_search_not_defined "$file_search"; then + tmux set-option -g "${COPYCAT_VAR_PREFIX}_${file_search}" "(^|^\.|[[:space:]]|[[:space:]]\.|[[:space:]]\.\.|^\.\.)[[:alnum:]~_-]*/[][[:alnum:]_.#$%&+=/@-]*" + fi + if stored_search_not_defined "$digit_search"; then + tmux set-option -g "${COPYCAT_VAR_PREFIX}_${digit_search}" "[[:digit:]]+" + fi + if stored_search_not_defined "$hash_search"; then + tmux set-option -g "${COPYCAT_VAR_PREFIX}_${hash_search}" "\b([0-9a-f]{7,40}|[[:alnum:]]{52}|[0-9a-f]{64})\b" + fi + if stored_search_not_defined "$ip_search"; then + tmux set-option -g "${COPYCAT_VAR_PREFIX}_${ip_search}" "[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}" + fi +} + +set_start_bindings() { + set_default_stored_searches + local stored_search_vars="$(stored_search_vars)" + local search_var + local key + local pattern + for search_var in $stored_search_vars; do + key="$(get_stored_search_key "$search_var")" + pattern="$(get_stored_search_pattern "$search_var")" + tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/copycat_mode_start.sh '$pattern'" + done +} + +set_copycat_search_binding() { + local key_bindings + read -r -d '' -a key_bindings <<<"$(get_tmux_option "$copycat_search_option" "$default_copycat_search_key")" + local key + for key in "${key_bindings[@]}"; do + tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/copycat_search.sh" + done +} + +set_copycat_git_special_binding() { + local key_bindings + read -r -d '' -a key_bindings <<<"$(get_tmux_option "$copycat_git_search_option" "$default_git_search_key")" + local key + for key in "${key_bindings[@]}"; do + tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/copycat_git_special.sh #{pane_current_path}" + done +} + +set_copycat_mode_bindings() { + "$CURRENT_DIR/scripts/copycat_mode_bindings.sh" +} + +main() { + set_start_bindings + set_copycat_search_binding + set_copycat_git_special_binding + set_copycat_mode_bindings +} +main diff --git a/dot_tmux/plugins/tmux-copycat/executable_run-tests b/dot_tmux/plugins/tmux-copycat/executable_run-tests new file mode 100644 index 0000000..7d866c7 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/executable_run-tests @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +# For each virtual machine where tests run, this script performs the following: +# - starts VM +# - starts the test suite witin a VM +# - stops the VM after the test suite is done + +# global variable for script exit value +export EXIT_VALUE=0 + +register_failing_specs() { + EXIT_VALUE=1 +} + +run_vagrant() { + local box="$1" + vagrant up "$box" +} + +# Halt vagrant after tests are done running, unless KEEP_RUNNING environment +# variable is set to 'true'. +stop_vagrant() { + local box="$1" + if [ -z "$KEEP_RUNNING" ]; then + vagrant halt "$box" + else + echo + echo "KEEP_RUNNING is set. Vagrant not halted." + fi +} + +run_tests() { + local box="$1" + local test_file="/vagrant/test/run-tests-within-vm" + echo "Running test suite on $box from: $test_file" + echo + vagrant ssh "$box" -c "cd /vagrant; $test_file" +} + +exit_message() { + local exit_val="$1" + echo + if [ $exit_val == 0 ]; then + echo "Success, tests pass!" + else + echo "Tests failed!" 1>&2 + fi +} + +run_tests_on_vm() { + local vm="$1" + run_vagrant "$vm" + run_tests "$vm" + local tests_exit_value="$?" + stop_vagrant "$vm" + if [ $tests_exit_value -gt 0 ]; then + register_failing_specs + fi +} + +main() { + run_tests_on_vm "ubuntu_two_five" + + exit_message "$EXIT_VALUE" + exit "$EXIT_VALUE" +} +main diff --git a/dot_tmux/plugins/tmux-copycat/scripts/executable_check_tmux_version.sh b/dot_tmux/plugins/tmux-copycat/scripts/executable_check_tmux_version.sh new file mode 100644 index 0000000..b0aedec --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/executable_check_tmux_version.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +VERSION="$1" +UNSUPPORTED_MSG="$2" + +get_tmux_option() { + local option=$1 + local default_value=$2 + local option_value=$(tmux show-option -gqv "$option") + if [ -z "$option_value" ]; then + echo "$default_value" + else + echo "$option_value" + fi +} + +# Ensures a message is displayed for 5 seconds in tmux prompt. +# Does not override the 'display-time' tmux option. +display_message() { + local message="$1" + + # display_duration defaults to 5 seconds, if not passed as an argument + if [ "$#" -eq 2 ]; then + local display_duration="$2" + else + local display_duration="5000" + fi + + # saves user-set 'display-time' option + local saved_display_time=$(get_tmux_option "display-time" "750") + + # sets message display time to 5 seconds + tmux set-option -gq display-time "$display_duration" + + # displays message + tmux display-message "$message" + + # restores original 'display-time' value + tmux set-option -gq display-time "$saved_display_time" +} + +# this is used to get "clean" integer version number. Examples: +# `tmux 1.9` => `19` +# `1.9a` => `19` +get_digits_from_string() { + local string="$1" + local only_digits="$(echo "$string" | tr -dC '[:digit:]')" + echo "$only_digits" +} + +tmux_version_int() { + local tmux_version_string=$(tmux -V) + echo "$(get_digits_from_string "$tmux_version_string")" +} + +unsupported_version_message() { + if [ -n "$UNSUPPORTED_MSG" ]; then + echo "$UNSUPPORTED_MSG" + else + echo "Error, Tmux version unsupported! Please install Tmux version $VERSION or greater!" + fi +} + +exit_if_unsupported_version() { + local current_version="$1" + local supported_version="$2" + if [ "$current_version" -lt "$supported_version" ]; then + display_message "$(unsupported_version_message)" + exit 1 + fi +} + +main() { + local supported_version_int="$(get_digits_from_string "$VERSION")" + local current_version_int="$(tmux_version_int)" + exit_if_unsupported_version "$current_version_int" "$supported_version_int" +} +main diff --git a/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_generate_results.sh b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_generate_results.sh new file mode 100644 index 0000000..c5f94dc --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_generate_results.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source "$CURRENT_DIR/helpers.sh" + +search_pattern="$1" + +capture_pane() { + local file=$1 + # copying 9M lines back will hopefully fetch the whole scrollback + tmux capture-pane -S -9000000 -p > "$file" +} + +# doing 2 things in 1 step so that we don't write to disk too much +reverse_and_create_copycat_file() { + local file=$1 + local copycat_file=$2 + local grep_pattern=$3 + (tac 2>/dev/null || tail -r) < "$file" | grep -oniE "$grep_pattern" > "$copycat_file" +} + +delete_old_files() { + local scrollback_filename="$(get_scrollback_filename)" + local copycat_filename="$(get_copycat_filename)" + rm -f "$scrollback_filename" "$copycat_filename" +} + +generate_copycat_file() { + local grep_pattern="$1" + local scrollback_filename="$(get_scrollback_filename)" + local copycat_filename="$(get_copycat_filename)" + mkdir -p "$(_get_tmp_dir)" + chmod 0700 "$(_get_tmp_dir)" + capture_pane "$scrollback_filename" + reverse_and_create_copycat_file "$scrollback_filename" "$copycat_filename" "$grep_pattern" +} + +if_no_results_exit_with_message() { + local copycat_filename="$(get_copycat_filename)" + # check for empty filename + if ! [ -s "$copycat_filename" ]; then + display_message "No results!" + exit 0 + fi +} + +main() { + local grep_pattern="$1" + if not_in_copycat_mode; then + delete_old_files + generate_copycat_file "$grep_pattern" + if_no_results_exit_with_message + set_copycat_mode + copycat_increase_counter + fi +} +main "$search_pattern" diff --git a/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_git_special.sh b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_git_special.sh new file mode 100644 index 0000000..439296b --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_git_special.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +PANE_CURRENT_PATH="$1" + +source "$CURRENT_DIR/helpers.sh" + +git_status_files() { + git -C "$PANE_CURRENT_PATH" status -s +} + +formatted_git_status() { + local raw_gist_status="$(git_status_files)" + echo "$raw_gist_status" | cut -c 4- +} + +exit_if_no_results() { + local results="$1" + if [ -z "$results" ]; then + display_message "No results!" + exit 0 + fi +} + +concatenate_files() { + local git_status_files="$(formatted_git_status)" + exit_if_no_results "$git_status_files" + + local result="" + # Undefined until later within a while loop. + local file_separator + while read -r line; do + result="${result}${file_separator}${line}" + file_separator="|" + done <<< "$git_status_files" + echo "$result" +} + +# Creates one, big regex out of git status files. +# Example: +# `git status` shows files `foo.txt` and `bar.txt` +# output regex will be: +# `(foo.txt|bar.txt) +git_status_files_regex() { + local concatenated_files="$(concatenate_files)" + local regex_result="(${concatenated_files})" + echo "$regex_result" +} + +main() { + local search_regex="$(git_status_files_regex)" + # starts copycat mode + $CURRENT_DIR/copycat_mode_start.sh "$search_regex" +} +main diff --git a/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_jump.sh b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_jump.sh new file mode 100644 index 0000000..fd2362c --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_jump.sh @@ -0,0 +1,289 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source "$CURRENT_DIR/helpers.sh" + +MAXIMUM_PADDING="25" # maximum padding below the result when it can't be centered + +# jump to 'next' or 'prev' match +# global var for this file +NEXT_PREV="$1" + +# 'vi' or 'emacs', this variable used as a global file constant +TMUX_COPY_MODE="$(tmux_copy_mode)" + +_file_number_of_lines() { + local file="$1" + echo "$(wc -l $file | $AWK_CMD '{print $1}')" +} + +_get_result_line() { + local file="$1" + local number="$2" + echo "$(head -"$number" "$file" | tail -1)" +} + +_string_starts_with_digit() { + local string="$1" + echo "$string" | + \grep -q '^[[:digit:]]\+:' +} + +_get_line_number() { + local string="$1" + local copycat_file="$2" # args 2 & 3 used to handle bug in OSX grep + local position_number="$3" + if _string_starts_with_digit "$string"; then + # we have a number! + local grep_line_number="$(echo "$string" | cut -f1 -d:)" + # grep line number index starts from 1, tmux line number index starts from 0 + local tmux_line_number="$((grep_line_number - 1))" + else + # no number in the results line This is a bug in OSX grep. + # Fetching a number from a previous line. + local previous_line_num="$((position_number - 1))" + local result_line="$(_get_result_line "$copycat_file" "$previous_line_num")" + # recursively invoke this same function + tmux_line_number="$(_get_line_number "$result_line" "$copycat_file" "$previous_line_num")" + fi + echo "$tmux_line_number" +} + +_get_match() { + local string="$1" + local full_match + if _string_starts_with_digit "$string"; then + full_match="$(echo "$string" | cut -f2- -d:)" + else + # This scenario handles OS X grep bug "no number in the results line". + # When there's no number at the beginning of the line, we're taking the + # whole line as a match. This handles the result line like this: + # `http://www.example.com` (the `http` would otherwise get cut off) + full_match="$string" + fi + echo -n "$full_match" +} + +_escape_backslash() { + local string="$1" + echo "$(echo "$string" | sed 's/\\/\\\\/g')" +} + +_get_match_line_position() { + local file="$1" + local line_number="$2" + local match="$3" + local adjusted_line_num=$((line_number + 1)) + local result_line=$(tail -"$adjusted_line_num" "$file" | head -1) + + # OS X awk cannot have `=` as the first char in the variable (bug in awk). + # If exists, changing the `=` character with `.` to avoid error. + local platform="$(uname)" + if [ "$platform" == "Darwin" ]; then + result_line="$(echo "$result_line" | sed 's/^=/./')" + match="$(echo "$match" | sed 's/^=/./')" + fi + + # awk treats \r, \n, \t etc as single characters and that messes up match + # highlighting. For that reason, we're escaping backslashes so above chars + # are treated literally. + result_line="$(_escape_backslash "$result_line")" + match="$(_escape_backslash "$match")" + + local index=$($AWK_CMD -v a="$result_line" -v b="$match" 'BEGIN{print index(a,b)}') + local zero_index=$((index - 1)) + echo "$zero_index" +} + +_copycat_jump() { + local line_number="$1" + local match_line_position="$2" + local match="$3" + local scrollback_line_number="$4" + _copycat_enter_mode + _copycat_exit_select_mode + _copycat_jump_to_line "$line_number" "$scrollback_line_number" + _copycat_position_to_match_start "$match_line_position" + _copycat_select "$match" +} + +_copycat_enter_mode() { + tmux copy-mode +} + +# clears selection from a previous match +_copycat_exit_select_mode() { + tmux send-keys -X clear-selection +} + +# "manually" go up in the scrollback for a number of lines +_copycat_manually_go_up() { + local line_number="$1" + tmux send-keys -X -N "$line_number" cursor-up + tmux send-keys -X start-of-line +} + +_copycat_create_padding_below_result() { + local number_of_lines="$1" + local maximum_padding="$2" + local padding + + # Padding should not be greater than half pane height + # (it wouldn't be centered then). + if [ "$number_of_lines" -gt "$maximum_padding" ]; then + padding="$maximum_padding" + else + padding="$number_of_lines" + fi + + # cannot create padding, exit function + if [ "$padding" -eq "0" ]; then + return + fi + + tmux send-keys -X -N "$padding" cursor-down + tmux send-keys -X -N "$padding" cursor-up +} + +# performs a jump to go to line +_copycat_go_to_line_with_jump() { + local line_number="$1" + # first jumps to the "bottom" in copy mode so that jumps are consistent + tmux send-keys -X history-bottom + tmux send-keys -X start-of-line + tmux send-keys -X goto-line $line_number +} + +# maximum line number that can be reached via tmux 'jump' +_get_max_jump() { + local scrollback_line_number="$1" + local window_height="$2" + local max_jump=$((scrollback_line_number - $window_height)) + # max jump can't be lower than zero + if [ "$max_jump" -lt "0" ]; then + max_jump="0" + fi + echo "$max_jump" +} + +_copycat_jump_to_line() { + local line_number="$1" + local scrollback_line_number="$2" + local window_height="$(tmux display-message -p '#{pane_height}')" + local correct_line_number + + local max_jump=$(_get_max_jump "$scrollback_line_number" "$window_height") + local correction="0" + + if [ "$line_number" -gt "$max_jump" ]; then + # We need to 'reach' a line number that is not accessible via 'jump'. + # Introducing 'correction' + correct_line_number="$max_jump" + correction=$((line_number - $correct_line_number)) + else + # we can reach the desired line number via 'jump'. Correction not needed. + correct_line_number="$line_number" + fi + + _copycat_go_to_line_with_jump "$correct_line_number" + + if [ "$correction" -gt "0" ]; then + _copycat_manually_go_up "$correction" + fi + + # If no corrections (meaning result is not at the top of scrollback) + # we can then 'center' the result within a pane. + if [ "$correction" -eq "0" ]; then + local half_window_height="$((window_height / 2))" + # creating as much padding as possible, up to half pane height + _copycat_create_padding_below_result "$line_number" "$half_window_height" + fi +} + +_copycat_position_to_match_start() { + local match_line_position="$1" + [ "$match_line_position" -eq "0" ] && return 0 + + tmux send-keys -X -N "$match_line_position" cursor-right +} + +_copycat_select() { + local match="$1" + local length="${#match}" + tmux send-keys -X begin-selection + tmux send-keys -X -N "$length" cursor-right + if [ "$TMUX_COPY_MODE" == "vi" ]; then + tmux send-keys -X cursor-left # selection correction for 1 char + fi +} + +# all functions above are "private", called from `do_next_jump` function + +get_new_position_number() { + local copycat_file="$1" + local current_position="$2" + local new_position + + # doing a forward/up jump + if [ "$NEXT_PREV" == "next" ]; then + local number_of_results=$(wc -l "$copycat_file" | $AWK_CMD '{ print $1 }') + if [ "$current_position" -eq "$number_of_results" ]; then + # position can't go beyond the last result + new_position="$current_position" + else + new_position="$((current_position + 1))" + fi + + # doing a backward/down jump + elif [ "$NEXT_PREV" == "prev" ]; then + if [ "$current_position" -eq "1" ]; then + # position can't go below 1 + new_position="1" + else + new_position="$((current_position - 1))" + fi + fi + echo "$new_position" +} + +do_next_jump() { + local position_number="$1" + local copycat_file="$2" + local scrollback_file="$3" + + local scrollback_line_number=$(_file_number_of_lines "$scrollback_file") + local result_line="$(_get_result_line "$copycat_file" "$position_number")" + local line_number=$(_get_line_number "$result_line" "$copycat_file" "$position_number") + local match=$(_get_match "$result_line") + local match_line_position=$(_get_match_line_position "$scrollback_file" "$line_number" "$match") + _copycat_jump "$line_number" "$match_line_position" "$match" "$scrollback_line_number" +} + +notify_about_first_last_match() { + local current_position="$1" + local next_position="$2" + local message_duration="1500" + + # if position didn't change, we are either on a 'first' or 'last' match + if [ "$current_position" -eq "$next_position" ]; then + if [ "$NEXT_PREV" == "next" ]; then + display_message "Last match!" "$message_duration" + elif [ "$NEXT_PREV" == "prev" ]; then + display_message "First match!" "$message_duration" + fi + fi +} + +main() { + if in_copycat_mode; then + local copycat_file="$(get_copycat_filename)" + local scrollback_file="$(get_scrollback_filename)" + local current_position="$(get_copycat_position)" + local next_position="$(get_new_position_number "$copycat_file" "$current_position")" + do_next_jump "$next_position" "$copycat_file" "$scrollback_file" + notify_about_first_last_match "$current_position" "$next_position" + set_copycat_position "$next_position" + fi +} +main diff --git a/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_mode_bindings.sh b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_mode_bindings.sh new file mode 100644 index 0000000..20d5725 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_mode_bindings.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source "$CURRENT_DIR/helpers.sh" +AWK_CMD='awk' +if command_exists gawk; then + AWK_CMD='gawk' +fi + +# Extends a keyboard key. +# Benefits: tmux won't report errors and everything will work fine even if the +# script is deleted. +extend_key() { + local key="$1" + local script="$2" + local copy_mode + copy_mode=$(tmux_copy_mode_string) + + # 1. The default command for 'key' is sent to tmux. This ensures the + # default key action is done. + # 2. Script is executed. + # 3. `true` command ensures an exit status 0 is returned. This ensures + # a user never gets an error msg - even if the script file from step 2 + # is deleted. + tmux list-keys -T "$copy_mode" | + "$AWK_CMD" -v mode="$copy_mode" -v key="$key" -v script="$script" ' + /copycat/ { next } + $3 == mode && $4 == key { + $1="" + $2="" + $3="" + $4="" + cmd=$0 + gsub(/["\\]/, "\\\\&", cmd) + system("tmux bind-key -T " mode " " key " run-shell \"tmux " cmd "; " script "; true\"") + }' +} + +copycat_cancel_bindings() { + # keys that quit copy mode are enhanced to quit copycat mode as well. + local cancel_mode_bindings=$(copycat_quit_copy_mode_keys) + local key + for key in $cancel_mode_bindings; do + extend_key "$key" "$CURRENT_DIR/copycat_mode_quit.sh" + done +} + +copycat_mode_bindings() { + extend_key "$(copycat_next_key)" "$CURRENT_DIR/copycat_jump.sh 'next'" + extend_key "$(copycat_prev_key)" "$CURRENT_DIR/copycat_jump.sh 'prev'" +} + +main() { + copycat_mode_bindings + copycat_cancel_bindings +} +main diff --git a/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_mode_quit.sh b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_mode_quit.sh new file mode 100644 index 0000000..b0b2a2b --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_mode_quit.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source "$CURRENT_DIR/helpers.sh" + +main() { + if in_copycat_mode; then + reset_copycat_position + unset_copycat_mode + copycat_decrease_counter + fi +} +main diff --git a/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_mode_start.sh b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_mode_start.sh new file mode 100644 index 0000000..b14f596 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_mode_start.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +SUPPORTED_VERSION="1.9" + +PATTERN="$1" + +supported_tmux_version_ok() { + $CURRENT_DIR/check_tmux_version.sh "$SUPPORTED_VERSION" +} + +main() { + local pattern="$1" + if supported_tmux_version_ok; then + $CURRENT_DIR/copycat_generate_results.sh "$pattern" # will `exit 0` if no results + $CURRENT_DIR/copycat_jump.sh 'next' + fi +} +main "$PATTERN" diff --git a/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_search.sh b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_search.sh new file mode 100644 index 0000000..b77f1f2 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/executable_copycat_search.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +main() { + tmux command-prompt -p "copycat search:" "run-shell \"$CURRENT_DIR/copycat_mode_start.sh '%1'\"" +} +main diff --git a/dot_tmux/plugins/tmux-copycat/scripts/helpers.sh b/dot_tmux/plugins/tmux-copycat/scripts/helpers.sh new file mode 100644 index 0000000..63fbd2d --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/helpers.sh @@ -0,0 +1,192 @@ +# config options + +default_next_key="n" +tmux_option_next="@copycat_next" + +default_prev_key="N" +tmux_option_prev="@copycat_prev" + +# keeps track of number of panes in copycat mode +tmux_option_counter="@copycat_counter" + +# === awk vs gawk === +command_exists() { + command -v "$@" > /dev/null 2>&1 +} +AWK_CMD='awk' +if command_exists gawk; then + AWK_CMD='gawk' +fi + +# === general helpers === + +get_tmux_option() { + local option=$1 + local default_value=$2 + local option_value=$(tmux show-option -gqv "$option") + if [ -z "$option_value" ]; then + echo "$default_value" + else + echo "$option_value" + fi +} + +set_tmux_option() { + local option=$1 + local value=$2 + tmux set-option -gq "$option" "$value" +} + +tmux_copy_mode() { + tmux show-option -gwv mode-keys +} + +tmux_copy_mode_string() { + if [ $(tmux_copy_mode) == 'vi' ]; then + echo copy-mode-vi + else + echo copy-mode + fi +} + +# === copycat mode specific helpers === + +set_copycat_mode() { + set_tmux_option "$(_copycat_mode_var)" "true" +} + +unset_copycat_mode() { + set_tmux_option "$(_copycat_mode_var)" "false" +} + +in_copycat_mode() { + local copycat_mode=$(get_tmux_option "$(_copycat_mode_var)" "false") + [ "$copycat_mode" == "true" ] +} + +not_in_copycat_mode() { + if in_copycat_mode; then + return 1 + else + return 0 + fi +} + +# === copycat mode position === + +get_copycat_position() { + local copycat_position_variable=$(_copycat_position_var) + echo $(get_tmux_option "$copycat_position_variable" "0") +} + +set_copycat_position() { + local position="$1" + local copycat_position_variable=$(_copycat_position_var) + set_tmux_option "$copycat_position_variable" "$position" +} + +reset_copycat_position() { + set_copycat_position "0" +} + +# === scrollback and results position === + +get_scrollback_filename() { + echo "$(_get_tmp_dir)/scrollback-$(_pane_unique_id)" +} + +get_copycat_filename() { + echo "$(_get_tmp_dir)/results-$(_pane_unique_id)" +} + +# Ensures a message is displayed for 5 seconds in tmux prompt. +# Does not override the 'display-time' tmux option. +display_message() { + local message="$1" + + # display_duration defaults to 5 seconds, if not passed as an argument + if [ "$#" -eq 2 ]; then + local display_duration="$2" + else + local display_duration="5000" + fi + + # saves user-set 'display-time' option + local saved_display_time=$(get_tmux_option "display-time" "750") + + # sets message display time to 5 seconds + tmux set-option -gq display-time "$display_duration" + + # displays message + tmux display-message "$message" + + # restores original 'display-time' value + tmux set-option -gq display-time "$saved_display_time" +} + +# === counter functions === + +copycat_increase_counter() { + local count=$(get_tmux_option "$tmux_option_counter" "0") + local new_count="$((count + 1))" + set_tmux_option "$tmux_option_counter" "$new_count" +} + +copycat_decrease_counter() { + local count="$(get_tmux_option "$tmux_option_counter" "0")" + if [ "$count" -gt "0" ]; then + # decreasing the counter only if it won't go below 0 + local new_count="$((count - 1))" + set_tmux_option "$tmux_option_counter" "$new_count" + fi +} + +copycat_counter_zero() { + local count="$(get_tmux_option "$tmux_option_counter" "0")" + [ "$count" -eq "0" ] +} + +# === key binding functions === + +copycat_next_key() { + echo "$(get_tmux_option "$tmux_option_next" "$default_next_key")" +} + +copycat_prev_key() { + echo "$(get_tmux_option "$tmux_option_prev" "$default_prev_key")" +} + +# function expected output: 'C-c Enter q' +copycat_quit_copy_mode_keys() { + local commands_that_quit_copy_mode="cancel" + local copy_mode="$(tmux_copy_mode_string)" + tmux list-keys -T "$copy_mode" | + \grep "$commands_that_quit_copy_mode" | + $AWK_CMD '{ print $4 }' | + sort -u | + sed 's/C-j//g' | + xargs echo +} + +# === 'private' functions === + +_copycat_mode_var() { + local pane_id="$(_pane_unique_id)" + echo "@copycat_mode_$pane_id" +} + +_copycat_position_var() { + local pane_id="$(_pane_unique_id)" + echo "@copycat_position_$pane_id" +} + +_get_tmp_dir() { + echo "${TMPDIR:-/tmp}/tmux-$EUID-copycat" +} + +# returns a string unique to current pane +# sed removes `$` sign because `session_id` contains is +_pane_unique_id() { + tmux display-message -p "#{session_id}-#{window_index}-#{pane_index}" | + sed 's/\$//' +} diff --git a/dot_tmux/plugins/tmux-copycat/scripts/stored_search_helpers.sh b/dot_tmux/plugins/tmux-copycat/scripts/stored_search_helpers.sh new file mode 100644 index 0000000..6d192fe --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/stored_search_helpers.sh @@ -0,0 +1,23 @@ +stored_search_not_defined() { + local key="$1" + local search_value="$(tmux show-option -gqv "${COPYCAT_VAR_PREFIX}_${key}")" + [ -z $search_value ] +} + +stored_search_vars() { + tmux show-options -g | + \grep -i "^${COPYCAT_VAR_PREFIX}_" | + cut -d ' ' -f1 | # cut just variable names + xargs # splat var names in one line +} + +# get the search key from the variable name +get_stored_search_key() { + local search_var="$1" + echo "$(echo "$search_var" | sed "s/^${COPYCAT_VAR_PREFIX}_//")" +} + +get_stored_search_pattern() { + local search_var="$1" + echo "$(get_tmux_option "$search_var" "")" +} diff --git a/dot_tmux/plugins/tmux-copycat/scripts/variables.sh b/dot_tmux/plugins/tmux-copycat/scripts/variables.sh new file mode 100644 index 0000000..82f8f7a --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/scripts/variables.sh @@ -0,0 +1,26 @@ +# stored search variable prefix +COPYCAT_VAR_PREFIX="@copycat_search" + +# basic search +default_copycat_search_key="/" +copycat_search_option="@copycat_search" + +# git special search +default_git_search_key="C-g" +copycat_git_search_option="@copycat_git_special" + +# regular searches +default_file_search_key="C-f" +copycat_file_search_option="@copycat_file_search" + +default_url_search_key="C-u" +copycat_url_search_option="@copycat_url_search" + +default_digit_search_key="C-d" +copycat_digit_search_option="@copycat_digit_search" + +default_hash_search_key="M-h" +copycat_hash_search_option="@copycat_hash_search" + +default_ip_search_key="M-i" +copycat_ip_search_option="@copycat_ip_search" diff --git a/dot_tmux/plugins/tmux-copycat/test/README.md b/dot_tmux/plugins/tmux-copycat/test/README.md new file mode 100644 index 0000000..7cefd3d --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/README.md @@ -0,0 +1,15 @@ +## Tmux copycat test suite + +This directory contains test files for tmux copycat. + +Tests are written with the [expect tool](http://expect.sourceforge.net/). + +### Dependencies + +- [Vagrant](https://www.vagrantup.com/) + +### Running the test suite + +From the `tmux copycat` project top directory run: + + $ ./run-tests diff --git a/dot_tmux/plugins/tmux-copycat/test/executable_run-tests-within-vm b/dot_tmux/plugins/tmux-copycat/test/executable_run-tests-within-vm new file mode 100644 index 0000000..8d57e6a --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/executable_run-tests-within-vm @@ -0,0 +1,48 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# running test suite is successful by default +tests_exit_value=0 + +test_files() { + ls -1 $CURRENT_DIR | # test files are in current dir + \grep -i '^test' | # test file names start with 'test' + xargs # file names in one line +} + +set_global_exit_val_to_false() { + tests_exit_value=1 +} + +run_test() { + local test_file="$1" + local tmux_copy_mode="$2" + + # running test + echo "Test: $test_file (copy-mode $tmux_copy_mode)" + + # by setting the EDITOR var tmux chooses vi or emacs copy mode + EDITOR="$tmux_copy_mode" $CURRENT_DIR/$test_file + + # handling exit value + local exit_value="$?" + if [ "$exit_value" == 0 ]; then + echo "Success" + else + echo "Test failed!" + set_global_exit_val_to_false + fi + echo +} + +main() { + local test_file + local test_dir_path="./" + for test_file in $(test_files); do + run_test "$test_file" "vi" + run_test "$test_file" "emacs" + done + exit "$tests_exit_value" +} +main diff --git a/dot_tmux/plugins/tmux-copycat/test/executable_test_digit_search.exp b/dot_tmux/plugins/tmux-copycat/test/executable_test_digit_search.exp new file mode 100644 index 0000000..d28db0b --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/executable_test_digit_search.exp @@ -0,0 +1,131 @@ +#!/usr/bin/env expect + +source "./test/helpers/setup.exp" + +# searches at the top of the pane +#-------------------------------- +display_text "123" +tmux_ctrl_d +assert_highlighted "123" "top of the pane" + +# middle of pane searches +#------------------------ +new_tmux_pane +create_output +clear_screen +display_text "234" +tmux_ctrl_d +assert_highlighted "234" "middle of the pane, beginning of the line" + +display_text "some 345" +tmux_ctrl_d +assert_highlighted "345" "middle of the pane, not beginning of the line" + +create_output +send "456" +sync_tmux +tmux_ctrl_d +assert_highlighted "456" "middle of the pane, pane bottom" + +# match selection when line contains escaped chars +#------------------------------------------------- +new_tmux_pane +display_text "filename=test.csv\r\nContent-Type: 567\r\n" +tmux_ctrl_d +assert_highlighted "567" "match selection when line contains escaped chars" + +# result navigation +#------------------ +new_tmux_pane +display_text "678" +display_text "789" +display_text "890" +tmux_ctrl_d +# 890 +next_match +# 890 +next_match +# 789 +next_match +# 789 +next_match +# 678 +previous_match +# 789 +assert_highlighted "789" "result navigation at the top of the pane" + +create_output +display_text "012" +display_text "123" +tmux_ctrl_d +# 123 +next_match +# 123 +next_match +# 012 +previous_match +# 123 +assert_highlighted "123" "result navigation, middle of the pane" + +# 2 matches on the same line +#--------------------------- +new_tmux_pane +display_text "234 345" +tmux_ctrl_d +assert_highlighted "234" "2 matches on the same line, first match" + +display_text "456 567" +tmux_ctrl_d +next_match +assert_highlighted "567" "2 matches on the same line, second match" + +# no match, first and last match +#------------------------------- +new_tmux_pane +tmux_ctrl_d +assert_on_screen "No results!" "No results is displayed when no results" + +display_text "678" +tmux_ctrl_d +next_match +next_match +assert_on_screen "Last match!" "'Last match' is displayed when last match" +# exit copycat mode +send "" + +new_tmux_pane +display_text "789" +tmux_ctrl_d +next_match +previous_match +previous_match +assert_on_screen "First match!" "'First match' is displayed when first match" +# exit copycat mode +send "" + +# irb console searches +#--------------------- +new_tmux_pane +enter_irb +irb_display_text "890" +tmux_ctrl_d +irb_assert_highlighted "890" "irb console, beggining of line" +exit_irb + +enter_irb +irb_display_text "901" +tmux_ctrl_d +irb_assert_highlighted "901" "irb console, not beggining of line" +exit_irb + +enter_irb +irb_generate_output +send "puts 012" +sync_tmux +tmux_ctrl_d +irb_assert_highlighted "012" "irb console, pane bottom, not beggining of line" +exit_irb + +# quit +#----- +teardown_and_exit diff --git a/dot_tmux/plugins/tmux-copycat/test/executable_test_file_search.exp b/dot_tmux/plugins/tmux-copycat/test/executable_test_file_search.exp new file mode 100644 index 0000000..a96bdef --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/executable_test_file_search.exp @@ -0,0 +1,146 @@ +#!/usr/bin/env expect + +source "./test/helpers/setup.exp" + +# searches at the top of the pane +#-------------------------------- +display_text "/top/of_the/pane/file.txt" +sleep 0.5 +tmux_ctrl_f +assert_highlighted "/top/of_the/pane/file.txt" "top of the pane absolute path" + +new_tmux_pane +display_text "another/top/of_the/pane/file.txt" +tmux_ctrl_f +assert_highlighted "another/top/of_the/pane/file.txt" "top of the pane relative path" + +# middle of pane searches +#------------------------ +new_tmux_pane +create_output +clear_screen +display_text "/this/is/some/file.txt" +tmux_ctrl_f +assert_highlighted "/this/is/some/file.txt" "middle of the pane, absolute path, beginning of the line" + +display_text "random /this/is/some/file.txt" +tmux_ctrl_f +assert_highlighted " /this/is/some/file.txt" "middle of the pane, absolute path, not beginning of the line" + +display_text "another/file.txt" +tmux_ctrl_f +assert_highlighted "another/file.txt" "middle of the pane, relative path, beginning of the line" + +display_text "some text another/file.txt" +tmux_ctrl_f +assert_highlighted " another/file.txt" "middle of the pane, relative path, not beginning of the line" + +create_output +sleep 0.2 +send " some/file.xyz " +sleep 0.2 +tmux_ctrl_f +assert_highlighted " some/file.xyz" "middle of the pane relative path, pane bottom" + +# match selection when line contains escaped chars +#------------------------------------------------- +new_tmux_pane +display_text "filename=test.csv\r\nContent-Type: text/csv\r\n" +tmux_ctrl_f +assert_highlighted " text/csv" "match selection when line contains escaped chars" + +# result navigation +#------------------ +new_tmux_pane +display_text "/file/1.txt" +display_text "/file/2.txt" +display_text "/file/3.txt" +tmux_ctrl_f +# /file/3.txt +next_match +# /file/3.txt +next_match +# /file/2.txt +next_match +# /file/2.txt +next_match +# /file/1.txt +previous_match +# /file/2.txt +assert_highlighted " /file/2.txt" "result navigation at the top of the pane" + +create_output +display_text "/file/1.txt" +display_text "/file/2.txt" +tmux_ctrl_f +# /file/2.txt +next_match +# /file/2.txt +next_match +# /file/1.txt +previous_match +# /file/2.txt +assert_highlighted " /file/2.txt" "result navigation, middle of the pane" + +# 2 matches on the same line +#--------------------------- +new_tmux_pane +display_text "/file/1.txt another/file/2.txt" +tmux_ctrl_f +assert_highlighted "/file/1.txt" "2 matches on the same line, first match" + +display_text "/file/1.txt another/file/2.txt" +tmux_ctrl_f +next_match +assert_highlighted " another/file/2.txt" "2 matches on the same line, second match" + +# no match, first and last match +#------------------------------- +new_tmux_pane +tmux_ctrl_f +assert_on_screen "No results!" "No results is displayed when no results" + +display_text "last/match/file.txt" +tmux_ctrl_f +next_match +next_match +assert_on_screen "Last match!" "'Last match' is displayed when last match" +# exit copycat mode +send "" + +new_tmux_pane +display_text "first/match/file.txt" +tmux_ctrl_f +next_match +previous_match +previous_match +assert_on_screen "First match!" "'First match' is displayed when first match" +# exit copycat mode +send "" + +# irb console searches +#--------------------- +new_tmux_pane +enter_irb +irb_display_text "file/within/irb.rb" +tmux_ctrl_f +irb_assert_highlighted "file/within/irb.rb" "irb console relative path, beggining of line" +exit_irb + +enter_irb +irb_display_text "some text file/within/irb.rb" +tmux_ctrl_f +irb_assert_highlighted " file/within/irb.rb" "irb console relative path, not beggining of line" +exit_irb + +enter_irb +irb_generate_output +send "puts /absolute/file/irb.rb" +sleep 5 +tmux_ctrl_f +irb_assert_highlighted " /absolute/file/irb.rb" "irb console absolute path, pane bottom, not beggining of line" +exit_irb + +# quit +#----- +teardown_and_exit diff --git a/dot_tmux/plugins/tmux-copycat/test/executable_test_free_search.exp b/dot_tmux/plugins/tmux-copycat/test/executable_test_free_search.exp new file mode 100644 index 0000000..06f4703 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/executable_test_free_search.exp @@ -0,0 +1,163 @@ +#!/usr/bin/env expect + +source "./test/helpers/setup.exp" + +# searches at the top of the pane +#-------------------------------- +new_tmux_pane +display_text "something search me1" +search "search me1" +assert_highlighted "search me1" "top of the pane, literal search" + +new_tmux_pane +display_text "something search me2" +search "search me\[\[:alnum:]]" +assert_highlighted "search me2" "top of the pane, search with \[\[:alnum:]]" + +new_tmux_pane +display_text "something search me3" +search "searc. me\[\[:digit:]]" +assert_highlighted "search me3" "top of the pane, search with dot and \[\[:digit:]]" + +new_tmux_pane +display_text "something search me4" +search "sear\[^\[:space:]]* me.+$" +assert_highlighted "search me4" "top of the pane, search with matching group, dot-plus and end of line $" + +# middle of pane searches +#------------------------ +new_tmux_pane +create_output +clear_screen +display_text "something search me1" +search "search me1" +assert_highlighted "search me1" "middle of the pane, literal search" + +display_text "something search me2" +search "search me\[\[:alnum:]]" +assert_highlighted "search me2" "middle of the pane, search with \[\[:alnum:]]" + +display_text "something search me3" +search "searc. me\[\[:digit:]]" +assert_highlighted "search me3" "middle of the pane, search with dot and \[\[:digit:]]" + +display_text "something search me4" +search "sear\[^\[:space:]]* me.+$" +assert_highlighted "search me4" "middle of the pane, search with matching group, dot-plus and end of line $" + +# bottom of the buffer searches +#------------------------------ +new_tmux_pane +create_output +sleep 0.2 +send "something search me1" +sleep 0.2 +search "search me1" +assert_highlighted "search me1" "bottom of the pane, literal search" + +sleep 0.2 +send "something search me2" +sleep 0.2 +search "search me\[\[:alnum:]]" +assert_highlighted "search me2" "bottom of the pane, search with \[\[:alnum:]]" + +sleep 0.2 +send "something search me3" +sleep 0.2 +search "searc. me\[\[:digit:]]" +assert_highlighted "search me3" "bottom of the pane, search with dot and \[\[:digit:]]" + +sleep 0.2 +send "something search me4" +sleep 0.2 +search "sear\[^\[:space:]]* me.+$" +assert_highlighted "search me4" "bottom of the pane, search with matching group, dot-plus and end of line $" + +# match selection when line contains escaped chars +#------------------------------------------------- +new_tmux_pane +display_text "filename=test.csv\r\nContent-Type: text/csv\r\n" +search "text/csv" +assert_highlighted "text/csv" "match selection when line contains escaped chars" + +# result navigation +#------------------ +new_tmux_pane +display_text "match no1" +display_text "match no2" +display_text "match no3" +search "match\[\[:space:]]no\[\[:digit:]]" +# match no3 +next_match +# match no3 +next_match +# match no2 +next_match +# match no2 +next_match +# match no1 +previous_match +# match no2 +assert_highlighted "match no2" "result navigation at the top of the pane" + +create_output +display_text "match no1" +display_text "match no2" +search "match\[\[:space:]]no\[\[:digit:]]" +# match no2 +next_match +# match no2 +next_match +# match no1 +previous_match +# match no2 +assert_highlighted "match no2" "result navigation, middle of the pane" + +# 2 matches on the same line +#--------------------------- +new_tmux_pane +display_text "match1 match2" +search "match\[\[:digit:]]" +assert_highlighted "match1" "2 matches on the same line, first match" + +display_text "match1 match2" +search "match\[\[:digit:]]" +next_match +assert_highlighted "match2" "2 matches on the same line, second match" + +# no match, first and last match +#------------------------------- +new_tmux_pane +search "something\[\[:digit:]]" +assert_on_screen "No results!" "No results is displayed when no results" + +new_tmux_pane +display_text "something2" +sleep 5.0 +search "something\[\[:digit:]]" +next_match +next_match +assert_on_screen "Last match!" "'Last match' is displayed when last match" +# exit copycat mode +send "" + +new_tmux_pane +display_text "random3" +search "random\[\[:digit:]]" +previous_match +assert_on_screen "First match!" "'First match' is displayed when first match" +# exit copycat mode +send "" + +# irb console searches +#--------------------- +new_tmux_pane +enter_irb +irb_display_text "within irb1" +search "within\[\[:space:]]irb\[\[:digit:]]" +irb_assert_highlighted "within irb1" "irb console" +exit_irb + +# quit +#----- +teardown_and_exit diff --git a/dot_tmux/plugins/tmux-copycat/test/executable_test_git_hash_search.exp b/dot_tmux/plugins/tmux-copycat/test/executable_test_git_hash_search.exp new file mode 100644 index 0000000..5b7f726 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/executable_test_git_hash_search.exp @@ -0,0 +1,22 @@ +#!/usr/bin/env expect + +source "./test/helpers/setup.exp" + +enter_test_git_repo + +# Match regular SHA-1 hashes +#--------------------------- +git_log_reverse +tmux_alt_h +assert_highlighted "935929c4c7265666e41e727f97a87d1af00a8b40" "match regular SHA-1 hashes" + +#Match shortened SHA-1 hashes +#---------------------------- +git_log_reverse_short +tmux_alt_h +assert_highlighted "935929c" "match shortened SHA-1 hashes" + +# quit +#----- +remove_test_git_repo +teardown_and_exit diff --git a/dot_tmux/plugins/tmux-copycat/test/executable_test_git_status_search.exp b/dot_tmux/plugins/tmux-copycat/test/executable_test_git_status_search.exp new file mode 100644 index 0000000..9fd2b6a --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/executable_test_git_status_search.exp @@ -0,0 +1,103 @@ +#!/usr/bin/env expect + +source "./test/helpers/setup.exp" + +enter_test_git_repo + +# single file tests +#------------------ +change_file "README.md" +git_status +tmux_ctrl_g +assert_highlighted "README.md" "change commited file" +clean_git_repo + +change_file "new_file.txt" +git_status +tmux_ctrl_g +assert_highlighted "new_file.txt" "change new file" +clean_git_repo + +change_file "another_file.txt" +send "some_command another_file.txt" +sleep 0.1 +tmux_ctrl_g +assert_highlighted "another_file.txt" "search works for files just written on the command line" +clean_git_repo + +# multile files changed +#---------------------- +change_file "README.md" +change_file "some_new_file.txt" +git_status +tmux_ctrl_g +assert_highlighted "some_new_file.txt" "multiple files, first file" +git_status +tmux_ctrl_g +next_match +assert_highlighted "README.md" "multiple files, second file" +clean_git_repo + +# navigation tests +#----------------- +change_file "README.md" +change_file "random_file1.txt" +change_file "random_file2.txt" + +git_status +tmux_ctrl_g +next_match +next_match +assert_highlighted "README.md" "navigation, last file" + +git_status +tmux_ctrl_g +next_match +next_match +next_match +previous_match +previous_match +previous_match +assert_highlighted "random_file2.txt" "navigation, first file" + +clean_git_repo + +# files with unusual names +#------------------------- +change_file "'file with spaces.txt'" +git_status +tmux_ctrl_g +assert_highlighted "file with spaces.txt" "filenames with spaces" +clean_git_repo + +# no match, first and last match +#------------------------------- +new_tmux_pane +enter_test_git_repo +tmux_ctrl_g +assert_on_screen "No results!" "No results is displayed when no results" +clean_git_repo + +new_tmux_pane +enter_test_git_repo +change_file "README.md" +git_status +tmux_ctrl_g +next_match +next_match +assert_on_screen "Last match!" "'Last match' is displayed when last match" +clean_git_repo + +new_tmux_pane +enter_test_git_repo +change_file "README.md" +git_status +tmux_ctrl_g +previous_match +assert_on_screen "First match!" "'First match' is displayed when first match" +clean_git_repo + +# quit +#----- +remove_test_git_repo +teardown_and_exit diff --git a/dot_tmux/plugins/tmux-copycat/test/executable_test_url_search.exp b/dot_tmux/plugins/tmux-copycat/test/executable_test_url_search.exp new file mode 100644 index 0000000..18809cf --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/executable_test_url_search.exp @@ -0,0 +1,190 @@ +#!/usr/bin/env expect + +source "./test/helpers/setup.exp" + +# searches at the top of the pane +#-------------------------------- +display_text "http://example1.com" +tmux_ctrl_u +assert_highlighted "http://example1.com" "top of the pane, http" + +new_tmux_pane +display_text "https://example1.com" +tmux_ctrl_u +assert_highlighted "https://example1.com" "top of the pane, https" + +# middle of pane searches +#------------------------ +new_tmux_pane +create_output +clear_screen +display_text "http://example2.com" +tmux_ctrl_u +assert_highlighted "http://example2.com" "middle of the pane, http, beginning of the line" + +display_text "random http://example3.com" +tmux_ctrl_u +assert_highlighted "http://example3.com" "middle of the pane, http, not beginning of the line" + +display_text "https://example4.com" +tmux_ctrl_u +assert_highlighted "https://example4.com" "middle of the pane, https, beginning of the line" + +display_text "some text https://example5.com" +tmux_ctrl_u +assert_highlighted "https://example5.com" "middle of the pane, https, not beginning of the line" + +create_output +sleep 0.2 +send " http://example6.com " +sleep 0.2 +tmux_ctrl_u +assert_highlighted "http://example6.com" "middle of the pane, http, pane bottom" + +# other url scheme searches +#-------------------------- +new_tmux_pane +create_output +clear_screen +display_text "git@github.com:rails/rails.git" +tmux_ctrl_u +assert_highlighted "git@github.com:rails/rails.git" "middle of the pane, git url" + +display_text "git://github.com/rails/rails.git" +tmux_ctrl_u +assert_highlighted "git://github.com/rails/rails.git" "middle of the pane, another git url" + +display_text "ftp://ftp.foo.bar/baz/lorem/IPSUM/file.txt" +tmux_ctrl_u +assert_highlighted "ftp://ftp.foo.bar/baz/lorem/IPSUM/file.txt" "middle of the pane, ftp url" + +display_text "file:///foo/bar/file.txt" +tmux_ctrl_u +assert_highlighted "file:///foo/bar/file.txt" "middle of the pane, file url" + +# urls with parameters +#--------------------- +new_tmux_pane +display_text "http://example61.com?some=params" +tmux_ctrl_u +assert_highlighted "http://example61.com?some=params" "http, simple params" + +# long links break tests, that's why the below one is shortened +new_tmux_pane +display_text "'https://github.com/H/h/b/g.rb'" +tmux_ctrl_u +assert_highlighted "https://github.com/H/h/b/g.rb" "github link" + +# match selection when line contains escaped chars +#------------------------------------------------- +new_tmux_pane +display_text "filename=test.csv\r\nContent-Type: http://example7.com\r\n" +tmux_ctrl_u +assert_highlighted "http://example7.com" "match selection when line contains escaped chars" + +# result navigation +#------------------ +new_tmux_pane +display_text "http://example81.com" +display_text "http://example82.com" +display_text "http://example83.com" +tmux_ctrl_u +# http://example83.com +next_match +# http://example83.com +next_match +# http://example82.com +next_match +# http://example82.com +next_match +# http://example81.com +previous_match +# http://example82.com +assert_highlighted "http://example82.com" "result navigation at the top of the pane" + +create_output +display_text "http://example91.com" +display_text "http://example92.com" +tmux_ctrl_u +# http://example92.com +next_match +# http://example92.com +next_match +# http://example91.com +previous_match +# http://example92.com +assert_highlighted "http://example92.com" "result navigation, middle of the pane" + +# 2 matches on the same line +#--------------------------- +new_tmux_pane +display_text "http://example101.com http://example102.com" +tmux_ctrl_u +assert_highlighted "http://example101.com" "2 matches on the same line, first match" + +display_text "http://example111.com http://example112.com" +tmux_ctrl_u +next_match +assert_highlighted "http://example112.com" "2 matches on the same line, second match" + +# works ok even with unicode characters in the line (requires gawk to be installed) +#-------------------------------------------------- +new_tmux_pane +display_text "Ξ ~CM_CONF_DIR → curl http://www.google.com" +tmux_ctrl_u +assert_highlighted "http://www.google.com" "match on the line with unicode characters" + +display_text "↑127 ~CM_CONF_DIR → echo http://www.google.com" +tmux_ctrl_u +assert_highlighted "http://www.google.com" "another match on the line with unicode characters" + +# no match, first and last match +#------------------------------- +new_tmux_pane +tmux_ctrl_u +assert_on_screen "No results!" "No results is displayed when no results" + +display_text "http://example12.com" +tmux_ctrl_u +next_match +next_match +assert_on_screen "Last match!" "'Last match' is displayed when last match" +# exit copycat mode +send "" + +new_tmux_pane +display_text "http://example13.com" +tmux_ctrl_u +next_match +previous_match +previous_match +assert_on_screen "First match!" "'First match' is displayed when first match" +# exit copycat mode +send "" + +# irb console searches +#--------------------- +new_tmux_pane +enter_irb +irb_display_text "http://example14.com" +tmux_ctrl_u +irb_assert_highlighted "http://example14.com" "irb console, beginning of line" +exit_irb + +enter_irb +irb_display_text "some text http://example15.com" +tmux_ctrl_u +irb_assert_highlighted "http://example15.com" "irb console, not beginning of line" +exit_irb + +enter_irb +irb_generate_output +send "puts http://example16.com" +sleep 5 +tmux_ctrl_u +irb_assert_highlighted "http://example16.com" "irb console, pane bottom, not beginning of line" +exit_irb + +# quit +#----- +teardown_and_exit diff --git a/dot_tmux/plugins/tmux-copycat/test/executable_test_user_defined_search.exp b/dot_tmux/plugins/tmux-copycat/test/executable_test_user_defined_search.exp new file mode 100644 index 0000000..2fccc3e --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/executable_test_user_defined_search.exp @@ -0,0 +1,137 @@ +#!/usr/bin/env expect + +source "./test/helpers/setup_with_custom_searches.exp" + +# searches at the top of the pane +#-------------------------------- +display_text "some text random string123 more text" +tmux_ctrl_t +assert_highlighted "random string123" "top of the pane, first string" + +new_tmux_pane +display_text "some text random string123456 more text" +tmux_ctrl_t +assert_highlighted "random string123456" "top of the pane, second string" + +# middle of pane searches +#------------------------ +new_tmux_pane +create_output +clear_screen +display_text "some text random string123 more text" +tmux_ctrl_t +assert_highlighted "random string123" "middle of the pane, first string" + +display_text "some text random string123456 more text" +tmux_ctrl_t +assert_highlighted "random string123456" "middle of the pane, second string" + +create_output +sleep 0.2 +send " beginning random string001 text" +sleep 0.2 +tmux_ctrl_t +assert_highlighted "random string001" "middle of the pane, pane bottom" + +# match selection when line contains escaped chars +#------------------------------------------------- +new_tmux_pane +display_text "filename=test.csv\r\nContent-Type: random string456\r\n" +tmux_ctrl_t +assert_highlighted "random string456" "match selection when line contains escaped chars" + +# result navigation +#------------------ +new_tmux_pane +display_text "random string1" +display_text "random string2" +display_text "random string3" +tmux_ctrl_t +# random string3 +next_match +# random string3 +next_match +# random string2 +next_match +# random string2 +next_match +# random string1 +previous_match +# random string2 +assert_highlighted "random string2" "result navigation at the top of the pane" + +create_output +display_text "random string01" +display_text "random string02" +tmux_ctrl_t +# random string02 +next_match +# random string02 +next_match +# random string01 +previous_match +# random string02 +assert_highlighted "random string02" "result navigation, middle of the pane" + +# 2 matches on the same line +#--------------------------- +new_tmux_pane +display_text "foo random string11 bar random string12 foobar" +tmux_ctrl_t +assert_highlighted "random string11" "2 matches on the same line, first match" + +display_text "foo random string11 bar random string12 foobar" +tmux_ctrl_t +next_match +assert_highlighted "random string12" "2 matches on the same line, second match" + +# no match, first and last match +#------------------------------- +new_tmux_pane +tmux_ctrl_t +assert_on_screen "No results!" "No results is displayed when no results" + +display_text "foo random string21" +tmux_ctrl_t +next_match +next_match +assert_on_screen "Last match!" "'Last match' is displayed when last match" +# exit copycat mode +send "" + +new_tmux_pane +display_text "foo random string22" +tmux_ctrl_t +next_match +previous_match +previous_match +assert_on_screen "First match!" "'First match' is displayed when first match" +# exit copycat mode +send "" + +# irb console searches +#--------------------- +new_tmux_pane +enter_irb +irb_display_text "foo random string31 bar" +tmux_ctrl_t +irb_assert_highlighted "random string31" "irb console, beginning of line" +exit_irb + +enter_irb +irb_display_text "foo random string32 bar" +tmux_ctrl_t +irb_assert_highlighted "random string32" "irb console, not beginning of line" +exit_irb + +enter_irb +irb_generate_output +send "puts random string33" +sleep 5 +tmux_ctrl_t +irb_assert_highlighted "random string33" "irb console, pane bottom, not beginning of line" +exit_irb + +# quit +#----- +teardown_and_exit diff --git a/dot_tmux/plugins/tmux-copycat/test/helpers/executable_setup_tmux_conf.sh b/dot_tmux/plugins/tmux-copycat/test/helpers/executable_setup_tmux_conf.sh new file mode 100644 index 0000000..71149e8 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/helpers/executable_setup_tmux_conf.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# Tests helper script for setting up `.tmux.conf` within the VM. +# To be used by sourcing from within individual test scripts. +BASE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" + +setup_tmux_conf() { + # Copy mode (vi or emacs) is automatically determined from EDITOR + # environment variable set in test runner file `test/run-tests-within-vm`. + echo "bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel" > ~/.tmux.conf + echo "bind-key -T copy-mode y send-keys -X copy-selection-and-cancel" >> ~/.tmux.conf + echo "run-shell '$BASE_DIR/copycat.tmux'" >> ~/.tmux.conf +} +setup_tmux_conf diff --git a/dot_tmux/plugins/tmux-copycat/test/helpers/executable_setup_tmux_conf_with_custom_searches.sh b/dot_tmux/plugins/tmux-copycat/test/helpers/executable_setup_tmux_conf_with_custom_searches.sh new file mode 100644 index 0000000..89cf457 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/helpers/executable_setup_tmux_conf_with_custom_searches.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +# Tests helper script for setting up `.tmux.conf` within the VM. +# To be used by sourcing from within individual test scripts. + +BASE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" + +setup_tmux_conf() { + # Copy mode (vi or emacs) is automatically determined from EDITOR + # environment variable set in test runner file `test/run-tests-within-vm`. + echo "bind-key -T copy-mode-vi y send-keys -X copy-selection-and-cancel" > ~/.tmux.conf + echo "bind-key -T copy-mode y send-keys -X copy-selection-and-cancel" >> ~/.tmux.conf + echo "set -g @copycat_search_C-t 'random string[[:digit:]]+'" >> ~/.tmux.conf + echo "run-shell '$BASE_DIR/copycat.tmux'" >> ~/.tmux.conf +} +setup_tmux_conf diff --git a/dot_tmux/plugins/tmux-copycat/test/helpers/executable_test.exp b/dot_tmux/plugins/tmux-copycat/test/helpers/executable_test.exp new file mode 100644 index 0000000..8289bf7 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/helpers/executable_test.exp @@ -0,0 +1,4 @@ +#!/usr/bin/env expect + +spawn bash +send "./test/helpers/setup_tmux_conf.sh\r" diff --git a/dot_tmux/plugins/tmux-copycat/test/helpers/expect_copycat_assertions.exp b/dot_tmux/plugins/tmux-copycat/test/helpers/expect_copycat_assertions.exp new file mode 100644 index 0000000..57650cf --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/helpers/expect_copycat_assertions.exp @@ -0,0 +1,67 @@ +# tmux copycat assertion helpers + +# Asserts text that is crrently highlighted (in copy mode). +proc assert_highlighted {text message} { + set checker [ _generate_checker ] + # Asserted text first has to be 'yanked' and displayed before `expect`. + _display_highlighted_with_checker_text "$checker" + expect { + "$checker$text" { puts " Success: $message" } + timeout { puts " Fail: $message"; exit_status_false } + } +} + +proc irb_assert_highlighted {text message} { + set checker [ _generate_checker ] + _irb_display_highlighted_with_checker_text "$checker" + expect { + "$checker$text" { puts " Success: $message" } + timeout { puts " Fail: $message"; exit_status_false } + } +} + +proc assert_on_screen {text message} { + expect { + "$text" { puts " Success: $message" } + timeout { puts " Fail: $message"; exit_status_false } + } +} + +# private functions + +proc _generate_checker {} { + set random [ expr { rand()*10000 } ] + set checker "Checker $random:" + return $checker +} + +proc _display_highlighted_with_checker_text {checker} { + _copy_mode_copy + send "" + sleep 0.1 + send "echo $checker" + sleep 0.1 + _tmux_paste + send "\r" +} + +proc _irb_display_highlighted_with_checker_text {checker} { + _copy_mode_copy + send "\r" + sleep 0.1 + send "puts '$checker" + sleep 0.1 + _tmux_paste + send "'" + send "\r" +} + +proc _copy_mode_copy {} { + send "y" + sleep 0.2 +} + +proc _tmux_paste {} { + send "]" + sleep 0.1 +} diff --git a/dot_tmux/plugins/tmux-copycat/test/helpers/expect_copycat_helpers.exp b/dot_tmux/plugins/tmux-copycat/test/helpers/expect_copycat_helpers.exp new file mode 100644 index 0000000..2e8f484 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/helpers/expect_copycat_helpers.exp @@ -0,0 +1,53 @@ +# a set of tmux specific helpers + +proc tmux_ctrl_f {} { + send "" + sleep 0.7 +} + +proc tmux_ctrl_d {} { + send "" + sleep 0.7 +} + +proc tmux_ctrl_u {} { + send "" + sleep 0.7 +} + +proc tmux_ctrl_r {} { + send "" + sleep 0.7 +} + +proc tmux_ctrl_g {} { + send "" + sleep 0.7 +} + +proc tmux_alt_h {} { + send "h" + sleep 0.7 +} + +proc tmux_ctrl_t {} { + send "" + sleep 0.7 +} + +proc search {text} { + send "/" + sleep 0.5 + send "$text\r" + sleep 0.7 +} + +proc next_match {} { + send "n" + sleep 0.7 +} + +proc previous_match {} { + send "N" + sleep 0.7 +} diff --git a/dot_tmux/plugins/tmux-copycat/test/helpers/expect_helpers.exp b/dot_tmux/plugins/tmux-copycat/test/helpers/expect_helpers.exp new file mode 100644 index 0000000..6cbc003 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/helpers/expect_helpers.exp @@ -0,0 +1,149 @@ +# a set of expect helpers + +# basic setup for each script +proc expect_setup {} { + # disables script output + log_user 0 + # standard timeout + set timeout 5 +} + +proc exit_status_false {} { + global exit_status + set exit_status 1 +} + +proc sync_tmux {} { + sleep 1.5 +} + +proc sync_irb {} { + sleep 5.0 +} + +proc teardown_and_exit {} { + global exit_status + _kill_tmux_server + exit $exit_status +} + +proc create_output {} { + # `yes` command just outputs `yes` + send "yes\r" + sleep 0.1 + # stop `yes` command + send "" + sync_tmux +} + +proc clear_screen {} { + send " " + sync_tmux +} + +proc display_text {text} { + send "echo $text\r" + sync_tmux +} + +proc new_tmux_pane {} { + sleep 0.3 + send "c" + sleep 1.0 +} + +proc enter_irb {} { + send "irb\r" + sync_irb +} + +proc exit_irb {} { + send "\r" + sync_irb + send "exit\r" + sync_tmux +} + +proc irb_display_text {text} { + send "puts '$text'\r" + sync_irb +} + +# Generates random output just to fill the screen. +proc irb_generate_output {} { + send "puts 'output\n' * 200\r" + sync_irb +} + +proc enter_test_git_repo {} { + sync_tmux + send "cd ~/tmux-example-plugin\r" + sync_tmux + send "git checkout --quiet tags/v0.0.1\r" + sync_tmux +} + +proc git_status {} { + sync_tmux + send "git status --short\r" + sync_tmux +} + +proc git_log_reverse_short {} { + sync_tmux + send "git --no-pager log --reverse --oneline -1\r" + sync_tmux +} + +proc git_log_reverse {} { + sync_tmux + send "git --no-pager log --reverse -1\r" + sync_tmux +} + +proc git_checkout {} { + sync_tmux + send "git checkout -- .\r" + sync_tmux +} + +proc git_clean_fd {} { + sync_tmux + send "git clean -f -d\r" + sync_tmux +} + +proc clean_git_repo {} { + git_checkout + git_clean_fd +} + +proc change_file {file} { + sync_tmux + send "echo 'change' > $file\r" + sync_tmux +} + +proc create_new_file_in_repo {} { + sync_tmux + send "echo 'text' >> new_file.txt\r" + sync_tmux +} + +proc remove_test_git_repo {} { + sync_tmux + send "cd ~\r" + sync_tmux + send "rm -rf ~/tmux_example_plugin/\r" + sync_tmux +} + +# private functions + +proc _kill_tmux_server {} { + send "" + sync_tmux + send "tmux kill-server\r" + sync_tmux +} + diff --git a/dot_tmux/plugins/tmux-copycat/test/helpers/literal_run_tmux.exp b/dot_tmux/plugins/tmux-copycat/test/helpers/literal_run_tmux.exp new file mode 100644 index 0000000..bffaa3f --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/helpers/literal_run_tmux.exp @@ -0,0 +1,5 @@ +# steps for starting tmux within an expect script + +spawn tmux +# delay with sleep to compensate for tmux starting time +sleep 1 diff --git a/dot_tmux/plugins/tmux-copycat/test/helpers/setup.exp b/dot_tmux/plugins/tmux-copycat/test/helpers/setup.exp new file mode 100644 index 0000000..783f389 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/helpers/setup.exp @@ -0,0 +1,14 @@ +# sourcing helper functions +source "./test/helpers/expect_helpers.exp" +source "./test/helpers/expect_copycat_helpers.exp" +source "./test/helpers/expect_copycat_assertions.exp" + +# .tmux.conf +exec "./test/helpers/setup_tmux_conf.sh" +expect_setup + +# exit status global var is successful by default +set exit_status 0 + +# run tmux (doesn't work when within a proc) +source "./test/helpers/run_tmux.exp" diff --git a/dot_tmux/plugins/tmux-copycat/test/helpers/setup_with_custom_searches.exp b/dot_tmux/plugins/tmux-copycat/test/helpers/setup_with_custom_searches.exp new file mode 100644 index 0000000..1146f89 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/test/helpers/setup_with_custom_searches.exp @@ -0,0 +1,14 @@ +# sourcing helper functions +source "./test/helpers/expect_helpers.exp" +source "./test/helpers/expect_copycat_helpers.exp" +source "./test/helpers/expect_copycat_assertions.exp" + +# .tmux.conf +exec "./test/helpers/setup_tmux_conf_with_custom_searches.sh" +expect_setup + +# exit status global var is successful by default +set exit_status 0 + +# run tmux (doesn't work when within a proc) +source "./test/helpers/run_tmux.exp" diff --git a/dot_tmux/plugins/tmux-copycat/vagrant_ubuntu_provisioning_two_five.sh b/dot_tmux/plugins/tmux-copycat/vagrant_ubuntu_provisioning_two_five.sh new file mode 100644 index 0000000..3f27bd8 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/vagrant_ubuntu_provisioning_two_five.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# override PS1 prompt +echo 'export PS1="\$ "' >> /home/vagrant/.bashrc +# simplify irb prompt +echo 'IRB.conf[:PROMPT_MODE] = :SIMPLE' >> /home/vagrant/.irbrc +chown -R vagrant:vagrant /home/vagrant/.irbrc + +sudo apt-get update +sudo apt-get install -y make +sudo apt-get install -y git-core expect vim gawk +sudo apt-get install -y python-software-properties software-properties-common + +# install Tmux 2.5 +VERSION=2.5 +sudo apt-get -y remove tmux +sudo apt-get -y install wget tar libevent-dev libncurses-dev +wget https://github.com/tmux/tmux/releases/download/${VERSION}/tmux-${VERSION}.tar.gz +tar xf tmux-${VERSION}.tar.gz +rm -f tmux-${VERSION}.tar.gz +cd tmux-${VERSION} +./configure +make +sudo make install +cd - +sudo rm -rf /usr/local/src/tmux-* +sudo mv tmux-${VERSION} /usr/local/src + +# clone a repo used later for tests +git clone https://github.com/tmux-plugins/tmux-example-plugin /home/vagrant/tmux-example-plugin +chown -R vagrant:vagrant /home/vagrant/tmux-example-plugin + +sudo locale-gen "en_US.UTF-8" +sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 diff --git a/dot_tmux/plugins/tmux-copycat/video/README.md b/dot_tmux/plugins/tmux-copycat/video/README.md new file mode 100644 index 0000000..c66e7d1 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/video/README.md @@ -0,0 +1,7 @@ +## Tmux copycat screencast + +This directory contains docs used for creating +[tmux copycat screencast](https://vimeo.com/101867689). + +- `script.md` - this file contains a script and a voiceover used to produce the + screencast diff --git a/dot_tmux/plugins/tmux-copycat/video/screencast_img.png b/dot_tmux/plugins/tmux-copycat/video/screencast_img.png new file mode 100644 index 0000000..3bbedd2 Binary files /dev/null and b/dot_tmux/plugins/tmux-copycat/video/screencast_img.png differ diff --git a/dot_tmux/plugins/tmux-copycat/video/script.md b/dot_tmux/plugins/tmux-copycat/video/script.md new file mode 100644 index 0000000..395c2d9 --- /dev/null +++ b/dot_tmux/plugins/tmux-copycat/video/script.md @@ -0,0 +1,233 @@ +# Video script + +1 - Intro: about selecting in copy mode +======================================= +Actions +------- +- select a file with the mouse +- paste it in the command line + +Script +------ +Let's demo Tmux copycat plugin. + +Tmux copycat enables you to perform regex searches and also to store those +searches for fast execution later. + +This is something not possible with vanilla tmux and it can greatly reduce mouse +usage and speed up your workflow. + +Let's jump to an example. We have tmux here, and I'll create some typical output +in the terminal. + +Now, I want to grab that last file you see listed. +The easiest and fastest way to do it is unfortunately with a mouse. +I'll select the file. +Copy and paste it. + +That, however feels wrong. I shouldn't be using mouse while in the command +line. There has to be a way to automate and speed things up with tmux. + +2 - Selecting files `prefix + ` +==================================== +Actions +------- +- select a file with `prefix + ` +- copy the file with `Enter` +- paste with `prefix + ]` + +Script +------ +Now, let's show a proper way to do it. + +Tmux copycat has a predefined file search, so pressing prefix plus control-f +jumps straight to the last file. + +Notice how the match is already selected. + +I'll copy it with enter, +and paste it with tmux default paste "bajnding": prefix plus right angle bracket. + +3 - Jumping over searches with `n` and `N` +========================================== +Actions +------- +- select a file with `prefix + ` +- another selection with `n` +- another selection with `n` +- previous match with `N` + +Script +------ +You can also easily jump over all the matches in the pane scrollback. + +I'll enter file search with prefix control-f again. + +I can move to the next match with n. + +And to the previous match with uppercase n. + +This jumping over the results is possible for any tmux copycat search. + +4 - Selecting git status files `prefix + ` +=============================================== +Actions +------- +- invoke `git status` +- the output should have: one word file name, and filename with spaces +- jump over all the results with `prefix + `, `n` and `N` +- make sure it's shown that simple files can't be selected +- invoke `prefix + ` +- go up and down to show all the files can be selected + +Script +------ +File search can be really useful for selecting `git status` files. I'll invoke +`git status` to get the output. + +But as you can see, file search has it's limitations. +In the example on the screen, file search didn't select `files.txt` and +`file with spaces.txt`. It just skiped those and selected the next file. + +Why? Well, file search does not detect simple file names. A string has to have a +forward slash in it to be detected as a file. + +To solve this, there is a git special "bajnding": prefix + control g. I'll +invoke it. + +I can now smoothly jump over all the git status files, including files with +spaces and single word files. + +5 - Selecting numbers `prefix + ` +====================================== +Actions +------- +- create commit +- create pull request +- start assigning the pull request to me +- fetch a pull request number +- assign a pull request to me + +Script +------ +To show another example I'll create a somewhat realistic scenario. +I'll git add a file, make a commit and push it to a remote repo. + +Next, I'll use a git alias for a program called `hub` to open a pull request +from the command line. + + +Good, here's the pull request url. + +Now, I need to assign that pull request with the program `ghi`. For that I need +a pull request number. +This is another situation where I'd just use the mouse to select that number. + +But since this is copycat demo, let's use prefix plus control d. + +It searches for digits or numbers. +Copy, paste and done without reaching for the mouse. + +6 - Selecting URLs `prefix + ` +=================================== +Actions +------- +- select last, pull request url with `prefix + C-u` +- press n, n, then N, N +- yank it with `y` + +Script +------ +How about checking that pull request on github now? I need to grab a url to do that. + +You might've guessed it: there's a stored search for url's. Invoke it with +prefix plus C-u and the url is selected. + +7 - Plain old search with `prefix + /` +===================================== +Actions +------- +- clear screen +- enter: echo 'search me123' +- then: echo 'search me2345' +- enter search command `prefix + /` +- search for a regex `search me[[:digit:]]\\+` +- scroll accross the results +- search for a regex `search me\\d\\+` +- scroll accress the results + +Script +------ +Now, I want to show you how to perform a free search using regex. +In fact plain regex search is the base for all other so called "saved searches" +shown in the video so far. + +I'll write a couple lines in the terminal to get some output. + + +Let's say we need to match 'search me' string and all the digits that come +after it. That can't be done using the tmux vanilla search, because it can do only +literal searches. + +I'll invoke copycat regex search by pressing `prefix` + slash. + +I get a prompt at the bottom of the screen where I can enter the search term or a regex. +I'll type 'search me', then a posix matching group for digits. + +Digit can be repeated one or more times and repeating is specified by the +trailing plus. +Note, plus has to be escaped to have special meaning. +In copycat prompt, all escapes are done twice, so there are two backslashes. + +I'll execute a search and as you can see, we're matching the desired string with +variable number of digits at the end. Yaay! + +8 - Other use examples +====================== +Actions +------- +*brew* +- brew info mobile-shell +- select project home page +- open +*gist* +- gist -a +- some example content and a +- highlight gist url +*rspec* +- bundle exec rspec +- have a failing spec +- highlight a failing spec file +- vim + +Script +------ +*brew* +To conclude this screencast, I'd like to show you a couple more examples where I +find this plugin useful. + +I'm using OS X, and I often check brew package manager packages. +Let's check this project called 'mobile shell'. + +Hmm, that doesn't tell me much about it, but there's the project homepage in the +output. +I'll use url search to fetch and open that url. + +*gist* +If you like to create gists from the command line, there's a similar use case. +I'll quickly create an example gist. + +Again, I'll use url search to fetch the gist url, without using the mouse. + +*rspec* +By far my most common usage of this plugin is when testing. +I'm a ruby developer and I often use rspec testing framework. +I'll run tests for this project. + +Oh-oh, it seems tests fail and I have to fix them. +To open the failing test file, I'll use file search. + +And now, I can open the file in vim. + +That's it for this screencast. I hope you like tmux copycat and that you'll find +it useful. diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/LICENSE.md b/dot_tmux/plugins/tmux-current-pane-hostname/LICENSE.md new file mode 100644 index 0000000..37af2ae --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Antoine Bluchet + +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/dot_tmux/plugins/tmux-current-pane-hostname/README.md b/dot_tmux/plugins/tmux-current-pane-hostname/README.md new file mode 100644 index 0000000..9c4bc5b --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/README.md @@ -0,0 +1,63 @@ +# Tmux current pane hostname/user + +Tmux plugin that enables displaying hostname and user of the current pane in your status bar. + +Replaces the `#H` format and adds a `#U` format option. + +### Usage + +- `#H` will be the hostname of your current path. If there is an ssh session opened, the ssh hostname will show instead of the local one. +- `#{hostname_short}` will be the short hostname of your current path (up to the first dot). If there is an ssh session opened, the ssh hostname will show instead of the local one. +- `#U` will show the `whoami` result or the user that logged in an ssh session. +- `#{pane_ssh_port}` if an open ssh session will show the connection port, otherwise it will be empty. +- `#{pane_ssh_connected}` will be set to 1 if the currently selected pane has an active ssh connection. (Useful for `#{?#{pane_ssh_connected},ssh,no-ssh}` which will evaluate to `ssh` if there is an active ssh in the currently selected pane and `no-ssh` otherwise.) + +Here's the example in `.tmux.conf`: + +```bash +set -g status-right '#[fg=cyan,bold] #U@#H #[default]#[fg=blue]#(tmux display-message -p "#{pane_current_path}" | sed "s#$HOME#~#g") #[fg=red]%H:%M %d-%b-%y#[default]' +``` + +### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended) + +Add plugin to the list of TPM plugins in `.tmux.conf`: + + set -g @tpm_plugins " \ + tmux-plugins/tpm \ + soyuka/tmux-current-pane-hostname \ + " + +Hit `prefix + I` to fetch the plugin and source it. + +`#U@#H` interpolation should now take the current pane ssh status into consideration. + +### Manual Installation + +Clone the repo: + + $ git clone https://github.com/soyuka/tmux-current-pane-hostname ~/clone/path + +Add this line to the bottom of `.tmux.conf`: + + run-shell ~/clone/path/current_pane_hostname.tmux + +Reload TMUX environment: + + # type this in terminal + $ tmux source-file ~/.tmux.conf + +`#U@#H` interpolation should now work. + +### Limitations + +I wanted to get the current path of the opened ssh session but that's not possible. I haven't found a way to get the output of a remote command that will be executed on an opened ssh session. A dirty way would be to use `send-keys pwd Enter` but this will show on the pane and we don't want this. +So, I'm just getting the correct ssh command corresponding to the pane job pid and parsing it, for example: +``` +ssh test@host.com +# #H => host.com +# #U => test +``` + +### License + +[MIT](LICENSE.md) diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/HEAD b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/HEAD new file mode 100644 index 0000000..cb089cd --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/branches/.keep b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/branches/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/config b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/config new file mode 100644 index 0000000..9682365 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[submodule] + active = . +[remote "origin"] + url = https://git::@github.com/soyuka/tmux-current-pane-hostname + fetch = +refs/heads/master:refs/remotes/origin/master +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/description b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_applypatch-msg.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_applypatch-msg.sample new file mode 100644 index 0000000..a5d7b84 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_commit-msg.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_commit-msg.sample new file mode 100644 index 0000000..b58d118 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_fsmonitor-watchman.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_fsmonitor-watchman.sample new file mode 100644 index 0000000..23e856f --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_post-update.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_post-update.sample new file mode 100644 index 0000000..ec17ec1 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-applypatch.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-applypatch.sample new file mode 100644 index 0000000..4142082 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-commit.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-commit.sample new file mode 100644 index 0000000..e144712 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-merge-commit.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-merge-commit.sample new file mode 100644 index 0000000..399eab1 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-push.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-push.sample new file mode 100644 index 0000000..4ce688d --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-rebase.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-rebase.sample new file mode 100644 index 0000000..6cbef5c --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-receive.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-receive.sample new file mode 100644 index 0000000..a1fd29e --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_prepare-commit-msg.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_prepare-commit-msg.sample new file mode 100644 index 0000000..10fa14c --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_push-to-checkout.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_push-to-checkout.sample new file mode 100644 index 0000000..af5a0c0 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_update.sample b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_update.sample new file mode 100644 index 0000000..c4d426b --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/hooks/executable_update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/index b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/index new file mode 100644 index 0000000..c8344de Binary files /dev/null and b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/index differ diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/info/exclude b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/logs/HEAD b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/logs/HEAD new file mode 100644 index 0000000..01576fc --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 6bb3c95250f8120d8b072f46a807d2678ecbc97c Simon Rieger 1699878735 +0100 clone: from https://github.com/soyuka/tmux-current-pane-hostname diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/logs/refs/heads/master b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/logs/refs/heads/master new file mode 100644 index 0000000..01576fc --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 6bb3c95250f8120d8b072f46a807d2678ecbc97c Simon Rieger 1699878735 +0100 clone: from https://github.com/soyuka/tmux-current-pane-hostname diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/logs/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..01576fc --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 6bb3c95250f8120d8b072f46a807d2678ecbc97c Simon Rieger 1699878735 +0100 clone: from https://github.com/soyuka/tmux-current-pane-hostname diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/info/.keep b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/info/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/pack/readonly_pack-f5ce4041f1c07643a0cbc1d1527db4aedcbd650c.idx b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/pack/readonly_pack-f5ce4041f1c07643a0cbc1d1527db4aedcbd650c.idx new file mode 100644 index 0000000..bde4e82 Binary files /dev/null and b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/pack/readonly_pack-f5ce4041f1c07643a0cbc1d1527db4aedcbd650c.idx differ diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/pack/readonly_pack-f5ce4041f1c07643a0cbc1d1527db4aedcbd650c.pack b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/pack/readonly_pack-f5ce4041f1c07643a0cbc1d1527db4aedcbd650c.pack new file mode 100644 index 0000000..9454fcd Binary files /dev/null and b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/pack/readonly_pack-f5ce4041f1c07643a0cbc1d1527db4aedcbd650c.pack differ diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/pack/readonly_pack-f5ce4041f1c07643a0cbc1d1527db4aedcbd650c.rev b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/pack/readonly_pack-f5ce4041f1c07643a0cbc1d1527db4aedcbd650c.rev new file mode 100644 index 0000000..97e0c9a Binary files /dev/null and b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/objects/pack/readonly_pack-f5ce4041f1c07643a0cbc1d1527db4aedcbd650c.rev differ diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/packed-refs b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/packed-refs new file mode 100644 index 0000000..89fad45 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +6bb3c95250f8120d8b072f46a807d2678ecbc97c refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/refs/heads/master b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/refs/heads/master new file mode 100644 index 0000000..07bdb49 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/refs/heads/master @@ -0,0 +1 @@ +6bb3c95250f8120d8b072f46a807d2678ecbc97c diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/refs/remotes/origin/HEAD new file mode 100644 index 0000000..6efe28f --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/refs/tags/.keep b/dot_tmux/plugins/tmux-current-pane-hostname/dot_git/refs/tags/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/executable_current_pane_hostname.tmux b/dot_tmux/plugins/tmux-current-pane-hostname/executable_current_pane_hostname.tmux new file mode 100644 index 0000000..aa88cf2 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/executable_current_pane_hostname.tmux @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +interpolation=('\#H' '\#{hostname_short}' '\#U' '\#\{pane_ssh_port\}' '\#\{pane_ssh_connected\}') +script=("#($CURRENT_DIR/scripts/hostname.sh)" "#($CURRENT_DIR/scripts/hostname_short.sh)" "#($CURRENT_DIR/scripts/whoami.sh)" "#($CURRENT_DIR/scripts/port.sh)" "#($CURRENT_DIR/scripts/pane_ssh_connected.sh)") + + +source $CURRENT_DIR/scripts/shared.sh + +do_interpolation() { + local interpolated=$1 + local j=0 + + for i in "${interpolation[@]}"; do + local s=${script[$j]} + local interpolated=${interpolated//$i/$s} + ((j+=1)) + done + echo "$interpolated" +} + +update_tmux_option() { + local option=$1 + local option_value=$(get_tmux_option "$option") + local new_option_value=$(do_interpolation "$option_value") + set_tmux_option "$option" "$new_option_value" +} + +main() { + update_tmux_option "status-right" + update_tmux_option "status-left" +} + +main diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_hostname.sh b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_hostname.sh new file mode 100644 index 0000000..7c6d4a0 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_hostname.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source $CURRENT_DIR/shared.sh + +main() { + get_info "hostname" +} + +main diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_hostname_short.sh b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_hostname_short.sh new file mode 100644 index 0000000..67583b5 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_hostname_short.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source $CURRENT_DIR/shared.sh + +main() { + get_info "hostname -s" +} + +main diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_pane_ssh_connected.sh b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_pane_ssh_connected.sh new file mode 100644 index 0000000..1c8cf39 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_pane_ssh_connected.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source $CURRENT_DIR/shared.sh + +main() { + if ssh_connected; then + echo 1 + else + echo 0 + fi +} + +main diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_port.sh b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_port.sh new file mode 100644 index 0000000..ff0885c --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_port.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source $CURRENT_DIR/shared.sh + +main() { + if ssh_connected; then + get_info "port" + fi +} + +main diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_whoami.sh b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_whoami.sh new file mode 100644 index 0000000..3ca5b0b --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/executable_whoami.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source $CURRENT_DIR/shared.sh + +main() { + get_info "whoami" +} + +main diff --git a/dot_tmux/plugins/tmux-current-pane-hostname/scripts/shared.sh b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/shared.sh new file mode 100644 index 0000000..063ef21 --- /dev/null +++ b/dot_tmux/plugins/tmux-current-pane-hostname/scripts/shared.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +get_tmux_option() { + local option=$1 + local default_value=$2 + local option_value=$(tmux show-option -gqv "$option") + if [ -z "$option_value" ]; then + echo "$default_value" + else + echo "$option_value" + fi +} + +set_tmux_option() { + local option=$1 + local value=$2 + tmux set-option -gq "$option" "$value" +} + +parse_ssh_port() { + # If there is a port get it + local port=$(echo $1|grep -Eo '\-p\s*([0-9]+)'|sed 's/-p\s*//') + + if [ -z $port ]; then + local port=22 + fi + + echo $port +} + +get_ssh_user() { + local ssh_user=$(whoami) + + for ssh_config in `awk ' + $1 == "Host" { + gsub("\\\\.", "\\\\.", $2); + gsub("\\\\*", ".*", $2); + host = $2; + next; + } + $1 == "User" { + $1 = ""; + sub( /^[[:space:]]*/, "" ); + printf "%s|%s\n", host, $0; + }' .ssh/config`; do + local host_regex=${ssh_config%|*} + local host_user=${ssh_config#*|} + if [[ "$1" =~ $host_regex ]]; then + ssh_user=$host_user + break + fi + done + + echo $ssh_user +} + +get_remote_info() { + local command=$1 + + # First get the current pane command pid to get the full command with arguments + local cmd=$({ pgrep -flaP `tmux display-message -p "#{pane_pid}"` ; ps -o command -p `tmux display-message -p "#{pane_pid}"` ; } | xargs -I{} echo {} | grep ssh | sed -E 's/^[0-9]*[[:blank:]]*ssh //') + + local port=$(parse_ssh_port "$cmd") + + local cmd=$(echo $cmd|sed 's/\-p\s*'"$port"'//g') + local user=$(echo $cmd | awk '{print $NF}'|cut -f1 -d@) + local host=$(echo $cmd | awk '{print $NF}'|cut -f2 -d@) + + if [ $user == $host ]; then + local user=$(get_ssh_user $host) + fi + + case "$1" in + "whoami") + echo $user + ;; + "hostname") + echo $host + ;; + "port") + echo $port + ;; + *) + echo "$user@$host:$port" + ;; + esac +} + +get_info() { + # If command is ssh do some magic + if ssh_connected; then + echo $(get_remote_info $1) + else + echo $($1) + fi +} + +ssh_connected() { + # Get current pane command + local cmd=$(tmux display-message -p "#{pane_current_command}") + + [ $cmd = "ssh" ] || [ $cmd = "sshpass" ] +} diff --git a/dot_tmux/plugins/tmux-pain-control/CHANGELOG.md b/dot_tmux/plugins/tmux-pain-control/CHANGELOG.md new file mode 100644 index 0000000..fa949b9 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/CHANGELOG.md @@ -0,0 +1,26 @@ +# Changelog + +### master +- update readme - write all keybindings +- override default split window key bindings +- Moving windows follows current window, compensate for change in behavior in + tmux 3.0 + +### v1.0.0, 2014-08-30 +- update readme to reflect github organization change +- update readme - more precise binding definition +- switch to tab indentation +- add swap-window bindings +- change "move window" key bindings to be more intuitive + +### v0.0.2, 2014-06-03 +- split-window bindings "|" and "-" now create a new pane with the same path as + the original one the split started from. +- improve the default new-window "c" binding so it creates new windows with the + same path as the current pane +- bugfix for "|", "-" and "c" bindings - setting the correct path in new windows + wasn't working properly with "$PWD". Changed to "#{pane_current_path}". +- add other plugins list to the README + +### v0.0.1, 2014-05-23 +- first version out diff --git a/dot_tmux/plugins/tmux-pain-control/LICENSE.md b/dot_tmux/plugins/tmux-pain-control/LICENSE.md new file mode 100644 index 0000000..40f6ddd --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/LICENSE.md @@ -0,0 +1,19 @@ +Copyright (C) 2014 Bruno Sutic + +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/dot_tmux/plugins/tmux-pain-control/README.md b/dot_tmux/plugins/tmux-pain-control/README.md new file mode 100644 index 0000000..18054a6 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/README.md @@ -0,0 +1,127 @@ +# Tmux Pain Control + +Tmux plugin for controlling panes. Adds standard pane navigation bindings. + +So far, you had to google around and comb other people's dotfiles to find these. +This plugin hopefully makes them more available and "more standard". + +Thanks to the Tmux community for "inventing" these bindings. I've merely just +copied them here. + +Tested and working on Linux, OSX and Cygwin. + +### Bindings + +Notice most of the bindings emulate vim cursor movements. + +pane navigation + +**Navigation** + +- `prefix + h` and `prefix + C-h`
+ select pane on the left +- `prefix + j` and `prefix + C-j`
+ select pane below the current one +- `prefix + k` and `prefix + C-k`
+ select pane above +- `prefix + l` and `prefix + C-l`
+ select pane on the right + +
+ +**Note**: This overrides tmux's default binding for toggling between last +active windows, `prefix + l`. +[tmux-sensible](https://github.com/tmux-plugins/tmux-sensible) gives you +a better binding for that, `prefix + a` (if your prefix is `C-a`). + +

+ +pane resizing + +**Resizing panes** + +- `prefix + shift + h`
+ resize current pane 5 cells to the left +- `prefix + shift + j`
+ resize 5 cells in the down direction +- `prefix + shift + k`
+ resize 5 cells in the up direction +- `prefix + shift + l`
+ resize 5 cells to the right + +These mappings are `repeatable`. + +The amount of cells to resize can be configured with `@pane_resize` option. See +[configuration section](#configuration) for the details. + +

+ +pane splitting + +**Splitting panes** + +- `prefix + |`
+ split the current pane into two, left and right. +- `prefix + -`
+ split the current pane into two, top and bottom. +- `prefix + \`
+ split current pane full width into two, left and right. +- `prefix + _`
+ split current pane full height into two, top and bottom. + +Newly created pane always has the same path as the original pane. + +




+ +**Swapping windows** + +- `prefix + <` - moves current window one position to the left +- `prefix + >` - moves current window one position to the right + +### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended) + +Add plugin to the list of TPM plugins in `.tmux.conf`: + + set -g @plugin 'tmux-plugins/tmux-pain-control' + +Hit `prefix + I` to fetch the plugin and source it. + +You should now have all `pain-control` bindings defined. + +### Manual Installation + +Clone the repo: + + $ git clone https://github.com/tmux-plugins/tmux-pain-control ~/clone/path + +Add this line to the bottom of `.tmux.conf`: + + run-shell ~/clone/path/pain_control.tmux + +Reload TMUX environment: + + # type this in terminal + $ tmux source-file ~/.tmux.conf + +You should now have all `pain-control` bindings defined. + +### Configuration + +You can set `@pane_resize` Tmux option to choose number of resize cells for the +resize bindings. "5" is the default. + +Example: + + set-option -g @pane_resize "10" + +### Other plugins + +You might also find these useful: + +- [sessionist](https://github.com/tmux-plugins/tmux-sessionist) - lightweight + tmux utils for switching and creating sessions +- [logging](https://github.com/tmux-plugins/tmux-logging) - easy logging and + screen capturing + +### License +[MIT](LICENSE.md) diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/HEAD b/dot_tmux/plugins/tmux-pain-control/dot_git/HEAD new file mode 100644 index 0000000..cb089cd --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/branches/.keep b/dot_tmux/plugins/tmux-pain-control/dot_git/branches/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/config b/dot_tmux/plugins/tmux-pain-control/dot_git/config new file mode 100644 index 0000000..84567e1 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[submodule] + active = . +[remote "origin"] + url = https://git::@github.com/tmux-plugins/tmux-pain-control + fetch = +refs/heads/master:refs/remotes/origin/master +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/description b/dot_tmux/plugins/tmux-pain-control/dot_git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_applypatch-msg.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_applypatch-msg.sample new file mode 100644 index 0000000..a5d7b84 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_commit-msg.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_commit-msg.sample new file mode 100644 index 0000000..b58d118 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_fsmonitor-watchman.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_fsmonitor-watchman.sample new file mode 100644 index 0000000..23e856f --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_post-update.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_post-update.sample new file mode 100644 index 0000000..ec17ec1 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-applypatch.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-applypatch.sample new file mode 100644 index 0000000..4142082 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-commit.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-commit.sample new file mode 100644 index 0000000..e144712 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-merge-commit.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-merge-commit.sample new file mode 100644 index 0000000..399eab1 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-push.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-push.sample new file mode 100644 index 0000000..4ce688d --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-rebase.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-rebase.sample new file mode 100644 index 0000000..6cbef5c --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-receive.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-receive.sample new file mode 100644 index 0000000..a1fd29e --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_prepare-commit-msg.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_prepare-commit-msg.sample new file mode 100644 index 0000000..10fa14c --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_push-to-checkout.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_push-to-checkout.sample new file mode 100644 index 0000000..af5a0c0 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_update.sample b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_update.sample new file mode 100644 index 0000000..c4d426b --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/hooks/executable_update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/index b/dot_tmux/plugins/tmux-pain-control/dot_git/index new file mode 100644 index 0000000..5cd8e77 Binary files /dev/null and b/dot_tmux/plugins/tmux-pain-control/dot_git/index differ diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/info/exclude b/dot_tmux/plugins/tmux-pain-control/dot_git/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/logs/HEAD b/dot_tmux/plugins/tmux-pain-control/dot_git/logs/HEAD new file mode 100644 index 0000000..074cc6d --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 32b760f6652f2305dfef0acd444afc311cf5c077 Simon Rieger 1699878731 +0100 clone: from https://github.com/tmux-plugins/tmux-pain-control diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/logs/refs/heads/master b/dot_tmux/plugins/tmux-pain-control/dot_git/logs/refs/heads/master new file mode 100644 index 0000000..074cc6d --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 32b760f6652f2305dfef0acd444afc311cf5c077 Simon Rieger 1699878731 +0100 clone: from https://github.com/tmux-plugins/tmux-pain-control diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/logs/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-pain-control/dot_git/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..074cc6d --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 32b760f6652f2305dfef0acd444afc311cf5c077 Simon Rieger 1699878731 +0100 clone: from https://github.com/tmux-plugins/tmux-pain-control diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/objects/info/.keep b/dot_tmux/plugins/tmux-pain-control/dot_git/objects/info/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/objects/pack/readonly_pack-c90847976e6a2f49a80038df7c35441827d303f1.idx b/dot_tmux/plugins/tmux-pain-control/dot_git/objects/pack/readonly_pack-c90847976e6a2f49a80038df7c35441827d303f1.idx new file mode 100644 index 0000000..7b1cca9 Binary files /dev/null and b/dot_tmux/plugins/tmux-pain-control/dot_git/objects/pack/readonly_pack-c90847976e6a2f49a80038df7c35441827d303f1.idx differ diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/objects/pack/readonly_pack-c90847976e6a2f49a80038df7c35441827d303f1.pack b/dot_tmux/plugins/tmux-pain-control/dot_git/objects/pack/readonly_pack-c90847976e6a2f49a80038df7c35441827d303f1.pack new file mode 100644 index 0000000..0d18c4d Binary files /dev/null and b/dot_tmux/plugins/tmux-pain-control/dot_git/objects/pack/readonly_pack-c90847976e6a2f49a80038df7c35441827d303f1.pack differ diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/objects/pack/readonly_pack-c90847976e6a2f49a80038df7c35441827d303f1.rev b/dot_tmux/plugins/tmux-pain-control/dot_git/objects/pack/readonly_pack-c90847976e6a2f49a80038df7c35441827d303f1.rev new file mode 100644 index 0000000..3e54660 Binary files /dev/null and b/dot_tmux/plugins/tmux-pain-control/dot_git/objects/pack/readonly_pack-c90847976e6a2f49a80038df7c35441827d303f1.rev differ diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/packed-refs b/dot_tmux/plugins/tmux-pain-control/dot_git/packed-refs new file mode 100644 index 0000000..4fad4fb --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +32b760f6652f2305dfef0acd444afc311cf5c077 refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/refs/heads/master b/dot_tmux/plugins/tmux-pain-control/dot_git/refs/heads/master new file mode 100644 index 0000000..0948796 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/refs/heads/master @@ -0,0 +1 @@ +32b760f6652f2305dfef0acd444afc311cf5c077 diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-pain-control/dot_git/refs/remotes/origin/HEAD new file mode 100644 index 0000000..6efe28f --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/refs/tags/v0.0.1 b/dot_tmux/plugins/tmux-pain-control/dot_git/refs/tags/v0.0.1 new file mode 100644 index 0000000..9b17464 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/refs/tags/v0.0.1 @@ -0,0 +1 @@ +135e4e2defb8eacc7d5f4ade445cf885e44b30a7 diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/refs/tags/v0.0.2 b/dot_tmux/plugins/tmux-pain-control/dot_git/refs/tags/v0.0.2 new file mode 100644 index 0000000..7c94fed --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/refs/tags/v0.0.2 @@ -0,0 +1 @@ +a9a98031bf298bc44282f465f7f31f2e50f0850c diff --git a/dot_tmux/plugins/tmux-pain-control/dot_git/refs/tags/v1.0.0 b/dot_tmux/plugins/tmux-pain-control/dot_git/refs/tags/v1.0.0 new file mode 100644 index 0000000..1b111d8 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_git/refs/tags/v1.0.0 @@ -0,0 +1 @@ +a678f64ed551a7386849432455011f6a63cb9fc0 diff --git a/dot_tmux/plugins/tmux-pain-control/dot_gitattributes b/dot_tmux/plugins/tmux-pain-control/dot_gitattributes new file mode 100644 index 0000000..89758fa --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/dot_gitattributes @@ -0,0 +1,4 @@ +# Force text files to have unix eols, so Windows/Cygwin does not break them +*.* eol=lf + +*.gif binary diff --git a/dot_tmux/plugins/tmux-pain-control/executable_pain_control.tmux b/dot_tmux/plugins/tmux-pain-control/executable_pain_control.tmux new file mode 100644 index 0000000..fd48409 --- /dev/null +++ b/dot_tmux/plugins/tmux-pain-control/executable_pain_control.tmux @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +default_pane_resize="5" + +# tmux show-option "q" (quiet) flag does not set return value to 1, even though +# the option does not exist. This function patches that. +get_tmux_option() { + local option=$1 + local default_value=$2 + local option_value=$(tmux show-option -gqv "$option") + if [ -z $option_value ]; then + echo $default_value + else + echo $option_value + fi +} + +pane_navigation_bindings() { + tmux bind-key h select-pane -L + tmux bind-key C-h select-pane -L + tmux bind-key j select-pane -D + tmux bind-key C-j select-pane -D + tmux bind-key k select-pane -U + tmux bind-key C-k select-pane -U + tmux bind-key l select-pane -R + tmux bind-key C-l select-pane -R +} + +window_move_bindings() { + tmux bind-key -r "<" swap-window -d -t -1 + tmux bind-key -r ">" swap-window -d -t +1 +} + +pane_resizing_bindings() { + local pane_resize=$(get_tmux_option "@pane_resize" "$default_pane_resize") + tmux bind-key -r H resize-pane -L "$pane_resize" + tmux bind-key -r J resize-pane -D "$pane_resize" + tmux bind-key -r K resize-pane -U "$pane_resize" + tmux bind-key -r L resize-pane -R "$pane_resize" +} + +pane_split_bindings() { + tmux bind-key "|" split-window -h -c "#{pane_current_path}" + tmux bind-key "\\" split-window -fh -c "#{pane_current_path}" + tmux bind-key "-" split-window -v -c "#{pane_current_path}" + tmux bind-key "_" split-window -fv -c "#{pane_current_path}" + tmux bind-key "%" split-window -h -c "#{pane_current_path}" + tmux bind-key '"' split-window -v -c "#{pane_current_path}" +} + +improve_new_window_binding() { + tmux bind-key "c" new-window -c "#{pane_current_path}" +} + +main() { + pane_navigation_bindings + window_move_bindings + pane_resizing_bindings + pane_split_bindings + improve_new_window_binding +} +main diff --git a/dot_tmux/plugins/tmux-pain-control/screenshots/pane_navigation.gif b/dot_tmux/plugins/tmux-pain-control/screenshots/pane_navigation.gif new file mode 100644 index 0000000..2d64150 Binary files /dev/null and b/dot_tmux/plugins/tmux-pain-control/screenshots/pane_navigation.gif differ diff --git a/dot_tmux/plugins/tmux-pain-control/screenshots/pane_resizing.gif b/dot_tmux/plugins/tmux-pain-control/screenshots/pane_resizing.gif new file mode 100644 index 0000000..327d6f8 Binary files /dev/null and b/dot_tmux/plugins/tmux-pain-control/screenshots/pane_resizing.gif differ diff --git a/dot_tmux/plugins/tmux-pain-control/screenshots/pane_resizing.psd b/dot_tmux/plugins/tmux-pain-control/screenshots/pane_resizing.psd new file mode 100644 index 0000000..ae93956 Binary files /dev/null and b/dot_tmux/plugins/tmux-pain-control/screenshots/pane_resizing.psd differ diff --git a/dot_tmux/plugins/tmux-pain-control/screenshots/pane_splitting.gif b/dot_tmux/plugins/tmux-pain-control/screenshots/pane_splitting.gif new file mode 100644 index 0000000..464eb42 Binary files /dev/null and b/dot_tmux/plugins/tmux-pain-control/screenshots/pane_splitting.gif differ diff --git a/dot_tmux/plugins/tmux-pain-control/screenshots/pane_splitting.psd b/dot_tmux/plugins/tmux-pain-control/screenshots/pane_splitting.psd new file mode 100644 index 0000000..59e462f Binary files /dev/null and b/dot_tmux/plugins/tmux-pain-control/screenshots/pane_splitting.psd differ diff --git a/dot_tmux/plugins/tmux-prefix-highlight/LICENSE b/dot_tmux/plugins/tmux-prefix-highlight/LICENSE new file mode 100644 index 0000000..98da78e --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Erick Pintor + +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/dot_tmux/plugins/tmux-prefix-highlight/README.md b/dot_tmux/plugins/tmux-prefix-highlight/README.md new file mode 100644 index 0000000..37dec79 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/README.md @@ -0,0 +1,121 @@ +# Tmux prefix highlight + +**NOTE:** This project is no longer in active development. Bugs and +features requests won't get implemented by the project maintainers. +We still welcome discussions and community pull requests, though. + +--- + +Plugin that highlights when you press tmux prefix key. Inspired by +[this](http://stackoverflow.com/questions/12003726/give-a-hint-when-press-prefix-key-in-tmux) +thread on stackoverflow. + +Many thanks to [@obxhdx](https://github.com/obxhdx) for showing me this trick. + +Prefix off: +![prefix_off](screenshots/prefix_off.png) + +Prefix on: +![prefix_on](screenshots/prefix_on.png) + +### Usage + +Just add `#{prefix_highlight}` to your left/right status bar. + +```tmux.conf +set -g status-right '#{prefix_highlight} | %a %Y-%m-%d %H:%M' +``` + +The plugin can also be configured to show when copy mode is active; see the +**Configurations** section for details. + +### Installation with Tmux Plugin Manager (recommended) + +Add plugin to the list of TPM plugins: + +```tmux.conf +set -g @plugin 'tmux-plugins/tmux-prefix-highlight' +``` + +Press prefix + I to install it. + +### Manual Installation + +Clone the repo: + +```bash +$ git clone https://github.com/tmux-plugins/tmux-prefix-highlight.git ~/clone/path +``` + +Add this line to your .tmux.conf: + +```tmux.conf +run-shell ~/clone/path/prefix_highlight.tmux +``` + +Reload TMUX environment with: + +```bash +$ tmux source-file ~/.tmux.conf +``` + +### Configurations + +The colors used for the prefix highlight can be configured: + +```tmux.conf +set -g @prefix_highlight_fg 'white' # default is 'colour231' +set -g @prefix_highlight_bg 'blue' # default is 'colour04' +``` + +The plugin can also be configured to show when copy or synchronized panes mode +is active. If enabled, the `#{prefix_highlight}` token will be replaced with +the string `Copy` when copy mode is enabled and `Sync` for synchronized panes. +The style for copy and sync mode can be configured as a comma-separated list of +colors and attributes: + +```tmux.conf +set -g @prefix_highlight_show_copy_mode 'on' +set -g @prefix_highlight_copy_mode_attr 'fg=black,bg=yellow,bold' # default is 'fg=default,bg=yellow' +set -g @prefix_highlight_show_sync_mode 'on' +set -g @prefix_highlight_sync_mode_attr 'fg=black,bg=green' # default is 'fg=default,bg=yellow' +``` + +The `prefix`, `copy` and `sync` prompts can also be configured: + +```tmux.conf +set -g @prefix_highlight_prefix_prompt 'Wait' +set -g @prefix_highlight_copy_prompt 'Copy' +set -g @prefix_highlight_sync_prompt 'Sync' +``` + +Additionally, the plugin can be configured to attach optional affixes to the +value contained in `#{prefix_highlight}`. +(e.g. `< ^B >`) + +```tmux.conf +set -g @prefix_highlight_output_prefix '< ' +set -g @prefix_highlight_output_suffix ' >' +``` + +The empty (shown when prefix is off) prompt and attribute can be configured, +It is useful for aligning segments. + +```tmux.conf +set -g @prefix_highlight_empty_prompt ' ' # default is '' (empty char) +set -g @prefix_highlight_empty_attr 'fg=default,bg=green' # default is 'fg=default,bg=default' +``` + +Defaultly, empty prompt can't be attached optional affixes. +If you want attach affixes on empty prompt, config `@prefix_highlight_empty_has_affixes` to `on`. + +```tmux.conf +set -g @prefix_highlight_empty_has_affixes 'on' # default is 'off' +set -g @prefix_highlight_empty_prompt 'Tmux' +set -g @prefix_highlight_output_prefix '< ' +set -g @prefix_highlight_output_suffix ' >' +``` + +### License + +[MIT](LICENSE) diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/HEAD b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/HEAD new file mode 100644 index 0000000..cb089cd --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/branches/.keep b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/branches/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/config b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/config new file mode 100644 index 0000000..b39fbc0 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[submodule] + active = . +[remote "origin"] + url = https://git::@github.com/tmux-plugins/tmux-prefix-highlight + fetch = +refs/heads/master:refs/remotes/origin/master +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/description b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_applypatch-msg.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_applypatch-msg.sample new file mode 100644 index 0000000..a5d7b84 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_commit-msg.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_commit-msg.sample new file mode 100644 index 0000000..b58d118 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_fsmonitor-watchman.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_fsmonitor-watchman.sample new file mode 100644 index 0000000..23e856f --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_post-update.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_post-update.sample new file mode 100644 index 0000000..ec17ec1 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-applypatch.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-applypatch.sample new file mode 100644 index 0000000..4142082 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-commit.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-commit.sample new file mode 100644 index 0000000..e144712 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-merge-commit.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-merge-commit.sample new file mode 100644 index 0000000..399eab1 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-push.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-push.sample new file mode 100644 index 0000000..4ce688d --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-rebase.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-rebase.sample new file mode 100644 index 0000000..6cbef5c --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-receive.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-receive.sample new file mode 100644 index 0000000..a1fd29e --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_prepare-commit-msg.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_prepare-commit-msg.sample new file mode 100644 index 0000000..10fa14c --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_push-to-checkout.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_push-to-checkout.sample new file mode 100644 index 0000000..af5a0c0 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_update.sample b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_update.sample new file mode 100644 index 0000000..c4d426b --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/hooks/executable_update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/index b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/index new file mode 100644 index 0000000..498ef1a Binary files /dev/null and b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/index differ diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/info/exclude b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/logs/HEAD b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/logs/HEAD new file mode 100644 index 0000000..03d6d17 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 13a16701207f3aac846cf7daed3f45ed3e7ea756 Simon Rieger 1699878734 +0100 clone: from https://github.com/tmux-plugins/tmux-prefix-highlight diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/logs/refs/heads/master b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/logs/refs/heads/master new file mode 100644 index 0000000..03d6d17 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 13a16701207f3aac846cf7daed3f45ed3e7ea756 Simon Rieger 1699878734 +0100 clone: from https://github.com/tmux-plugins/tmux-prefix-highlight diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/logs/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..03d6d17 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 13a16701207f3aac846cf7daed3f45ed3e7ea756 Simon Rieger 1699878734 +0100 clone: from https://github.com/tmux-plugins/tmux-prefix-highlight diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/info/.keep b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/info/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/pack/readonly_pack-7c5883098f17a21af91bd14333b936df8306ecf5.idx b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/pack/readonly_pack-7c5883098f17a21af91bd14333b936df8306ecf5.idx new file mode 100644 index 0000000..28b725b Binary files /dev/null and b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/pack/readonly_pack-7c5883098f17a21af91bd14333b936df8306ecf5.idx differ diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/pack/readonly_pack-7c5883098f17a21af91bd14333b936df8306ecf5.pack b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/pack/readonly_pack-7c5883098f17a21af91bd14333b936df8306ecf5.pack new file mode 100644 index 0000000..ee5aa7d Binary files /dev/null and b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/pack/readonly_pack-7c5883098f17a21af91bd14333b936df8306ecf5.pack differ diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/pack/readonly_pack-7c5883098f17a21af91bd14333b936df8306ecf5.rev b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/pack/readonly_pack-7c5883098f17a21af91bd14333b936df8306ecf5.rev new file mode 100644 index 0000000..5b7b0da Binary files /dev/null and b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/objects/pack/readonly_pack-7c5883098f17a21af91bd14333b936df8306ecf5.rev differ diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/packed-refs b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/packed-refs new file mode 100644 index 0000000..91fa804 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +13a16701207f3aac846cf7daed3f45ed3e7ea756 refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/refs/heads/master b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/refs/heads/master new file mode 100644 index 0000000..b5f6146 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/refs/heads/master @@ -0,0 +1 @@ +13a16701207f3aac846cf7daed3f45ed3e7ea756 diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/refs/remotes/origin/HEAD new file mode 100644 index 0000000..6efe28f --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-prefix-highlight/dot_git/refs/tags/.keep b/dot_tmux/plugins/tmux-prefix-highlight/dot_git/refs/tags/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-prefix-highlight/executable_prefix_highlight.tmux b/dot_tmux/plugins/tmux-prefix-highlight/executable_prefix_highlight.tmux new file mode 100644 index 0000000..c477ff7 --- /dev/null +++ b/dot_tmux/plugins/tmux-prefix-highlight/executable_prefix_highlight.tmux @@ -0,0 +1,104 @@ +#!/usr/bin/env bash + +set -e + +# Place holder for status left/right +place_holder="\#{prefix_highlight}" + +# Possible configurations +fg_color_config='@prefix_highlight_fg' +bg_color_config='@prefix_highlight_bg' +output_prefix='@prefix_highlight_output_prefix' +output_suffix='@prefix_highlight_output_suffix' +show_copy_config='@prefix_highlight_show_copy_mode' +show_sync_config='@prefix_highlight_show_sync_mode' +copy_attr_config='@prefix_highlight_copy_mode_attr' +sync_attr_config='@prefix_highlight_sync_mode_attr' +prefix_prompt='@prefix_highlight_prefix_prompt' +copy_prompt='@prefix_highlight_copy_prompt' +sync_prompt='@prefix_highlight_sync_prompt' +empty_prompt='@prefix_highlight_empty_prompt' +empty_attr_config='@prefix_highlight_empty_attr' +empty_has_affixes='@prefix_highlight_empty_has_affixes' + +tmux_option() { + local -r value=$(tmux show-option -gqv "$1") + local -r default="$2" + + if [ -n "$value" ]; then + echo "$value" + else + echo "$default" + fi +} + +format_style() { + echo "#[${1}]" | sed -e 's/,/]#[/g' +} + +# Defaults +default_fg='colour231' +default_bg='colour04' +default_copy_attr='fg=default,bg=yellow' +default_sync_attr='fg=default,bg=yellow' +default_empty_attr='fg=default,bg=default' +default_prefix_prompt=$(tmux_option prefix | tr "[:lower:]" "[:upper:]" | sed 's/C-/\^/') +default_copy_prompt='Copy' +default_sync_prompt='Sync' +default_empty_prompt='' + +main() { + local -r \ + fg_color=$(tmux_option "$fg_color_config" "$default_fg") \ + bg_color=$(tmux_option "$bg_color_config" "$default_bg") \ + show_copy_mode=$(tmux_option "$show_copy_config" "off") \ + show_sync_mode=$(tmux_option "$show_sync_config" "off") \ + output_prefix=$(tmux_option "$output_prefix" " ") \ + output_suffix=$(tmux_option "$output_suffix" " ") \ + copy_attr=$(tmux_option "$copy_attr_config" "$default_copy_attr") \ + sync_attr=$(tmux_option "$sync_attr_config" "$default_sync_attr") \ + prefix_prompt=$(tmux_option "$prefix_prompt" "$default_prefix_prompt") \ + copy_prompt=$(tmux_option "$copy_prompt" "$default_copy_prompt") \ + sync_prompt=$(tmux_option "$sync_prompt" "$default_sync_prompt") \ + empty_prompt=$(tmux_option "$empty_prompt" "$default_empty_prompt") \ + empty_attr=$(tmux_option "$empty_attr_config" "$default_empty_attr") \ + empty_has_affixes=$(tmux_option "$empty_has_affixes" "off") + + local -r prefix_highlight="$(format_style "fg=$fg_color,bg=$bg_color")" + local -r prefix_mode="$prefix_highlight$output_prefix$prefix_prompt$output_suffix" + + local -r copy_highlight="$(format_style "${copy_attr:+default,$copy_attr}")" + local -r copy_mode="$copy_highlight$output_prefix$copy_prompt$output_suffix" + + local -r sync_highlight="$(format_style "${sync_attr:+default,$sync_attr}")" + local -r sync_mode="$sync_highlight$output_prefix$sync_prompt$output_suffix" + + local -r empty_highlight="$(format_style "${empty_attr:+default,$empty_attr}")" + if [[ "on" = "$empty_has_affixes" ]]; then + local -r empty_mode="$empty_highlight$output_prefix$empty_prompt$output_suffix" + else + local -r empty_mode="$empty_highlight$empty_prompt" + fi + + if [[ "on" = "$show_copy_mode" ]]; then + if [[ "on" = "$show_sync_mode" ]]; then + local -r fallback="#{?pane_in_mode,$copy_mode,#{?synchronize-panes,$sync_mode,$empty_mode}}" + else + local -r fallback="#{?pane_in_mode,$copy_mode,$empty_mode}" + fi + elif [[ "on" = "$show_sync_mode" ]]; then + local -r fallback="#{?synchronize-panes,$sync_mode,$empty_mode}" + else + local -r fallback="$empty_mode" + fi + + local -r highlight="#{?client_prefix,$prefix_mode,$fallback}#[default]" + + local -r status_left_value="$(tmux_option "status-left")" + tmux set-option -gq "status-left" "${status_left_value//$place_holder/$highlight}" + + local -r status_right_value="$(tmux_option "status-right")" + tmux set-option -gq "status-right" "${status_right_value//$place_holder/$highlight}" +} + +main diff --git a/dot_tmux/plugins/tmux-prefix-highlight/screenshots/prefix_off.png b/dot_tmux/plugins/tmux-prefix-highlight/screenshots/prefix_off.png new file mode 100644 index 0000000..ae7dfab Binary files /dev/null and b/dot_tmux/plugins/tmux-prefix-highlight/screenshots/prefix_off.png differ diff --git a/dot_tmux/plugins/tmux-prefix-highlight/screenshots/prefix_on.png b/dot_tmux/plugins/tmux-prefix-highlight/screenshots/prefix_on.png new file mode 100644 index 0000000..d81adfc Binary files /dev/null and b/dot_tmux/plugins/tmux-prefix-highlight/screenshots/prefix_on.png differ diff --git a/dot_tmux/plugins/tmux-sensible/CHANGELOG.md b/dot_tmux/plugins/tmux-sensible/CHANGELOG.md new file mode 100644 index 0000000..579c0db --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/CHANGELOG.md @@ -0,0 +1,43 @@ +# Changelog + +### master +- remove `detach-on-destroy` +- do not set `aggressive-resize` on iTerm terminal +- disable `detach-on-destroy` + +### v3.0.0, 2015-06-24 +- remove 'almost sensible' feature + +### v2.3.0, 2015-06-24 +- update to support \*THE\* latest tmux version +- bugfix for `prefix + R` key binding +- fix for tmux 2.0 `default-terminal` option (thanks @kwbr) + +### v2.2.0, 2015-02-10 +- bugfix in `key_binding_not_set`: the regex is now properly detecting key + bindings with `-r` flag. +- enable `aggressive-resize` + +### v2.1.0, 2014-12-12 +- check before binding `prefix + prefix` (@m1foley) +- enable `focus-events` +- deprecate 'almost sensible' feature. The reason for this is to focus the + plugin on doing just one thing. + +### v2.0.0, 2014-10-03 +- bugfix: prevent exiting tmux if 'reattach-to-user-namespace' is not installed +- remove all mouse-related options +- introduce 'almost sensible' setting and options + +### v1.1.0, 2014-08-30 +- bugfix: determine the default shell from the $SHELL env var on OS X +- set `mode-mouse on` by default +- do not make any decision about the prefix, just enhance it +- update `README.md`. List options set in the plugin. +- do *not* set `mode-mouse on` by default because some users don't like it +- if a user changes default prefix but binds `C-b` to something else, do not + unbind `C-b` + +### v1.0.0, 2014-07-30 +- initial work on the plugin +- add readme diff --git a/dot_tmux/plugins/tmux-sensible/LICENSE.md b/dot_tmux/plugins/tmux-sensible/LICENSE.md new file mode 100644 index 0000000..40f6ddd --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/LICENSE.md @@ -0,0 +1,19 @@ +Copyright (C) 2014 Bruno Sutic + +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/dot_tmux/plugins/tmux-sensible/README.md b/dot_tmux/plugins/tmux-sensible/README.md new file mode 100644 index 0000000..fff34fa --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/README.md @@ -0,0 +1,122 @@ +# Tmux sensible + +A set of tmux options that should be acceptable to everyone. + +Inspired by [vim-sensible](https://github.com/tpope/vim-sensible). + +Tested and working on Linux, OSX and Cygwin. + +### Principles + +- `tmux-sensible` options should be acceptable to **every** tmux user!
+ If any of the options bothers you, please open an issue and it will probably + be updated (or removed). +- if you think a new option should be added, feel free to open a pull request. +- **no overriding** of user defined settings.
+ Your existing `.tmux.conf` settings are respected and they won't be changed. + That way you can use `tmux-sensible` if you have a few specific options. + +### Goals + +- group standard tmux community options in one place +- remove clutter from your `.tmux.conf` +- educate new tmux users about basic options + +### Options + +```tmux +# Address vim mode switching delay (http://superuser.com/a/252717/65504) +set -s escape-time 0 + +# Increase scrollback buffer size from 2000 to 50000 lines +set -g history-limit 50000 + +# Increase tmux messages display duration from 750ms to 4s +set -g display-time 4000 + +# Refresh 'status-left' and 'status-right' more often, from every 15s to 5s +set -g status-interval 5 + +# (OS X) Fix pbcopy/pbpaste for old tmux versions (pre 2.6) +set -g default-command "reattach-to-user-namespace -l $SHELL" + +# Upgrade $TERM +set -g default-terminal "screen-256color" + +# Emacs key bindings in tmux command prompt (prefix + :) are better than +# vi keys, even for vim users +set -g status-keys emacs + +# Focus events enabled for terminals that support them +set -g focus-events on + +# Super useful when using "grouped sessions" and multi-monitor setup +setw -g aggressive-resize on +``` + +### Key bindings + +```tmux +# Easier and faster switching between next/prev window +bind C-p previous-window +bind C-n next-window +``` + +Above bindings enhance the default `prefix + p` and `prefix + n` bindings by +allowing you to hold `Ctrl` and repeat `a + p`/`a + n` (if your prefix is +`C-a`), which is a lot quicker. + +```tmux +# Source .tmux.conf as suggested in `man tmux` +bind R source-file '~/.tmux.conf' +``` + +"Adaptable" key bindings that build upon your `prefix` value: + +```tmux +# If prefix is 'C-a' +bind C-a send-prefix +bind a last-window +``` + +If prefix is `C-b`, above keys will be `C-b` and `b`.
+If prefix is `C-z`, above keys will be `C-z` and `z`... you get the idea. + +### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended) + +Add plugin to the list of TPM plugins in `.tmux.conf`: + +```tmux +set -g @plugin 'tmux-plugins/tmux-sensible' +``` + +Hit `prefix + I` to fetch the plugin and source it. That's it! + +### Manual Installation + +Clone the repo: + + $ git clone https://github.com/tmux-plugins/tmux-sensible ~/clone/path + +Add this line to the bottom of `.tmux.conf`: + +```tmux +run-shell ~/clone/path/sensible.tmux +``` + +Reload TMUX environment with `$ tmux source-file ~/.tmux.conf`, and that's it. + +### Other goodies + +You might also find these useful: + +- [copycat](https://github.com/tmux-plugins/tmux-copycat) + improve tmux search and reduce mouse usage +- [pain control](https://github.com/tmux-plugins/tmux-pain-control) + useful standard bindings for controlling panes +- [resurrect](https://github.com/tmux-plugins/tmux-resurrect) + persists tmux environment across system restarts + +### License + +[MIT](LICENSE.md) diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/HEAD b/dot_tmux/plugins/tmux-sensible/dot_git/HEAD new file mode 100644 index 0000000..cb089cd --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/branches/.keep b/dot_tmux/plugins/tmux-sensible/dot_git/branches/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/config b/dot_tmux/plugins/tmux-sensible/dot_git/config new file mode 100644 index 0000000..d3eb0d4 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[submodule] + active = . +[remote "origin"] + url = https://git::@github.com/tmux-plugins/tmux-sensible + fetch = +refs/heads/master:refs/remotes/origin/master +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/description b/dot_tmux/plugins/tmux-sensible/dot_git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_applypatch-msg.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_applypatch-msg.sample new file mode 100644 index 0000000..a5d7b84 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_commit-msg.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_commit-msg.sample new file mode 100644 index 0000000..b58d118 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_fsmonitor-watchman.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_fsmonitor-watchman.sample new file mode 100644 index 0000000..23e856f --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_post-update.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_post-update.sample new file mode 100644 index 0000000..ec17ec1 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-applypatch.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-applypatch.sample new file mode 100644 index 0000000..4142082 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-commit.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-commit.sample new file mode 100644 index 0000000..e144712 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-merge-commit.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-merge-commit.sample new file mode 100644 index 0000000..399eab1 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-push.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-push.sample new file mode 100644 index 0000000..4ce688d --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-rebase.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-rebase.sample new file mode 100644 index 0000000..6cbef5c --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-receive.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-receive.sample new file mode 100644 index 0000000..a1fd29e --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_prepare-commit-msg.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_prepare-commit-msg.sample new file mode 100644 index 0000000..10fa14c --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_push-to-checkout.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_push-to-checkout.sample new file mode 100644 index 0000000..af5a0c0 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_update.sample b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_update.sample new file mode 100644 index 0000000..c4d426b --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/hooks/executable_update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/index b/dot_tmux/plugins/tmux-sensible/dot_git/index new file mode 100644 index 0000000..fccaade Binary files /dev/null and b/dot_tmux/plugins/tmux-sensible/dot_git/index differ diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/info/exclude b/dot_tmux/plugins/tmux-sensible/dot_git/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/logs/HEAD b/dot_tmux/plugins/tmux-sensible/dot_git/logs/HEAD new file mode 100644 index 0000000..82ba5c3 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 25cb91f42d020f675bb0a2ce3fbd3a5d96119efa Simon Rieger 1699878729 +0100 clone: from https://github.com/tmux-plugins/tmux-sensible diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/logs/refs/heads/master b/dot_tmux/plugins/tmux-sensible/dot_git/logs/refs/heads/master new file mode 100644 index 0000000..82ba5c3 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 25cb91f42d020f675bb0a2ce3fbd3a5d96119efa Simon Rieger 1699878729 +0100 clone: from https://github.com/tmux-plugins/tmux-sensible diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/logs/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-sensible/dot_git/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..82ba5c3 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 25cb91f42d020f675bb0a2ce3fbd3a5d96119efa Simon Rieger 1699878729 +0100 clone: from https://github.com/tmux-plugins/tmux-sensible diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/objects/info/.keep b/dot_tmux/plugins/tmux-sensible/dot_git/objects/info/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/objects/pack/readonly_pack-6b9a01cfec744033b4a7c1d9f764911107dadf93.idx b/dot_tmux/plugins/tmux-sensible/dot_git/objects/pack/readonly_pack-6b9a01cfec744033b4a7c1d9f764911107dadf93.idx new file mode 100644 index 0000000..2cdcae9 Binary files /dev/null and b/dot_tmux/plugins/tmux-sensible/dot_git/objects/pack/readonly_pack-6b9a01cfec744033b4a7c1d9f764911107dadf93.idx differ diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/objects/pack/readonly_pack-6b9a01cfec744033b4a7c1d9f764911107dadf93.pack b/dot_tmux/plugins/tmux-sensible/dot_git/objects/pack/readonly_pack-6b9a01cfec744033b4a7c1d9f764911107dadf93.pack new file mode 100644 index 0000000..adb25e1 Binary files /dev/null and b/dot_tmux/plugins/tmux-sensible/dot_git/objects/pack/readonly_pack-6b9a01cfec744033b4a7c1d9f764911107dadf93.pack differ diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/objects/pack/readonly_pack-6b9a01cfec744033b4a7c1d9f764911107dadf93.rev b/dot_tmux/plugins/tmux-sensible/dot_git/objects/pack/readonly_pack-6b9a01cfec744033b4a7c1d9f764911107dadf93.rev new file mode 100644 index 0000000..a2745c4 Binary files /dev/null and b/dot_tmux/plugins/tmux-sensible/dot_git/objects/pack/readonly_pack-6b9a01cfec744033b4a7c1d9f764911107dadf93.rev differ diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/packed-refs b/dot_tmux/plugins/tmux-sensible/dot_git/packed-refs new file mode 100644 index 0000000..aa00119 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +25cb91f42d020f675bb0a2ce3fbd3a5d96119efa refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/refs/heads/master b/dot_tmux/plugins/tmux-sensible/dot_git/refs/heads/master new file mode 100644 index 0000000..61072b5 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/refs/heads/master @@ -0,0 +1 @@ +25cb91f42d020f675bb0a2ce3fbd3a5d96119efa diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-sensible/dot_git/refs/remotes/origin/HEAD new file mode 100644 index 0000000..6efe28f --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v1.0.0 b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v1.0.0 new file mode 100644 index 0000000..f9c2582 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v1.0.0 @@ -0,0 +1 @@ +bb7593b2c5c6c76a2872981f837d16e6ddbeff53 diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v1.1.0 b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v1.1.0 new file mode 100644 index 0000000..9a414ff --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v1.1.0 @@ -0,0 +1 @@ +dfea8c551c6c6b5e03873476360a732cc798f3a5 diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.0.0 b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.0.0 new file mode 100644 index 0000000..58a2b6e --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.0.0 @@ -0,0 +1 @@ +8478e668197b78c46e2fe934ea2b582587731be9 diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.1.0 b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.1.0 new file mode 100644 index 0000000..9e5cf7a --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.1.0 @@ -0,0 +1 @@ +992141db12089e0a1cc9fac1e425788fdc34173c diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.2.0 b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.2.0 new file mode 100644 index 0000000..ddb030e --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.2.0 @@ -0,0 +1 @@ +f896d2af916d3185616d498287515b3d43449aa1 diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.3.0 b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.3.0 new file mode 100644 index 0000000..39a28a4 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v2.3.0 @@ -0,0 +1 @@ +a4f9a791e09178abcb7a9625cfea9e210f14210e diff --git a/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v3.0.0 b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v3.0.0 new file mode 100644 index 0000000..631584b --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_git/refs/tags/v3.0.0 @@ -0,0 +1 @@ +ccb68a6b1cf9b75818b93240240d6d266f2f12c4 diff --git a/dot_tmux/plugins/tmux-sensible/dot_gitattributes b/dot_tmux/plugins/tmux-sensible/dot_gitattributes new file mode 100644 index 0000000..4cde323 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/dot_gitattributes @@ -0,0 +1,2 @@ +# Force text files to have unix eols, so Windows/Cygwin does not break them +*.* eol=lf diff --git a/dot_tmux/plugins/tmux-sensible/executable_sensible.tmux b/dot_tmux/plugins/tmux-sensible/executable_sensible.tmux new file mode 100644 index 0000000..66db3c1 --- /dev/null +++ b/dot_tmux/plugins/tmux-sensible/executable_sensible.tmux @@ -0,0 +1,168 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# used to match output from `tmux list-keys` +KEY_BINDING_REGEX="bind-key[[:space:]]\+\(-r[[:space:]]\+\)\?\(-T prefix[[:space:]]\+\)\?" + +is_osx() { + local platform=$(uname) + [ "$platform" == "Darwin" ] +} + +iterm_terminal() { + [[ "${TERM_PROGRAM}" =~ ^iTerm || "${LC_TERMINAL}" =~ ^iTerm ]] +} + +command_exists() { + local command="$1" + type "$command" >/dev/null 2>&1 +} + +# returns prefix key, e.g. 'C-a' +prefix() { + tmux show-option -gv prefix +} + +# if prefix is 'C-a', this function returns 'a' +prefix_without_ctrl() { + local prefix="$(prefix)" + echo "$prefix" | cut -d '-' -f2 +} + +option_value_not_changed() { + local option="$1" + local default_value="$2" + local option_value=$(tmux show-option -gv "$option") + [ "$option_value" == "$default_value" ] +} + +server_option_value_not_changed() { + local option="$1" + local default_value="$2" + local option_value=$(tmux show-option -sv "$option") + [ "$option_value" == "$default_value" ] +} + +key_binding_not_set() { + local key="${1//\\/\\\\}" + if $(tmux list-keys | grep -q "${KEY_BINDING_REGEX}${key}[[:space:]]"); then + return 1 + else + return 0 + fi +} + +key_binding_not_changed() { + local key="$1" + local default_value="$2" + if $(tmux list-keys | grep -q "${KEY_BINDING_REGEX}${key}[[:space:]]\+${default_value}"); then + # key still has the default binding + return 0 + else + return 1 + fi +} + +get_tmux_config() { + local tmux_config_xdg="${XDG_CONFIG_HOME:-$HOME/.config}/tmux/tmux.conf" + local tmux_config="$HOME/.tmux.conf" + + if [ -f "${tmux_config_xdg}" ]; then + echo "${tmux_config_xdg}" + else + echo ${tmux_config} + fi +} + +main() { + # OPTIONS + + # address vim mode switching delay (http://superuser.com/a/252717/65504) + if server_option_value_not_changed "escape-time" "500"; then + tmux set-option -s escape-time 0 + fi + + # increase scrollback buffer size + if option_value_not_changed "history-limit" "2000"; then + tmux set-option -g history-limit 50000 + fi + + # tmux messages are displayed for 4 seconds + if option_value_not_changed "display-time" "750"; then + tmux set-option -g display-time 4000 + fi + + # refresh 'status-left' and 'status-right' more often + if option_value_not_changed "status-interval" "15"; then + tmux set-option -g status-interval 5 + fi + + # required (only) on OS X + if is_osx && command_exists "reattach-to-user-namespace" && option_value_not_changed "default-command" ""; then + tmux set-option -g default-command "reattach-to-user-namespace -l $SHELL" + fi + + # upgrade $TERM, tmux 1.9 + if option_value_not_changed "default-terminal" "screen"; then + tmux set-option -g default-terminal "screen-256color" + fi + # upgrade $TERM, tmux 2.0+ + if server_option_value_not_changed "default-terminal" "screen"; then + tmux set-option -s default-terminal "screen-256color" + fi + + # emacs key bindings in tmux command prompt (prefix + :) are better than + # vi keys, even for vim users + tmux set-option -g status-keys emacs + + # focus events enabled for terminals that support them + tmux set-option -g focus-events on + + # super useful when using "grouped sessions" and multi-monitor setup + if ! iterm_terminal; then + tmux set-window-option -g aggressive-resize on + fi + + # DEFAULT KEY BINDINGS + + local prefix="$(prefix)" + local prefix_without_ctrl="$(prefix_without_ctrl)" + + # if C-b is not prefix + if [ $prefix != "C-b" ]; then + # unbind obsolete default binding + if key_binding_not_changed "C-b" "send-prefix"; then + tmux unbind-key C-b + fi + + # pressing `prefix + prefix` sends to the shell + if key_binding_not_set "$prefix"; then + tmux bind-key "$prefix" send-prefix + fi + fi + + # If Ctrl-a is prefix then `Ctrl-a + a` switches between alternate windows. + # Works for any prefix character. + if key_binding_not_set "$prefix_without_ctrl"; then + tmux bind-key "$prefix_without_ctrl" last-window + fi + + # easier switching between next/prev window + if key_binding_not_set "C-p"; then + tmux bind-key C-p previous-window + fi + if key_binding_not_set "C-n"; then + tmux bind-key C-n next-window + fi + + # source `.tmux.conf` file - as suggested in `man tmux` + if key_binding_not_set "R"; then + local tmux_config=$(get_tmux_config) + + tmux bind-key R run-shell " \ + tmux source-file ${tmux_config} > /dev/null; \ + tmux display-message 'Sourced ${tmux_config}!'" + fi +} +main diff --git a/dot_tmux/plugins/tmux-yank/CHANGELOG.md b/dot_tmux/plugins/tmux-yank/CHANGELOG.md new file mode 100644 index 0000000..ca1740c --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/CHANGELOG.md @@ -0,0 +1,132 @@ +Change Log +========== + +[master] +-------- + +### Added + +- Mouse support, controlled by `yank_with_mouse` and `yank_selection_mouse` + (@keidax) + +[v2.3.0] 2018-02-01 +------------------- + +### Added + +- Tmux 2.4 support (@docwhat, @edi9999) +- Windows Subsystem for Linux (WSL) support via `clip.exe` (@lukewang1024) +- "copy pane current directory" feature (@bruno-) +- `yank_line` and `yank_pane_pwd` fork to prevent xclip from hanging Tmux (@leoalekseyev) +* `yank_line` no longer cares if you use emacs or vi in copy-mode. + +### Fixed + +- Detect git builds of tmux version ≥ 2.4 (@maximbaz PR#89) + +[v2.2.0] 2015-10-12 +------------------- + +### Added + +- Support for custom copy command (if `xclip` and others aren't + accessible, and you want to have your custom copy command) +- Cygwin support via `putclip` command + +[v2.1.0] 2015-06-17 +------------------- + +### Added + +- Add support for `xsel` on Linux (@ctjhoa) +- Support for shell `vi` mode (@xnaveira) + +### Updated + +- Make `reattach-to-user-namespace` on OS X optional (@bosr) +- Deprecate Alty + +[v2.0.0] 2014-12-06 +------------------- + +### Fixed + +- Change copy mode "put selection" key binding to Y so that vi + mode Controly is not overridden. + +[v1.0.0] 2014-12-06 +------------------- + +### Added + +- Show error message if plugin dependencies aren't installed. +- Vagrant setup for manually testing Linux. + +### Updated + +- `README` + - Related plugin list + - Instructions on updating `xclip` for Linux. + +### Removed + +- The screen-cast is moved into `screencast` branch. + +[v0.0.4] 2014-07-29 +------------------- + +### Updated + +- `README` documentation; including a screen-cast. + +[v0.0.3] 2014-06-29 +------------------- + +### Added + +- Wait when doing "yank line" when using a remote shell (`ssh`, `mosh`) to + ensure screen is updated. + +### Fixed + +- Handle `yank-line` when used on the last line of buffer: copy multiple + lines. +- `yank-line` never yanks 'newline' char for multiple-line commands in + shell (this is actually tmux/bash bug). + +### Updated + +- Code cleanup. + +[v0.0.2] 2014-06-25 +------------------- + +### Updated + + - `README` + +### Added + + - In OS X: Check if `reattach-to-user-namespace` is installed. + - "copy current command line" feature. + +[v0.0.1] 2014-06-24 +------------------- + +- First working version. + +Notes +----- + +This change log is kept in format. + + [master]: https://github.com/tmux-plugins/tmux-yank/compare/v2.3.0...HEAD + [v2.3.0]: https://github.com/tmux-plugins/tmux-yank/compare/v2.2.0...v2.3.0 + [v2.2.0]: https://github.com/tmux-plugins/tmux-yank/compare/v2.1.0...v2.2.0 + [v2.1.0]: https://github.com/tmux-plugins/tmux-yank/compare/v2.0.0...v2.1.0 + [v2.0.0]: https://github.com/tmux-plugins/tmux-yank/compare/v1.0.0...v2.0.0 + [v1.0.0]: https://github.com/tmux-plugins/tmux-yank/compare/v0.0.4...v1.0.0 + [v0.0.4]: https://github.com/tmux-plugins/tmux-yank/compare/v0.0.3...v0.0.4 + [v0.0.3]: https://github.com/tmux-plugins/tmux-yank/compare/v0.0.2...v0.0.3 + [v0.0.2]: https://github.com/tmux-plugins/tmux-yank/compare/v0.0.1...v0.0.2 + [v0.0.1]: https://github.com/tmux-plugins/tmux-yank/commits/v0.0.1 diff --git a/dot_tmux/plugins/tmux-yank/LICENSE.md b/dot_tmux/plugins/tmux-yank/LICENSE.md new file mode 100644 index 0000000..a898835 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/LICENSE.md @@ -0,0 +1,20 @@ +Copyright (C) 2014, 2017 Bruno Sutic +Copyright (C) 2017 Christian Höltje + +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/dot_tmux/plugins/tmux-yank/README.md b/dot_tmux/plugins/tmux-yank/README.md new file mode 100644 index 0000000..cfe5a79 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/README.md @@ -0,0 +1,290 @@ +[![Build +Status](https://travis-ci.org/tmux-plugins/tmux-yank.svg?branch=master)](https://travis-ci.org/tmux-plugins/tmux-yank) +[![GitHub +release](https://img.shields.io/github/release/tmux-plugins/tmux-yank.svg)](https://github.com/tmux-plugins/tmux-yank/releases) +[![GitHub +issues](https://img.shields.io/github/issues/tmux-plugins/tmux-yank.svg)](https://github.com/tmux-plugins/tmux-yank/issues) + +tmux-yank +========= + +Copy to the system clipboard in [`tmux`](https://tmux.github.io/). + +Supports: + +- Linux +- macOS +- Cygwin +- Windows Subsystem for Linux (WSL) + +Installing +---------- + +### Via TPM (recommended) + +The easiest way to install `tmux-yank` is via the [Tmux Plugin +Manager](https://github.com/tmux-plugins/tpm). + +1. Add plugin to the list of TPM plugins in `.tmux.conf`: + + ``` tmux + set -g @plugin 'tmux-plugins/tmux-yank' + ``` + +2. Use prefixI install `tmux-yank`. You should now + be able to `tmux-yank` immediately. +3. When you want to update `tmux-yank` use prefixU. + +### Manual Installation + +1. Clone the repository + + ``` sh + $ git clone https://github.com/tmux-plugins/tmux-yank ~/clone/path + ``` + +2. Add this line to the bottom of `.tmux.conf` + + ``` tmux + run-shell ~/clone/path/yank.tmux + ``` + +3. Reload the `tmux` environment + + ``` sh + # type this inside tmux + $ tmux source-file ~/.tmux.conf + ``` + +You should now be able to use `tmux-yank` immediately. + +Requirements +------------ + +In order for `tmux-yank` to work, there must be a program that store data in +the system clipboard. + +### macOS + +- [`reattach-to-user-namespace`](https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard) + +**Note**: Some versions of macOS (aka OS X) have been reported to work +without `reattach-to-user-namespace`. It doesn't hurt to have it installed. + +- OS X 10.8: Mountain Lion – *required* +- OS X 10.9: Mavericks – *required* +- OS X 10.10: Yosemite – *not required* +- OS X 10.11: El Capitan – *not required* +- macOS 10.12: Sierra – *required* +- macOS 10.14: Mojave - *required* +- macOS 10.15: Catalina - *not required* + +The easiest way to use `reattach-to-user-namespace` with `tmux` is use to +use the [`tmux-sensible`](https://github.com/tmux-plugins/tmux-sensible) +plugin. + +To use it manually, use: + +``` tmux +# ~/.tmux.conf +set-option -g default-command "reattach-to-user-namespace -l $SHELL" +``` + +If you have `tmux` 1.5 or newer and are using +[iTerm2](https://www.iterm2.com/) version 3 or newer then the y +in `copy-mode` and mouse selection will work without `tmux-yank`. + +To enable this: + +1. Go into iTerm2's preferences. +2. Go to the "General" tab. +3. Check "Applications in terminal may access clipboard" +4. In `tmux`, ensure `set-clipboard` is turned on: + + ``` sh + $ tmux show-options -g -s set-clipboard + set-clipboard on + ``` + +#### [HomeBrew](https://brew.sh/) (recommended) + +``` sh +$ brew install reattach-to-user-namespace +``` + +#### MacPorts + +``` sh +$ sudo port install tmux-pasteboard +``` + +### Linux + +- `xsel` (recommended) or `xclip` (for X). +- `wl-copy` from [wl-clipboard](https://github.com/bugaevc/wl-clipboard) (for Wayland) + +If you have `tmux` 1.5 or newer and are using `xterm`, the y in +`copy-mode` and mouse selection will work without `tmux-yank`. See the +`tmux(1)` man page entry for the `set-clipboard` option. + +#### Debian & Ubuntu + +``` sh +$ sudo apt-get install xsel # or xclip +``` + +#### RedHat & CentOS + +``` sh +$ sudo yum install xsel # or xclip +``` + +### Cygwin + +- (*optional*) `putclip` which is part of the `cygutils-extra` package. + +### Windows Subsystem for Linux (WSL) + +- `clip.exe` is shipped with Windows Subsystem for Linux. + +Configuration +------------- + +### Key bindings + +- Normal Mode + - prefixy — copies text from the command line + to the clipboard. + + Works with all popular shells/repls. Tested with: + + - shells: `bash`, `zsh` (with `bindkey -e`), `tcsh` + - repls: `irb`, `pry`, `node`, `psql`, `python`, `php -a`, + `coffee` + - remote shells: `ssh`, [mosh](http://mosh.mit.edu/) + - vim/neovim command line (requires + [vim-husk](https://github.com/bruno-/vim-husk) or + [vim-rsi](https://github.com/tpope/vim-rsi) plugin) + + - prefixY — copy the current pane's current + working directory to the clipboard. + +- Copy Mode + - y — copy selection to system clipboard. + - Y (shift-y) — "put" selection. Equivalent to copying a + selection, and pasting it to the command line. + + +### Default and Preferred Clipboard Programs + +tmux-yank does its best to detect a reasonable choice for a clipboard +program on your OS. + +If tmux-yank can't detect a known clipboard program then it uses the +`@custom_copy_command` tmux option as your clipboard program if set. + +If you need to always override tmux-yank's choice for a clipboard program, +then you can set `@override_copy_command` to force tmux-yank to use whatever +you want. + +Note that both programs _must_ accept `STDIN` for the text to be copied. + +An example of setting `@override_copy_command`: + +``` tmux +# ~/.tmux.conf + +set -g @custom_copy_command 'my-clipboard-copy --some-arg' +# or +set -g @override_copy_command 'my-clipboard-copy --some-arg' +``` + +### Linux Clipboards + +Linux has several cut-and-paste clipboards: `primary`, `secondary`, and +`clipboard` (default in tmux-yank is `clipboard`). + +You can change this by setting `@yank_selection`: + +``` tmux +# ~/.tmux.conf + +set -g @yank_selection 'primary' # or 'secondary' or 'clipboard' +``` + +With mouse support turned on (see below) the default clipboard for mouse +selections is `primary`. + +You can change this by setting `@yank_selection_mouse`: + +``` tmux +# ~/.tmux.conf + +set -g @yank_selection_mouse 'clipboard' # or 'primary' or 'secondary' +``` + +### Controlling Yank Behavior + +By default, `tmux-yank` will exit copy mode after yanking text. If you wish to +remain in copy mode, you can set `@yank_action`: + +``` tmux +# ~/.tmux.conf + +set -g @yank_action 'copy-pipe' # or 'copy-pipe-and-cancel' for the default +``` + +### Mouse Support + +`tmux-yank` has mouse support enabled by default. It will only work if `tmux`'s +built-in mouse support is also enabled (with `mouse on` since `tmux` 2.1, or +`mode-mouse on` in older versions). + +To yank with the mouse, click and drag with the primary button to begin +selection, and release to yank. + +If you would prefer to disable this behavior, or provide your own bindings for +the `MouseDragEnd1Pane` event, you can do so with: + +``` tmux +# ~/.tmux.conf + +set -g @yank_with_mouse off # or 'on' +``` + +If you want to remain in copy mode after making a mouse selection, set +`@yank_action` as described above. + +### vi mode support + +If using `tmux` 2.3 or older *and* using vi keys then you'll have add the +following configuration setting: + +``` tmux +# ~/.tmux.conf + +set -g @shell_mode 'vi' +``` + +This isn't needed with `tmux` 2.4 or newer. + +### Screen-cast + +[![screencast +screenshot](/video/screencast_img.png)](https://vimeo.com/102039099) + +**Note**: The screen-cast uses Controly for +"put selection". Use Y in `v2.0.0` and later. + +### Other tmux plugins + +- [tmux-copycat](https://github.com/tmux-plugins/tmux-copycat) - a plugin + for regular expression searches in tmux and fast match selection +- [tmux-open](https://github.com/tmux-plugins/tmux-open) - a plugin for + quickly opening highlighted file or a URL +- [tmux-continuum](https://github.com/tmux-plugins/tmux-continuum) - + automatic restoring and continuous saving of tmux environment. + +### License + +[MIT](LICENSE.md) diff --git a/dot_tmux/plugins/tmux-yank/Vagrantfile b/dot_tmux/plugins/tmux-yank/Vagrantfile new file mode 100644 index 0000000..778b77a --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/Vagrantfile @@ -0,0 +1,10 @@ +VAGRANTFILE_API_VERSION = '2' + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.box = 'precise32' + config.vm.box_url = 'http://files.vagrantup.com/precise32.box' + + config.vm.provision 'shell', path: 'vagrant_provisioning.sh' + + config.ssh.forward_x11 = true +end diff --git a/dot_tmux/plugins/tmux-yank/_config.yml b/dot_tmux/plugins/tmux-yank/_config.yml new file mode 100644 index 0000000..c741881 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-slate \ No newline at end of file diff --git a/dot_tmux/plugins/tmux-yank/dot_editorconfig b/dot_tmux/plugins/tmux-yank/dot_editorconfig new file mode 100644 index 0000000..d65b947 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_editorconfig @@ -0,0 +1,24 @@ +# EditorConfig: http://EditorConfig.org + +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 + +[*.md] +max_line_length = 76 +indent_size = 4 +trim_trailing_whitespace = true + +[Vagrantfile] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + + +[{*.sh,*.tmux}] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true diff --git a/dot_tmux/plugins/tmux-yank/dot_git/HEAD b/dot_tmux/plugins/tmux-yank/dot_git/HEAD new file mode 100644 index 0000000..cb089cd --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/dot_tmux/plugins/tmux-yank/dot_git/branches/.keep b/dot_tmux/plugins/tmux-yank/dot_git/branches/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/config b/dot_tmux/plugins/tmux-yank/dot_git/config new file mode 100644 index 0000000..c715f37 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[submodule] + active = . +[remote "origin"] + url = https://git::@github.com/tmux-plugins/tmux-yank + fetch = +refs/heads/master:refs/remotes/origin/master +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/dot_tmux/plugins/tmux-yank/dot_git/description b/dot_tmux/plugins/tmux-yank/dot_git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_applypatch-msg.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_applypatch-msg.sample new file mode 100644 index 0000000..a5d7b84 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_commit-msg.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_commit-msg.sample new file mode 100644 index 0000000..b58d118 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_fsmonitor-watchman.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_fsmonitor-watchman.sample new file mode 100644 index 0000000..23e856f --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_post-update.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_post-update.sample new file mode 100644 index 0000000..ec17ec1 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-applypatch.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-applypatch.sample new file mode 100644 index 0000000..4142082 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-commit.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-commit.sample new file mode 100644 index 0000000..e144712 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-merge-commit.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-merge-commit.sample new file mode 100644 index 0000000..399eab1 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-push.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-push.sample new file mode 100644 index 0000000..4ce688d --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-rebase.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-rebase.sample new file mode 100644 index 0000000..6cbef5c --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-receive.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-receive.sample new file mode 100644 index 0000000..a1fd29e --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_prepare-commit-msg.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_prepare-commit-msg.sample new file mode 100644 index 0000000..10fa14c --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_push-to-checkout.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_push-to-checkout.sample new file mode 100644 index 0000000..af5a0c0 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_update.sample b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_update.sample new file mode 100644 index 0000000..c4d426b --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/hooks/executable_update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/index b/dot_tmux/plugins/tmux-yank/dot_git/index new file mode 100644 index 0000000..2944782 Binary files /dev/null and b/dot_tmux/plugins/tmux-yank/dot_git/index differ diff --git a/dot_tmux/plugins/tmux-yank/dot_git/info/exclude b/dot_tmux/plugins/tmux-yank/dot_git/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/dot_tmux/plugins/tmux-yank/dot_git/logs/HEAD b/dot_tmux/plugins/tmux-yank/dot_git/logs/HEAD new file mode 100644 index 0000000..28d8117 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 acfd36e4fcba99f8310a7dfb432111c242fe7392 Simon Rieger 1699878733 +0100 clone: from https://github.com/tmux-plugins/tmux-yank diff --git a/dot_tmux/plugins/tmux-yank/dot_git/logs/refs/heads/master b/dot_tmux/plugins/tmux-yank/dot_git/logs/refs/heads/master new file mode 100644 index 0000000..28d8117 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 acfd36e4fcba99f8310a7dfb432111c242fe7392 Simon Rieger 1699878733 +0100 clone: from https://github.com/tmux-plugins/tmux-yank diff --git a/dot_tmux/plugins/tmux-yank/dot_git/logs/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-yank/dot_git/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..28d8117 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 acfd36e4fcba99f8310a7dfb432111c242fe7392 Simon Rieger 1699878733 +0100 clone: from https://github.com/tmux-plugins/tmux-yank diff --git a/dot_tmux/plugins/tmux-yank/dot_git/objects/info/.keep b/dot_tmux/plugins/tmux-yank/dot_git/objects/info/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/objects/pack/readonly_pack-9589e7095e8016290060123bf3cc10e133b790ba.idx b/dot_tmux/plugins/tmux-yank/dot_git/objects/pack/readonly_pack-9589e7095e8016290060123bf3cc10e133b790ba.idx new file mode 100644 index 0000000..761058b Binary files /dev/null and b/dot_tmux/plugins/tmux-yank/dot_git/objects/pack/readonly_pack-9589e7095e8016290060123bf3cc10e133b790ba.idx differ diff --git a/dot_tmux/plugins/tmux-yank/dot_git/objects/pack/readonly_pack-9589e7095e8016290060123bf3cc10e133b790ba.pack b/dot_tmux/plugins/tmux-yank/dot_git/objects/pack/readonly_pack-9589e7095e8016290060123bf3cc10e133b790ba.pack new file mode 100644 index 0000000..a86c0a2 Binary files /dev/null and b/dot_tmux/plugins/tmux-yank/dot_git/objects/pack/readonly_pack-9589e7095e8016290060123bf3cc10e133b790ba.pack differ diff --git a/dot_tmux/plugins/tmux-yank/dot_git/objects/pack/readonly_pack-9589e7095e8016290060123bf3cc10e133b790ba.rev b/dot_tmux/plugins/tmux-yank/dot_git/objects/pack/readonly_pack-9589e7095e8016290060123bf3cc10e133b790ba.rev new file mode 100644 index 0000000..5a64f01 Binary files /dev/null and b/dot_tmux/plugins/tmux-yank/dot_git/objects/pack/readonly_pack-9589e7095e8016290060123bf3cc10e133b790ba.rev differ diff --git a/dot_tmux/plugins/tmux-yank/dot_git/packed-refs b/dot_tmux/plugins/tmux-yank/dot_git/packed-refs new file mode 100644 index 0000000..3c66c70 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +acfd36e4fcba99f8310a7dfb432111c242fe7392 refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/heads/master b/dot_tmux/plugins/tmux-yank/dot_git/refs/heads/master new file mode 100644 index 0000000..443e2c8 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/heads/master @@ -0,0 +1 @@ +acfd36e4fcba99f8310a7dfb432111c242fe7392 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/remotes/origin/HEAD b/dot_tmux/plugins/tmux-yank/dot_git/refs/remotes/origin/HEAD new file mode 100644 index 0000000..6efe28f --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.1 b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.1 new file mode 100644 index 0000000..244d228 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.1 @@ -0,0 +1 @@ +34a97e02dbf7cde9e461f477c5b7a9f15efdfa48 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.2 b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.2 new file mode 100644 index 0000000..826199a --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.2 @@ -0,0 +1 @@ +260c29505bbdd90511d467bfb117db29c1c94659 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.3 b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.3 new file mode 100644 index 0000000..9ef4315 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.3 @@ -0,0 +1 @@ +76a5c8485f00acdecdad6372afe7a97ef1fd2236 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.4 b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.4 new file mode 100644 index 0000000..b7478b5 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v0.0.4 @@ -0,0 +1 @@ +f633618cdd55caec59b63ce69bdd13924f67ec91 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v1.0.0 b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v1.0.0 new file mode 100644 index 0000000..81c2f18 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v1.0.0 @@ -0,0 +1 @@ +c879f38dbcc2740b3ad64eb27c6ea7e9c4ba5d65 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.0.0 b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.0.0 new file mode 100644 index 0000000..4058041 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.0.0 @@ -0,0 +1 @@ +c3262f748883c8324a66d4df5bfe74e25bd3a882 diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.1.0 b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.1.0 new file mode 100644 index 0000000..e7fd9d4 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.1.0 @@ -0,0 +1 @@ +3d479d92d01c3360d371c820102d5b00f3cf505b diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.2.0 b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.2.0 new file mode 100644 index 0000000..4d0c37a --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.2.0 @@ -0,0 +1 @@ +82e65a84dddd072b642bda322bffac246fafe26b diff --git a/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.3.0 b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.3.0 new file mode 100644 index 0000000..d02e288 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_git/refs/tags/v2.3.0 @@ -0,0 +1 @@ +fd8000238b324005389076486a2e6e03dba1c64f diff --git a/dot_tmux/plugins/tmux-yank/dot_gitattributes b/dot_tmux/plugins/tmux-yank/dot_gitattributes new file mode 100644 index 0000000..07c6d8e --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_gitattributes @@ -0,0 +1,11 @@ +# The linguist directives are for https://github.com/github/linguist + +*.md text eol=lf whitespace=blank-at-eol +*.sh text eol=lf whitespace=blank-at-eol diff=php +*.tmux text eol=lf whitespace=blank-at-eol diff=php + +Vagrantfile text eol=lf linguist-vendored +video/* linguist-documentation + +# Binary Types +*.png binary diff --git a/dot_tmux/plugins/tmux-yank/dot_gitignore b/dot_tmux/plugins/tmux-yank/dot_gitignore new file mode 100644 index 0000000..a977916 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_gitignore @@ -0,0 +1 @@ +.vagrant/ diff --git a/dot_tmux/plugins/tmux-yank/dot_travis.yml b/dot_tmux/plugins/tmux-yank/dot_travis.yml new file mode 100644 index 0000000..cc4b3ac --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/dot_travis.yml @@ -0,0 +1,17 @@ +sudo: required +language: bash +services: + - docker + +script: +- "./citest" + +notifications: + email: false + pushover: + on_success: change + on_failure: always + api_key: + secure: gWoqAqGyBbO6mcKbHkt29jJZ7ElOfct2C5WPfliBARl8ImCE0HE6CEGdK25i29mjfIxXWp3HITsRawuauZDN8nCZ9srO+0wr7OWAcZuhDW6mDmKNLX2y4eR4lK21MsMpLIHqA48hYXkHVKSHR7TDG88A/0MRXoTb5gcuPDJMqPk= + users: + secure: dIUBBbi8R7cOcwBQ8guLsq+M8vBXcSAu9vKUVEqToSHoWap4fTl4QSZpyhzxLy6uSNRwg1u20xVSlEAPee2Z+efzZQtA0I9bRTkcAMbzH65+sWKgMsEMJoHrqlCr7FvX4c+UMW9sWlRLoH52oN3ilCQNy2beI8mWqE4gAGxD4aA= diff --git a/dot_tmux/plugins/tmux-yank/executable_citest b/dot_tmux/plugins/tmux-yank/executable_citest new file mode 100644 index 0000000..f8e17f5 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/executable_citest @@ -0,0 +1,30 @@ +#!/bin/bash + +set -euo pipefail + +cd "$(dirname "$0")" + +bash_scripts=( + yank.tmux + scripts/*.sh +) + +set -x +docker run \ + --rm \ + --volume="${PWD}:/mnt:ro" \ + --workdir="/mnt" \ + bash:latest \ + bash -Dn "${bash_scripts[@]}" + +docker run \ + --rm \ + --volume="${PWD}:/mnt:ro" \ + --workdir="/mnt" \ + koalaman/shellcheck:stable \ + --shell=bash \ + --external-sources \ + --color=always \ + "${bash_scripts[@]}" + +# EOF diff --git a/dot_tmux/plugins/tmux-yank/executable_yank.tmux b/dot_tmux/plugins/tmux-yank/executable_yank.tmux new file mode 100644 index 0000000..3003974 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/executable_yank.tmux @@ -0,0 +1,92 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SCRIPTS_DIR="${CURRENT_DIR}/scripts" +HELPERS_DIR="${CURRENT_DIR}/scripts" + +# shellcheck source=scripts/helpers.sh +source "${HELPERS_DIR}/helpers.sh" + +clipboard_copy_without_newline_command() { + local copy_command="$1" + printf "tr -d '\\n' | %s" "$copy_command" +} + +set_error_bindings() { + local key_bindings key + key_bindings="$(yank_key) $(put_key) $(yank_put_key)" + for key in $key_bindings; do + if tmux_is_at_least 2.4; then + tmux bind-key -T copy-mode-vi "$key" send-keys -X copy-pipe-and-cancel "tmux display-message 'Error! tmux-yank dependencies not installed!'" + tmux bind-key -T copy-mode "$key" send-keys -X copy-pipe-and-cancel "tmux display-message 'Error! tmux-yank dependencies not installed!'" + else + tmux bind-key -t vi-copy "$key" copy-pipe "tmux display-message 'Error! tmux-yank dependencies not installed!'" + tmux bind-key -t emacs-copy "$key" copy-pipe "tmux display-message 'Error! tmux-yank dependencies not installed!'" + fi + done +} + +error_handling_if_command_not_present() { + local copy_command="$1" + if [ -z "$copy_command" ]; then + set_error_bindings + exit 0 + fi +} + +# `yank_without_newline` binding isn't intended to be used by the user. It is +# a helper for `copy_line` command. +set_copy_mode_bindings() { + local copy_command="$1" + local copy_wo_newline_command + copy_wo_newline_command="$(clipboard_copy_without_newline_command "$copy_command")" + local copy_command_mouse + copy_command_mouse="$(clipboard_copy_command "true")" + if tmux_is_at_least 2.4; then + tmux bind-key -T copy-mode-vi "$(yank_key)" send-keys -X "$(yank_action)" "$copy_command" + tmux bind-key -T copy-mode-vi "$(put_key)" send-keys -X copy-pipe-and-cancel "tmux paste-buffer -p" + tmux bind-key -T copy-mode-vi "$(yank_put_key)" send-keys -X copy-pipe-and-cancel "$copy_command; tmux paste-buffer -p" + tmux bind-key -T copy-mode-vi "$(yank_wo_newline_key)" send-keys -X "$(yank_action)" "$copy_wo_newline_command" + if [[ "$(yank_with_mouse)" == "on" ]]; then + tmux bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X "$(yank_action)" "$copy_command_mouse" + fi + + tmux bind-key -T copy-mode "$(yank_key)" send-keys -X "$(yank_action)" "$copy_command" + tmux bind-key -T copy-mode "$(put_key)" send-keys -X copy-pipe-and-cancel "tmux paste-buffer -p" + tmux bind-key -T copy-mode "$(yank_put_key)" send-keys -X copy-pipe-and-cancel "$copy_command; tmux paste-buffer -p" + tmux bind-key -T copy-mode "$(yank_wo_newline_key)" send-keys -X "$(yank_action)" "$copy_wo_newline_command" + if [[ "$(yank_with_mouse)" == "on" ]]; then + tmux bind-key -T copy-mode MouseDragEnd1Pane send-keys -X "$(yank_action)" "$copy_command_mouse" + fi + else + tmux bind-key -t vi-copy "$(yank_key)" copy-pipe "$copy_command" + tmux bind-key -t vi-copy "$(put_key)" copy-pipe "tmux paste-buffer -p" + tmux bind-key -t vi-copy "$(yank_put_key)" copy-pipe "$copy_command; tmux paste-buffer -p" + tmux bind-key -t vi-copy "$(yank_wo_newline_key)" copy-pipe "$copy_wo_newline_command" + if [[ "$(yank_with_mouse)" == "on" ]]; then + tmux bind-key -t vi-copy MouseDragEnd1Pane copy-pipe "$copy_command_mouse" + fi + + tmux bind-key -t emacs-copy "$(yank_key)" copy-pipe "$copy_command" + tmux bind-key -t emacs-copy "$(put_key)" copy-pipe "tmux paste-buffer -p" + tmux bind-key -t emacs-copy "$(yank_put_key)" copy-pipe "$copy_command; tmux paste-buffer -p" + tmux bind-key -t emacs-copy "$(yank_wo_newline_key)" copy-pipe "$copy_wo_newline_command" + if [[ "$(yank_with_mouse)" == "on" ]]; then + tmux bind-key -t emacs-copy MouseDragEnd1Pane copy-pipe "$copy_command_mouse" + fi + fi +} + +set_normal_bindings() { + tmux bind-key "$(yank_line_key)" run-shell -b "$SCRIPTS_DIR/copy_line.sh" + tmux bind-key "$(yank_pane_pwd_key)" run-shell -b "$SCRIPTS_DIR/copy_pane_pwd.sh" +} + +main() { + local copy_command + copy_command="$(clipboard_copy_command)" + error_handling_if_command_not_present "$copy_command" + set_copy_mode_bindings "$copy_command" + set_normal_bindings +} +main diff --git a/dot_tmux/plugins/tmux-yank/scripts/executable_copy_line.sh b/dot_tmux/plugins/tmux-yank/scripts/executable_copy_line.sh new file mode 100644 index 0000000..20a70e1 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/scripts/executable_copy_line.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +HELPERS_DIR="$CURRENT_DIR" +TMUX_COPY_MODE="" + +REMOTE_SHELL_WAIT_TIME="0.4" + +# shellcheck source=scripts/helpers.sh +source "${HELPERS_DIR}/helpers.sh" + +# sets a TMUX_COPY_MODE that is used as a global variable +get_tmux_copy_mode() { + TMUX_COPY_MODE="$(tmux show-option -gwv mode-keys)" +} + +# The command when on ssh with latency. To make it work in this case too, +# sleep is added. +add_sleep_for_remote_shells() { + local pane_command + pane_command="$(tmux display-message -p '#{pane_current_command}')" + if [[ $pane_command =~ (ssh|mosh) ]]; then + sleep "$REMOTE_SHELL_WAIT_TIME" + fi +} + +go_to_the_beginning_of_current_line() { + if [ "$(shell_mode)" == "emacs" ]; then + tmux send-key 'C-a' + else + tmux send-key 'Escape' '0' + fi +} + +enter_tmux_copy_mode() { + tmux copy-mode +} + +start_tmux_selection() { + if tmux_is_at_least 2.4; then + tmux send -X begin-selection + elif [ "$TMUX_COPY_MODE" == "vi" ]; then + # vi copy mode + tmux send-key 'Space' + else + # emacs copy mode + tmux send-key 'C-Space' + fi +} + +# works when command spans accross multiple lines +end_of_line_in_copy_mode() { + if tmux_is_at_least 2.4; then + tmux send -X -N 150 'cursor-down' # 'down' key. 'vi' mode is faster so we're + # jumping more lines than emacs. + tmux send -X 'end-of-line' # End of line (just in case we are already at the last line). + tmux send -X 'previous-word' # Beginning of the previous word. + tmux send -X 'next-word-end' # End of next word. + elif [ "$TMUX_COPY_MODE" == "vi" ]; then + # vi copy mode + # This sequence of keys consistently selects multiple lines + tmux send-key '150' # Go to the bottom of scrollback buffer by using + tmux send-key 'j' # 'down' key. 'vi' mode is faster so we're + # jumping more lines than emacs. + tmux send-key '$' # End of line (just in case we are already at the last line). + tmux send-key 'b' # Beginning of the previous word. + tmux send-key 'e' # End of next word. + else + # emacs copy mode + for ((c = 1; c <= '30'; c++)); do # go to the bottom of scrollback buffer + tmux send-key 'C-n' + done + tmux send-key 'C-e' + tmux send-key 'M-b' + tmux send-key 'M-f' + fi +} + +yank_to_clipboard() { + if tmux_is_at_least 2.4; then + # shellcheck disable=SC2119 + tmux send -X copy-pipe-and-cancel "$(clipboard_copy_command)" + else + tmux send-key "$(yank_wo_newline_key)" + fi +} + +go_to_the_end_of_current_line() { + if [ "$(shell_mode)" == "emacs" ]; then + tmux send-keys 'C-e' + else + tmux send-keys '$' 'a' + fi +} + +yank_current_line() { + go_to_the_beginning_of_current_line + add_sleep_for_remote_shells + enter_tmux_copy_mode + start_tmux_selection + end_of_line_in_copy_mode + yank_to_clipboard + go_to_the_end_of_current_line + display_message 'Line copied to clipboard!' +} + +main() { + get_tmux_copy_mode + yank_current_line +} +main diff --git a/dot_tmux/plugins/tmux-yank/scripts/executable_copy_pane_pwd.sh b/dot_tmux/plugins/tmux-yank/scripts/executable_copy_pane_pwd.sh new file mode 100644 index 0000000..1db321f --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/scripts/executable_copy_pane_pwd.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +HELPERS_DIR="$CURRENT_DIR" + +# shellcheck source=scripts/helpers.sh +source "${HELPERS_DIR}/helpers.sh" + +pane_current_path() { + tmux display -p -F "#{pane_current_path}" +} + +display_notice() { + display_message 'PWD copied to clipboard!' +} + +main() { + local copy_command + local payload + # shellcheck disable=SC2119 + copy_command="$(clipboard_copy_command)" + payload="$(pane_current_path | tr -d '\n')" + # $copy_command below should not be quoted + echo "$payload" | $copy_command + tmux set-buffer "$payload" + display_notice +} +main diff --git a/dot_tmux/plugins/tmux-yank/scripts/helpers.sh b/dot_tmux/plugins/tmux-yank/scripts/helpers.sh new file mode 100644 index 0000000..66beeec --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/scripts/helpers.sh @@ -0,0 +1,208 @@ +#!bash +# shellcheck disable=SC2239 + +yank_line="y" +yank_line_option="@yank_line" + +yank_pane_pwd="Y" +yank_pane_pwd_option="@yank_pane_pwd" + +yank_default="y" +yank_option="@copy_mode_yank" + +put_default="Y" +put_option="@copy_mode_put" + +yank_put_default="M-y" +yank_put_option="@copy_mode_yank_put" + +yank_wo_newline_default="!" +yank_wo_newline_option="@copy_mode_yank_wo_newline" + +yank_selection_default="clipboard" +yank_selection_option="@yank_selection" + +yank_selection_mouse_default="primary" +yank_selection_mouse_option="@yank_selection_mouse" + +yank_with_mouse_default="on" +yank_with_mouse_option="@yank_with_mouse" + +yank_action_default="copy-pipe-and-cancel" +yank_action_option="@yank_action" + +shell_mode_default="emacs" +shell_mode_option="@shell_mode" + +custom_copy_command_default="" +custom_copy_command_option="@custom_copy_command" + +override_copy_command_default="" +override_copy_command_option="@override_copy_command" + +# helper functions +get_tmux_option() { + local option="$1" + local default_value="$2" + local option_value + option_value=$(tmux show-option -gqv "$option") + if [ -z "$option_value" ]; then + echo "$default_value" + else + echo "$option_value" + fi +} + +yank_line_key() { + get_tmux_option "$yank_line_option" "$yank_line" +} + +yank_pane_pwd_key() { + get_tmux_option "$yank_pane_pwd_option" "$yank_pane_pwd" +} + +yank_key() { + get_tmux_option "$yank_option" "$yank_default" +} + +put_key() { + get_tmux_option "$put_option" "$put_default" +} + +yank_put_key() { + get_tmux_option "$yank_put_option" "$yank_put_default" +} + +yank_wo_newline_key() { + get_tmux_option "$yank_wo_newline_option" "$yank_wo_newline_default" +} + +yank_selection() { + get_tmux_option "$yank_selection_option" "$yank_selection_default" +} + +yank_selection_mouse() { + get_tmux_option "$yank_selection_mouse_option" "$yank_selection_mouse_default" +} + +yank_with_mouse() { + get_tmux_option "$yank_with_mouse_option" "$yank_with_mouse_default" +} + +yank_action() { + get_tmux_option "$yank_action_option" "$yank_action_default" +} + +shell_mode() { + get_tmux_option "$shell_mode_option" "$shell_mode_default" +} + +custom_copy_command() { + get_tmux_option "$custom_copy_command_option" "$custom_copy_command_default" +} + +override_copy_command() { + get_tmux_option "$override_copy_command_option" "$override_copy_command_default" +} +# Ensures a message is displayed for 5 seconds in tmux prompt. +# Does not override the 'display-time' tmux option. +display_message() { + local message="$1" + + # display_duration defaults to 5 seconds, if not passed as an argument + if [ "$#" -eq 2 ]; then + local display_duration="$2" + else + local display_duration="5000" + fi + + # saves user-set 'display-time' option + local saved_display_time + saved_display_time=$(get_tmux_option "display-time" "750") + + # sets message display time to 5 seconds + tmux set-option -gq display-time "$display_duration" + + # displays message + tmux display-message "$message" + + # restores original 'display-time' value + tmux set-option -gq display-time "$saved_display_time" +} + +command_exists() { + local command="$1" + type "$command" >/dev/null 2>&1 +} + +clipboard_copy_command() { + local mouse="${1:-false}" + # installing reattach-to-user-namespace is recommended on OS X + if [ -n "$(override_copy_command)" ]; then + override_copy_command + elif command_exists "pbcopy"; then + if command_exists "reattach-to-user-namespace"; then + echo "reattach-to-user-namespace pbcopy" + else + echo "pbcopy" + fi + elif command_exists "clip.exe"; then # WSL clipboard command + echo "cat | clip.exe" + elif command_exists "wl-copy"; then # wl-clipboard: Wayland clipboard utilities + echo "wl-copy" + elif command_exists "xsel"; then + local xsel_selection + if [[ $mouse == "true" ]]; then + xsel_selection="$(yank_selection_mouse)" + else + xsel_selection="$(yank_selection)" + fi + echo "xsel -i --$xsel_selection" + elif command_exists "xclip"; then + local xclip_selection + if [[ $mouse == "true" ]]; then + xclip_selection="$(yank_selection_mouse)" + else + xclip_selection="$(yank_selection)" + fi + echo "xclip -selection $xclip_selection" + elif command_exists "putclip"; then # cygwin clipboard command + echo "putclip" + elif [ -n "$(custom_copy_command)" ]; then + custom_copy_command + fi +} + +# Cache the TMUX version for speed. +tmux_version="$(tmux -V | cut -d ' ' -f 2 | sed 's/next-//')" + +tmux_is_at_least() { + if [[ $tmux_version == "$1" ]] || [[ $tmux_version == master ]]; then + return 0 + fi + + local i + local -a current_version wanted_version + IFS='.' read -ra current_version <<<"$tmux_version" + IFS='.' read -ra wanted_version <<<"$1" + + # fill empty fields in current_version with zeros + for ((i = ${#current_version[@]}; i < ${#wanted_version[@]}; i++)); do + current_version[i]=0 + done + + # fill empty fields in wanted_version with zeros + for ((i = ${#wanted_version[@]}; i < ${#current_version[@]}; i++)); do + wanted_version[i]=0 + done + + for ((i = 0; i < ${#current_version[@]}; i++)); do + if ((10#${current_version[i]} < 10#${wanted_version[i]})); then + return 1 + fi + if ((10#${current_version[i]} > 10#${wanted_version[i]})); then + return 0 + fi + done + return 0 +} diff --git a/dot_tmux/plugins/tmux-yank/vagrant_provisioning.sh b/dot_tmux/plugins/tmux-yank/vagrant_provisioning.sh new file mode 100644 index 0000000..c093d29 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/vagrant_provisioning.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +sudo apt-get update +sudo apt-get install -y git-core expect vim xclip +sudo apt-get install -y python-software-properties software-properties-common + +# install latest Tmux 1.9a +sudo add-apt-repository -y ppa:pi-rho/dev +sudo apt-get update +sudo apt-get install -y tmux=1.9a-1~ppa1~p + +# configure X11 for xclip testing +echo "export DISPLAY='IP:0.0'" >>/home/vagrant/.bashrc diff --git a/dot_tmux/plugins/tmux-yank/video/README.md b/dot_tmux/plugins/tmux-yank/video/README.md new file mode 100644 index 0000000..97f3056 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/video/README.md @@ -0,0 +1,7 @@ +## Tmux yank screencast + +This directory contains docs used for creating +[tmux yank screencast](https://vimeo.com/102039099). + +- `script.md` - this file contains a script and a voiceover used to produce the + screencast diff --git a/dot_tmux/plugins/tmux-yank/video/screencast_img.png b/dot_tmux/plugins/tmux-yank/video/screencast_img.png new file mode 100644 index 0000000..3bbedd2 Binary files /dev/null and b/dot_tmux/plugins/tmux-yank/video/screencast_img.png differ diff --git a/dot_tmux/plugins/tmux-yank/video/script.md b/dot_tmux/plugins/tmux-yank/video/script.md new file mode 100644 index 0000000..e401aa4 --- /dev/null +++ b/dot_tmux/plugins/tmux-yank/video/script.md @@ -0,0 +1,204 @@ +# Tmux yank screencast script + +1 - Intro - what's the plugin about +=================================== +Actions +------- +- none, just clear screen + +Script +------ +In this screencast we'll demo a tmux yank plugin. + +This plugin enables you to copy some text from tmux to the system clipboard, +along with some extra functionality we'll show. +It was made to complement tmux copycat plugin which we'll also be using for +selection in this screencast. + +2 - problems with vanilla tmux and `y` +============================== +Actions +------- +- $ echo 'example url https://github.com/tmux-plugins/tmux-yank' +- highlight url +- enter +- paste url + +- remove url +- highlight url again +- 'y' +- paste with cmd + v + +Script +------ +Let's show a problem scenario you might be having with tmux. + +I'll generate some example output with a url in the terminal. + +Okay, now I want to copy that url and open it in the browser. +By using tmux copycat saved search I'll quickly select the url. + +I'll press enter, a "bajnding" for copy. +I can now paste it in tmux by pressing prefix + right angle bracket. + +That works, but there's a problem. Tmux paste works only within tmux. Pressing +prefix + right angle bracket won't work in the browser where I actually want the +above url to be. + + +Ideally, when I copy some text in tmux, I want it to be available for paste +anywhere on the system with control-v or command-v if I'm on a Mac. + +Enter tmux-yank which enables just that. +I'll select the url again. + +Tmux-yank provides a convenient "bajnding" so that pressing 'y' in copy mode +copies the text and makes it available in system clipboard. + +I'm on a mac so I'll press command-v and there you have you have it. +It goes without saying that this paste will work in the browser. + + +Personally, I use tmux-yank copying all the time so I don't have to think in +terms of being in tmux versus working with the rest of the system. + +And also, this way I can avoid tmux default paste binding 'prefix + right angle +bracket' because it is a bit clunky and unintuitive. + +3 - showing 'ctrl-y' +==================== +Actions +------- +- git status -sb (file1.txt, file2.txt, file3.txt) +- git add +- highlight last file +- y +- paste and enter to git add a file + +- clear screen +- git status -sb +- git add +- highlight last file +- ctrl-y and git add a file + +- cmd - v + +Script +------ +Let's show another feature. + +I'll invoke git status command for the project I'm in. +Now I want to git add only the last file. + +I'll select the last file, yank and paste. + +Do you think we can optimize this? + +Often with tmux there's a need to copy a selection, and paste it to the command +line immediately. + +Tmux-yank provides a so called 'put selection' command. Let's demo it. + +I'll highlight another git status file and press control-y. +The selection is immediately 'put' to the command line. That's one step, instead +of two. + + +A nice side-effect of 'put selection' command is that it preserves the system +clipboard content. +If I press command-v now you'll see that the clipboard still contains the +previous entry. 'put selection' command didn't overwrite it. + +4. show 'line yank' +=================== +Actions +------- +- clear pane scrollback +- split window +- echo 'some command' +- ctrl-p to show the last command +- prefix + y + +- go the the pane on the right +- cmd - v + +Script +------ +The last tmux-yank feature I'd like to show is 'line yank'. + +It enables you to quickly copy the current command line to system clipoard. +The nice thing is, it also works for commands that strech multiple lines. + +But here's the basic example. I'll write a simple command. + +Okay, that works. Now, I want to execute that same command in the pane on the +right. I could of course type the command again, but that's tedious and I could +make a typo. + +Another solution is mouse selection, but that's just slow and lame. + + +I'll use the 'line yank' feature. +I'll press prefix + 'y' and the command is copied. Notice there were no changes +to the command itself - it is intact. + +In the second pane on the right I can paste the line with command - v. + +5. show 'line yank' with the production server +============================================== +Actions +------- +- left pane - local psql console +- right pane - psql console on developsta +- prepared create_table command on the left +- execute the command, it's ok +- show the command again +- show that mouse selection is innefective +- prefix + y + +- switch to right pane +- paste +- enter + +Script +------ +One scenario where I find line yank feature really useful is when I have to +execute a command on the production server. + +Here I have the local environment in the left pane, and I'm connected to +the production server in the right pane. + +The task I want to perform is creating a database table on the +production server. +Frankly, I feel hesitatnt to type that command straight on production. + +I'd rather first try and debug it locally, and then execute it on production. + +Let's do that then. I'll open a database console locally and type the command. + + +Oh, it looks like I have a typo. It's good I tried this locally first. + +Ok, the command works and is now ready. How do I now run in on production? +Typing this again, with the possibility of making a typo is not an option. +Let's try mouse selection. + +Hm, that won't work either. It seems I can't scope mouse +selection to the left pane. + +Let's now try line yank with prefix + 'y'. +Notice we're copying a multi-line command. + +I'll paste it in the right pane. + +That looks ok, so I'll execute it.. and it's good. + +6. Outro +======== +Actions +------- +- just a blank screen + +Script +------ +That's it for this screencast. I hope you'll find tmux-yank useful. diff --git a/dot_tmux/plugins/tpm/CHANGELOG.md b/dot_tmux/plugins/tpm/CHANGELOG.md new file mode 100644 index 0000000..a9ce81e --- /dev/null +++ b/dot_tmux/plugins/tpm/CHANGELOG.md @@ -0,0 +1,86 @@ +# Changelog + +### master + +### v3.1.0, 2023-01-03 +- upgrade to new version of `tmux-test` +- bug: when using `emacs` copy mode, Enter does not quit screen after tpm + installation/update. Fix by making `Escape` the key for emacs mode. +- add a doc with troubleshooting instructions +- add `.gitattributes` file that forces linefeed characters (classic `\n`) as + line endings - helps with misconfigured git on windows/cygwin +- readme update: announce Cygwin support +- un-deprecate old plugin definition syntax: `set -g @tpm_plugins` +- More stuff, check `git log`. + +### v3.0.0, 2015-08-03 +- refactor `shared_set_tpm_path_constant` function +- move all instructions to `docs/` dir +- add `bin/install_plugins` cli executable script +- improved test runner function +- switch to using [tmux-test](https://github.com/tmux-plugins/tmux-test) + framework +- add `bin/update_plugins` cli executable script +- refactor test `expect` scripts, make them simpler and ensure they properly + assert expectations +- refactor code that sets 'TMUX_PLUGIN_MANAGER_PATH' global env var +- stop using global variable for 'tpm path' +- support defining plugins via `set -g @plugin` in sourced files as well + +### v2.0.0, 2015-07-07 +- enable overriding default key bindings +- start using `C-c` to clear screen +- add uninstall/clean procedure and keybinding (prefix+alt+u) (@chilicuil) +- add new `set @plugin 'repo'` plugin definition syntax (@chilicuil) +- revert back to using `-g` flag in new plugin definition syntax +- permit leading whitespace with new plugin definition syntax (thanks @chilicuil) +- make sure `TMUX_PLUGIN_MANAGER_PATH` always has trailng slash +- ensure old/deprecated plugin syntax `set -g @tpm_plugins` works alongside new + `set -g @plugin` syntax + +### v1.2.2, 2015-02-08 +- set GIT_TERMINAL_PROMPT=0 when doing `git clone`, `pull` or `submodule update` + to ensure git does not prompt for username/password in any case + +### v1.2.1, 2014-11-21 +- change the way plugin name is expanded. It now uses the http username + and password by default, like this: `https://git::@github.com/`. This prevents + username and password prompt (and subsequently tmux install hanging) with old + git versions. Fixes #7. + +### v1.2.0, 2014-11-20 +- refactor tests so they can be used on travis +- add travis.yml, add travis badge to the readme + +### v1.1.0, 2014-11-19 +- if the plugin is not downloaded do not source it +- remove `PLUGINS.md`, an obsolete list of plugins +- update readme with instructions about uninstalling plugins +- tilde char and `$HOME` in `TMUX_SHARED_MANAGER_PATH` couldn't be used because + they are just plain strings. Fixing the problem by manually expanding them. +- bugfix: fragile `*.tmux` file globbing (@majutsushi) + +### v1.0.0, 2014-08-05 +- update readme because of github organization change to + [tmux-plugins](https://github.com/tmux-plugins) +- update tests to pass +- update README to suggest different first plugin +- update list of plugins in the README +- remove README 'about' section +- move key binding to the main file. Delete `key_binding.sh`. +- rename `display_message` -> `echo_message` +- installing plugins installs just new plugins. Already installed plugins aren't + updated. +- add 'update plugin' binding and functionality +- add test for updating a plugin + +### v0.0.2, 2014-07-17 +- run all *.tmux plugin files as executables +- fix all redirects to /dev/null +- fix bug: TPM shared path is created before sync (cloning plugins from github + is done) +- add test suite running in Vagrant +- add Tmux version check. `TPM` won't run if Tmux version is less than 1.9. + +### v0.0.1, 2014-05-21 +- get TPM up and running diff --git a/dot_tmux/plugins/tpm/HOW_TO_PLUGIN.md b/dot_tmux/plugins/tpm/HOW_TO_PLUGIN.md new file mode 100644 index 0000000..9901619 --- /dev/null +++ b/dot_tmux/plugins/tpm/HOW_TO_PLUGIN.md @@ -0,0 +1,2 @@ +Instructions moved to +[docs/how_to_create_plugin.md](docs/how_to_create_plugin.md). diff --git a/dot_tmux/plugins/tpm/LICENSE.md b/dot_tmux/plugins/tpm/LICENSE.md new file mode 100644 index 0000000..1222865 --- /dev/null +++ b/dot_tmux/plugins/tpm/LICENSE.md @@ -0,0 +1,20 @@ +MIT license +Copyright (C) 2014 Bruno Sutic + +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/dot_tmux/plugins/tpm/README.md b/dot_tmux/plugins/tpm/README.md new file mode 100644 index 0000000..2371863 --- /dev/null +++ b/dot_tmux/plugins/tpm/README.md @@ -0,0 +1,101 @@ +# Tmux Plugin Manager + +[![Build Status](https://travis-ci.org/tmux-plugins/tpm.svg?branch=master)](https://travis-ci.org/tmux-plugins/tpm) + +Installs and loads `tmux` plugins. + +Tested and working on Linux, OSX, and Cygwin. + +See list of plugins [here](https://github.com/tmux-plugins/list). + +### Installation + +Requirements: `tmux` version 1.9 (or higher), `git`, `bash`. + +Clone TPM: + +```bash +git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm +``` + +Put this at the bottom of `~/.tmux.conf` (`$XDG_CONFIG_HOME/tmux/tmux.conf` +works too): + +```bash +# List of plugins +set -g @plugin 'tmux-plugins/tpm' +set -g @plugin 'tmux-plugins/tmux-sensible' + +# Other examples: +# set -g @plugin 'github_username/plugin_name' +# set -g @plugin 'github_username/plugin_name#branch' +# set -g @plugin 'git@github.com:user/plugin' +# set -g @plugin 'git@bitbucket.com:user/plugin' + +# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) +run '~/.tmux/plugins/tpm/tpm' +``` + +Reload TMUX environment so TPM is sourced: + +```bash +# type this in terminal if tmux is already running +tmux source ~/.tmux.conf +``` + +That's it! + +### Installing plugins + +1. Add new plugin to `~/.tmux.conf` with `set -g @plugin '...'` +2. Press `prefix` + I (capital i, as in **I**nstall) to fetch the plugin. + +You're good to go! The plugin was cloned to `~/.tmux/plugins/` dir and sourced. + +### Uninstalling plugins + +1. Remove (or comment out) plugin from the list. +2. Press `prefix` + alt + u (lowercase u as in **u**ninstall) to remove the plugin. + +All the plugins are installed to `~/.tmux/plugins/` so alternatively you can +find plugin directory there and remove it. + +### Key bindings + +`prefix` + I +- Installs new plugins from GitHub or any other git repository +- Refreshes TMUX environment + +`prefix` + U +- updates plugin(s) + +`prefix` + alt + u +- remove/uninstall plugins not on the plugin list + +### Docs + +- [Help, tpm not working](docs/tpm_not_working.md) - problem solutions + +More advanced features and instructions, regular users probably do not need +this: + +- [How to create a plugin](docs/how_to_create_plugin.md). It's easy. +- [Managing plugins via the command line](docs/managing_plugins_via_cmd_line.md) +- [Changing plugins install dir](docs/changing_plugins_install_dir.md) +- [Automatic TPM installation on a new machine](docs/automatic_tpm_installation.md) + +### Tests + +Tests for this project run on [Travis CI](https://travis-ci.org/tmux-plugins/tpm). + +When run locally, [vagrant](https://www.vagrantup.com/) is required. +Run tests with: + +```bash +# within project directory +./run_tests +``` + +### License + +[MIT](LICENSE.md) diff --git a/dot_tmux/plugins/tpm/bin/executable_clean_plugins b/dot_tmux/plugins/tpm/bin/executable_clean_plugins new file mode 100644 index 0000000..12f8730 --- /dev/null +++ b/dot_tmux/plugins/tpm/bin/executable_clean_plugins @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# Script intended for use via the command line. +# +# `.tmux.conf` needs to be set for TPM. Tmux has to be installed on the system, +# but does not need to be started in order to run this script. + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SCRIPTS_DIR="$CURRENT_DIR/../scripts" + +main() { + "$SCRIPTS_DIR/clean_plugins.sh" # has correct exit code +} +main diff --git a/dot_tmux/plugins/tpm/bin/executable_install_plugins b/dot_tmux/plugins/tpm/bin/executable_install_plugins new file mode 100644 index 0000000..c66b15b --- /dev/null +++ b/dot_tmux/plugins/tpm/bin/executable_install_plugins @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# Script intended for use via the command line. +# +# `.tmux.conf` needs to be set for TPM. Tmux has to be installed on the system, +# but does not need to be started in order to run this script. + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SCRIPTS_DIR="$CURRENT_DIR/../scripts" + +main() { + "$SCRIPTS_DIR/install_plugins.sh" # has correct exit code +} +main diff --git a/dot_tmux/plugins/tpm/bin/executable_update_plugins b/dot_tmux/plugins/tpm/bin/executable_update_plugins new file mode 100644 index 0000000..30a5646 --- /dev/null +++ b/dot_tmux/plugins/tpm/bin/executable_update_plugins @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Script intended for use via the command line. +# +# `.tmux.conf` needs to be set for TPM. Tmux has to be installed on the system, +# but does not need to be started in order to run this script. + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SCRIPTS_DIR="$CURRENT_DIR/../scripts" +PROGRAM_NAME="$0" + +if [ $# -eq 0 ]; then + echo "usage:" + echo " $PROGRAM_NAME all update all plugins" + echo " $PROGRAM_NAME tmux-foo update plugin 'tmux-foo'" + echo " $PROGRAM_NAME tmux-bar tmux-baz update multiple plugins" + exit 1 +fi + +main() { + "$SCRIPTS_DIR/update_plugin.sh" --shell-echo "$*" # has correct exit code +} +main "$*" + diff --git a/dot_tmux/plugins/tpm/bindings/executable_clean_plugins b/dot_tmux/plugins/tpm/bindings/executable_clean_plugins new file mode 100644 index 0000000..9a0d5d7 --- /dev/null +++ b/dot_tmux/plugins/tpm/bindings/executable_clean_plugins @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# Tmux key-binding script. +# Scripts intended to be used via the command line are in `bin/` directory. + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SCRIPTS_DIR="$CURRENT_DIR/../scripts" +HELPERS_DIR="$SCRIPTS_DIR/helpers" + +source "$HELPERS_DIR/tmux_echo_functions.sh" +source "$HELPERS_DIR/tmux_utils.sh" + +main() { + reload_tmux_environment + "$SCRIPTS_DIR/clean_plugins.sh" --tmux-echo >/dev/null 2>&1 + reload_tmux_environment + end_message +} +main diff --git a/dot_tmux/plugins/tpm/bindings/executable_install_plugins b/dot_tmux/plugins/tpm/bindings/executable_install_plugins new file mode 100644 index 0000000..3ade3c4 --- /dev/null +++ b/dot_tmux/plugins/tpm/bindings/executable_install_plugins @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# Tmux key-binding script. +# Scripts intended to be used via the command line are in `bin/` directory. + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SCRIPTS_DIR="$CURRENT_DIR/../scripts" +HELPERS_DIR="$SCRIPTS_DIR/helpers" + +source "$HELPERS_DIR/tmux_echo_functions.sh" +source "$HELPERS_DIR/tmux_utils.sh" + +main() { + reload_tmux_environment + "$SCRIPTS_DIR/install_plugins.sh" --tmux-echo >/dev/null 2>&1 + reload_tmux_environment + end_message +} +main diff --git a/dot_tmux/plugins/tpm/bindings/executable_update_plugins b/dot_tmux/plugins/tpm/bindings/executable_update_plugins new file mode 100644 index 0000000..28cc281 --- /dev/null +++ b/dot_tmux/plugins/tpm/bindings/executable_update_plugins @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +# Tmux key-binding script. +# Scripts intended to be used via the command line are in `bin/` directory. + +# This script: +# - shows a list of installed plugins +# - starts a prompt to enter the name of the plugin that will be updated + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SCRIPTS_DIR="$CURRENT_DIR/../scripts" +HELPERS_DIR="$SCRIPTS_DIR/helpers" + +source "$HELPERS_DIR/plugin_functions.sh" +source "$HELPERS_DIR/tmux_echo_functions.sh" +source "$HELPERS_DIR/tmux_utils.sh" + +display_plugin_update_list() { + local plugins="$(tpm_plugins_list_helper)" + tmux_echo "Installed plugins:" + tmux_echo "" + + for plugin in $plugins; do + # displaying only installed plugins + if plugin_already_installed "$plugin"; then + local plugin_name="$(plugin_name_helper "$plugin")" + tmux_echo " $plugin_name" + fi + done + + tmux_echo "" + tmux_echo "Type plugin name to update it." + tmux_echo "" + tmux_echo "- \"all\" - updates all plugins" + tmux_echo "- ENTER - cancels" +} + +update_plugin_prompt() { + tmux command-prompt -p 'plugin update:' " \ + send-keys C-c; \ + run-shell '$SCRIPTS_DIR/update_plugin_prompt_handler.sh %1'" +} + +main() { + reload_tmux_environment + display_plugin_update_list + update_plugin_prompt +} +main diff --git a/dot_tmux/plugins/tpm/docs/automatic_tpm_installation.md b/dot_tmux/plugins/tpm/docs/automatic_tpm_installation.md new file mode 100644 index 0000000..630573f --- /dev/null +++ b/dot_tmux/plugins/tpm/docs/automatic_tpm_installation.md @@ -0,0 +1,12 @@ +# Automatic tpm installation + +One of the first things we do on a new machine is cloning our dotfiles. Not everything comes with them though, so for example `tpm` most likely won't be installed. + +If you want to install `tpm` and plugins automatically when tmux is started, put the following snippet in `.tmux.conf` before the final `run '~/.tmux/plugins/tpm/tpm'`: + +``` +if "test ! -d ~/.tmux/plugins/tpm" \ + "run 'git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm && ~/.tmux/plugins/tpm/bin/install_plugins'" +``` + +This useful tip was submitted by @acr4 and narfman0. diff --git a/dot_tmux/plugins/tpm/docs/changing_plugins_install_dir.md b/dot_tmux/plugins/tpm/docs/changing_plugins_install_dir.md new file mode 100644 index 0000000..27de96d --- /dev/null +++ b/dot_tmux/plugins/tpm/docs/changing_plugins_install_dir.md @@ -0,0 +1,16 @@ +# Changing plugins install dir + +By default, TPM installs plugins in a subfolder named `plugins/` inside +`$XDG_CONFIG_HOME/tmux/` if a `tmux.conf` file was found at that location, or +inside `~/.tmux/` otherwise. + +You can change the install path by putting this in `.tmux.conf`: + + set-environment -g TMUX_PLUGIN_MANAGER_PATH '/some/other/path/' + +Tmux plugin manager initialization in `.tmux.conf` should also be updated: + + # initializes TMUX plugin manager in a new path + run /some/other/path/tpm/tpm + +Please make sure that the `run` line is at the very bottom of `.tmux.conf`. diff --git a/dot_tmux/plugins/tpm/docs/how_to_create_plugin.md b/dot_tmux/plugins/tpm/docs/how_to_create_plugin.md new file mode 100644 index 0000000..f7d9c13 --- /dev/null +++ b/dot_tmux/plugins/tpm/docs/how_to_create_plugin.md @@ -0,0 +1,108 @@ +# How to create Tmux plugins + +Creating a new plugin is easy. + +For demonstration purposes we'll create a simple plugin that lists all +installed TPM plugins. Yes, a plugin that lists plugins :) We'll bind that to +`prefix + T`. + +The source code for this example plugin can be found +[here](https://github.com/tmux-plugins/tmux-example-plugin). + +### 1. create a new git project + +TPM depends on git for downloading and updating plugins. + +To create a new git project: + + $ mkdir tmux_my_plugin + $ cd tmux_my_plugin + $ git init + +### 2. create a `*.tmux` plugin run file + +When it sources a plugin, TPM executes all `*.tmux` files in your plugins' +directory. That's how plugins are run. + +Create a plugin run file in plugin directory: + + $ touch my_plugin.tmux + $ chmod u+x my_plugin.tmux + +You can have more than one `*.tmux` file, and all will get executed. However, usually +you'll need just one. + +### 3. create a plugin key binding + +We want the behavior of the plugin to trigger when a user hits `prefix + T`. + +Key `T` is chosen because: + - it's "kind of" a mnemonic for `TPM` + - the key is not used by Tmux natively. Tmux man page, KEY BINDINGS section + contains a list of all the bindings Tmux uses. There's plenty of unused keys + and we don't want to override any of Tmux default key bindings. + +Open the plugin run file in your favorite text editor: + + $ vim my_plugin.tmux + # or + $ subl my_plugin.tmux + +Put the following content in the file: + + #!/usr/bin/env bash + + CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + tmux bind-key T run-shell "$CURRENT_DIR/scripts/tmux_list_plugins.sh" + +As you can see, plugin run file is a simple bash script that sets up the binding. + +When pressed, `prefix + T` will execute another shell script: +`tmux_list_plugins.sh`. That script should be in `scripts/` directory - +relative to the plugin run file. + + +### 4. listing plugins + +Now that we have the binding, let's create a script that's invoked with +`prefix + T`. + + $ mkdir scripts + $ touch scripts/tmux_list_plugins.sh + $ chmod u+x scripts/tmux_list_plugins.sh + +And here's the script content: + + #!/usr/bin/env bash + + # fetching the directory where plugins are installed + plugin_path="$(tmux show-env -g TMUX_PLUGIN_MANAGER_PATH | cut -f2 -d=)" + + # listing installed plugins + ls -1 "$plugin_path" + +### 5. try it out + +To see if this works, execute the plugin run file: + + $ ./my_plugin.tmux + +That should set up the key binding. Now hit `prefix + T` and see if it works. + +### 6. publish the plugin + +When everything is ready, push the plugin to an online git repository, +preferably GitHub. + +Other users can install your plugin by just adding plugin git URL to the +`@plugin` list in their `.tmux.conf`. + +If the plugin is on GitHub, your users will be able to use the shorthand of +`github_username/repository`. + +### Conclusion + +Hopefully, that was easy. As you can see, it's mostly shell scripting. + +You can use other scripting languages (ruby, python etc) but plain old shell +is preferred because of portability. diff --git a/dot_tmux/plugins/tpm/docs/managing_plugins_via_cmd_line.md b/dot_tmux/plugins/tpm/docs/managing_plugins_via_cmd_line.md new file mode 100644 index 0000000..7aefd7d --- /dev/null +++ b/dot_tmux/plugins/tpm/docs/managing_plugins_via_cmd_line.md @@ -0,0 +1,36 @@ +# Managing plugins via the command line + +Aside from tmux key bindings, TPM provides shell interface for managing plugins +via scripts located in [bin/](../bin/) directory. + +Tmux does not need to be started in order to run scripts (but it's okay if it +is). If you [changed tpm install dir](../docs/changing_plugins_install_dir.md) +in `.tmux.conf` that should work fine too. + +Prerequisites: + +- tmux installed on the system (doh) +- `.tmux.conf` set up for TPM + +### Installing plugins + +As usual, plugins need to be specified in `.tmux.conf`. Run the following +command to install plugins: + + ~/.tmux/plugins/tpm/bin/install_plugins + +### Updating plugins + +To update all installed plugins: + + ~/.tmux/plugins/tpm/bin/update_plugins all + +or update a single plugin: + + ~/.tmux/plugins/tpm/bin/update_plugins tmux-sensible + +### Removing plugins + +To remove plugins not on the plugin list: + + ~/.tmux/plugins/tpm/bin/clean_plugins diff --git a/dot_tmux/plugins/tpm/docs/tpm_not_working.md b/dot_tmux/plugins/tpm/docs/tpm_not_working.md new file mode 100644 index 0000000..6680291 --- /dev/null +++ b/dot_tmux/plugins/tpm/docs/tpm_not_working.md @@ -0,0 +1,102 @@ +# Help, tpm not working! + +Here's the list of issues users had with `tpm`: + +
+ +> Nothing works. `tpm` key bindings `prefix + I`, `prefix + U` not even + defined. + +Related [issue #22](https://github.com/tmux-plugins/tpm/issues/22) + +- Do you have required `tmux` version to run `tpm`?
+ Check `tmux` version with `$ tmux -V` command and make sure it's higher or + equal to the required version for `tpm` as stated in the readme. + +- ZSH tmux plugin might be causing issues.
+ If you have it installed, try disabling it and see if `tpm` works then. + +
+ +> Help, I'm using custom config file with `tmux -f /path/to/my_tmux.conf` +to start Tmux and for some reason plugins aren't loaded!? + +Related [issue #57](https://github.com/tmux-plugins/tpm/issues/57) + +`tpm` has a known issue when using custom config file with `-f` option. +The solution is to use alternative plugin definition syntax. Here are the steps +to make it work: + +1. remove all `set -g @plugin` lines from tmux config file +2. in the config file define the plugins in the following way: + + # List of plugins + set -g @tpm_plugins ' \ + tmux-plugins/tpm \ + tmux-plugins/tmux-sensible \ + tmux-plugins/tmux-resurrect \ + ' + + # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) + run '~/.tmux/plugins/tpm/tpm' + +3. Reload TMUX environment so TPM is sourced: `$ tmux source /path/to/my_tmux.conf` + +The plugins should now be working. + +
+ +> Weird sequence of characters show up when installing or updating plugins + +Related: [issue #25](https://github.com/tmux-plugins/tpm/issues/25) + +- This could be caused by [tmuxline.vim](https://github.com/edkolev/tmuxline.vim) + plugin. Uninstall it and see if things work. + +
+ +> "failed to connect to server" error when sourcing .tmux.conf + +Related: [issue #48](https://github.com/tmux-plugins/tpm/issues/48) + +- Make sure `tmux source ~/.tmux.conf` command is ran from inside `tmux`. + +
+ +> tpm not working: '~/.tmux/plugins/tpm/tpm' returned 2 (Windows / Cygwin) + +Related: [issue #81](https://github.com/tmux-plugins/tpm/issues/81) + +This issue is most likely caused by Windows line endings. For example, if you +have git's `core.autocrlf` option set to `true`, git will automatically convert +all the files to Windows line endings which might cause a problem. + +The solution is to convert all line ending to Unix newline characters. This +command handles that for all files under `.tmux/` dir (skips `.git` +subdirectories): + +```bash +find ~/.tmux -type d -name '.git*' -prune -o -type f -print0 | xargs -0 dos2unix +``` + +
+ +> '~/.tmux/plugins/tpm/tpm' returned 127 (on macOS, w/ tmux installed using brew) + +Related: [issue #67](https://github.com/tmux-plugins/tpm/issues/67) + +This problem is because tmux's `run-shell` command runs a shell which doesn't read from user configs, thus tmux installed in a brew prefix (e.g. `/usr/local/bin`) will not be found. + +The solution is to find your brew prefix + +```sh +> echo "$(brew --prefix)/bin" +/opt/homebrew/bin +``` + +And prepend it to the `PATH` environment variable +``` +set-environment -g PATH "/opt/homebrew/bin:/bin:/usr/bin" +``` + +before any `run-shell`/`run` commands in `~/.tmux.conf`. diff --git a/dot_tmux/plugins/tpm/dot_git/HEAD b/dot_tmux/plugins/tpm/dot_git/HEAD new file mode 100644 index 0000000..cb089cd --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/dot_tmux/plugins/tpm/dot_git/branches/.keep b/dot_tmux/plugins/tpm/dot_git/branches/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tpm/dot_git/config b/dot_tmux/plugins/tpm/dot_git/config new file mode 100644 index 0000000..e20a621 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/config @@ -0,0 +1,11 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[remote "origin"] + url = https://github.com/tmux-plugins/tpm + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "master"] + remote = origin + merge = refs/heads/master diff --git a/dot_tmux/plugins/tpm/dot_git/description b/dot_tmux/plugins/tpm/dot_git/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_applypatch-msg.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_applypatch-msg.sample new file mode 100644 index 0000000..a5d7b84 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_commit-msg.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_commit-msg.sample new file mode 100644 index 0000000..b58d118 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_fsmonitor-watchman.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_fsmonitor-watchman.sample new file mode 100644 index 0000000..23e856f --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_post-update.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_post-update.sample new file mode 100644 index 0000000..ec17ec1 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-applypatch.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-applypatch.sample new file mode 100644 index 0000000..4142082 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-commit.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-commit.sample new file mode 100644 index 0000000..e144712 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-merge-commit.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-merge-commit.sample new file mode 100644 index 0000000..399eab1 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-push.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-push.sample new file mode 100644 index 0000000..4ce688d --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-rebase.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-rebase.sample new file mode 100644 index 0000000..6cbef5c --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-receive.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-receive.sample new file mode 100644 index 0000000..a1fd29e --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_prepare-commit-msg.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_prepare-commit-msg.sample new file mode 100644 index 0000000..10fa14c --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_push-to-checkout.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_push-to-checkout.sample new file mode 100644 index 0000000..af5a0c0 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/dot_tmux/plugins/tpm/dot_git/hooks/executable_update.sample b/dot_tmux/plugins/tpm/dot_git/hooks/executable_update.sample new file mode 100644 index 0000000..c4d426b --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/hooks/executable_update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/dot_tmux/plugins/tpm/dot_git/index b/dot_tmux/plugins/tpm/dot_git/index new file mode 100644 index 0000000..2be1a2b Binary files /dev/null and b/dot_tmux/plugins/tpm/dot_git/index differ diff --git a/dot_tmux/plugins/tpm/dot_git/info/exclude b/dot_tmux/plugins/tpm/dot_git/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/dot_tmux/plugins/tpm/dot_git/logs/HEAD b/dot_tmux/plugins/tpm/dot_git/logs/HEAD new file mode 100644 index 0000000..c5bfd10 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/logs/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 99469c4a9b1ccf77fade25842dc7bafbc8ce9946 Simon Rieger 1699878640 +0100 clone: from https://github.com/tmux-plugins/tpm diff --git a/dot_tmux/plugins/tpm/dot_git/logs/refs/heads/master b/dot_tmux/plugins/tpm/dot_git/logs/refs/heads/master new file mode 100644 index 0000000..c5bfd10 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 99469c4a9b1ccf77fade25842dc7bafbc8ce9946 Simon Rieger 1699878640 +0100 clone: from https://github.com/tmux-plugins/tpm diff --git a/dot_tmux/plugins/tpm/dot_git/logs/refs/remotes/origin/HEAD b/dot_tmux/plugins/tpm/dot_git/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..c5bfd10 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 99469c4a9b1ccf77fade25842dc7bafbc8ce9946 Simon Rieger 1699878640 +0100 clone: from https://github.com/tmux-plugins/tpm diff --git a/dot_tmux/plugins/tpm/dot_git/objects/info/.keep b/dot_tmux/plugins/tpm/dot_git/objects/info/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tpm/dot_git/objects/pack/readonly_pack-973c4342f0207eb8e5df3976969ced25c0c9f270.idx b/dot_tmux/plugins/tpm/dot_git/objects/pack/readonly_pack-973c4342f0207eb8e5df3976969ced25c0c9f270.idx new file mode 100644 index 0000000..25aba2b Binary files /dev/null and b/dot_tmux/plugins/tpm/dot_git/objects/pack/readonly_pack-973c4342f0207eb8e5df3976969ced25c0c9f270.idx differ diff --git a/dot_tmux/plugins/tpm/dot_git/objects/pack/readonly_pack-973c4342f0207eb8e5df3976969ced25c0c9f270.pack b/dot_tmux/plugins/tpm/dot_git/objects/pack/readonly_pack-973c4342f0207eb8e5df3976969ced25c0c9f270.pack new file mode 100644 index 0000000..02c2301 Binary files /dev/null and b/dot_tmux/plugins/tpm/dot_git/objects/pack/readonly_pack-973c4342f0207eb8e5df3976969ced25c0c9f270.pack differ diff --git a/dot_tmux/plugins/tpm/dot_git/objects/pack/readonly_pack-973c4342f0207eb8e5df3976969ced25c0c9f270.rev b/dot_tmux/plugins/tpm/dot_git/objects/pack/readonly_pack-973c4342f0207eb8e5df3976969ced25c0c9f270.rev new file mode 100644 index 0000000..6e73ee5 Binary files /dev/null and b/dot_tmux/plugins/tpm/dot_git/objects/pack/readonly_pack-973c4342f0207eb8e5df3976969ced25c0c9f270.rev differ diff --git a/dot_tmux/plugins/tpm/dot_git/packed-refs b/dot_tmux/plugins/tpm/dot_git/packed-refs new file mode 100644 index 0000000..aae3407 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/packed-refs @@ -0,0 +1,24 @@ +# pack-refs with: peeled fully-peeled sorted +aeb196db5c13161defbac64314d47ca346b34826 refs/remotes/origin/fix-automatic-tpm-install +bfc7a2c2cbbbb0c448b23396bdb7bf088b8c6dc3 refs/remotes/origin/fix_emacs_continue_key +99469c4a9b1ccf77fade25842dc7bafbc8ce9946 refs/remotes/origin/master +e1bbcd6f8b7db9df823632d4140fb4bbd65798d3 refs/remotes/origin/travis_install_tmux_from_source +aee1fbc949e1f68db3d8da7ac1b9bee5b4ac1595 refs/tags/v0.0.1 +e29045e1db9ad6e1e9cf72ab59b78f0ec72cafb8 refs/tags/v0.0.2 +^e68e4d52e4d0acb0691fb99d07de922142cc6759 +d520c6a47a40dc1ab0e7799d95514c5aab000a8f refs/tags/v1.0.0 +^f44ae34d112beceead7f09994cb057fe5b136b57 +0794614b55ea7c9b7c07306e64a09b8ac1207a2e refs/tags/v1.1.0 +^604cca0e8ae0479b850bf62e8030a8f421513598 +1e65a591ab5972ff9072f2c07608ee1dd0b88eb7 refs/tags/v1.2.0 +^7c10afc0612f1d1c69837cbc65b20f22c864141d +92ba10978b6e9a7a767ed2ddb9c7190f9956789a refs/tags/v1.2.1 +^db8b06c509e44a60c4ec3132fc9839ebe1bbf08a +5957fe6b4644e75ba0740a94faf97307eb31046d refs/tags/v1.2.2 +^330176355013884fa04caf7fbac0df8be2349273 +79c45e42bf525de25a12689f3770ff1f1d30a1aa refs/tags/v2.0.0 +^35161668d986d83c46cdcf870cfc549431db9f8f +234002ad1c58e04b4e74853c7f1698874f69da60 refs/tags/v3.0.0 +^1ff32085b2b30956fbab58b1520d84d95f18d48d +c628645dfa7c4fc16acfb7a73c9d7a98697b472c refs/tags/v3.1.0 +^7bdb7ca33c9cc6440a600202b50142f401b6fe21 diff --git a/dot_tmux/plugins/tpm/dot_git/refs/heads/master b/dot_tmux/plugins/tpm/dot_git/refs/heads/master new file mode 100644 index 0000000..e69d6dc --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/refs/heads/master @@ -0,0 +1 @@ +99469c4a9b1ccf77fade25842dc7bafbc8ce9946 diff --git a/dot_tmux/plugins/tpm/dot_git/refs/remotes/origin/HEAD b/dot_tmux/plugins/tpm/dot_git/refs/remotes/origin/HEAD new file mode 100644 index 0000000..6efe28f --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_git/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/master diff --git a/dot_tmux/plugins/tpm/dot_git/refs/tags/.keep b/dot_tmux/plugins/tpm/dot_git/refs/tags/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tpm/dot_gitattributes b/dot_tmux/plugins/tpm/dot_gitattributes new file mode 100644 index 0000000..80772e4 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_gitattributes @@ -0,0 +1,9 @@ +# Force text files to have unix eols, so Windows/Cygwin does not break them +*.* eol=lf + +# These files are unfortunately not recognized as text files so +# explicitly listing them here +tpm eol=lf +bin/* eol=lf +bindings/* eol=lf +tests/* eol=lf diff --git a/dot_tmux/plugins/tpm/dot_gitignore b/dot_tmux/plugins/tpm/dot_gitignore new file mode 100644 index 0000000..8a94156 --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_gitignore @@ -0,0 +1,4 @@ +**/.vagrant/ +run_tests +tests/run_tests_in_isolation +tests/helpers/helpers.sh diff --git a/dot_tmux/plugins/tpm/dot_gitmodules b/dot_tmux/plugins/tpm/dot_gitmodules new file mode 100644 index 0000000..5e44e3c --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/tmux-test"] + path = lib/tmux-test + url = https://github.com/tmux-plugins/tmux-test.git diff --git a/dot_tmux/plugins/tpm/dot_travis.yml b/dot_tmux/plugins/tpm/dot_travis.yml new file mode 100644 index 0000000..ac45d8b --- /dev/null +++ b/dot_tmux/plugins/tpm/dot_travis.yml @@ -0,0 +1,19 @@ +# generic packages and tmux +before_install: + - sudo apt-get update + - sudo apt-get install -y git-core expect + - sudo apt-get install -y python-software-properties software-properties-common + - sudo apt-get install -y libevent-dev libncurses-dev + - git clone https://github.com/tmux/tmux.git + - cd tmux + - git checkout 2.0 + - sh autogen.sh + - ./configure && make && sudo make install + +install: + - git fetch --unshallow --recurse-submodules || git fetch --recurse-submodules + # manual `git clone` required for testing `tmux-test` plugin itself + - git clone https://github.com/tmux-plugins/tmux-test lib/tmux-test; true + - lib/tmux-test/setup + +script: ./tests/run_tests_in_isolation diff --git a/dot_tmux/plugins/tpm/executable_tpm b/dot_tmux/plugins/tpm/executable_tpm new file mode 100644 index 0000000..7ad4b99 --- /dev/null +++ b/dot_tmux/plugins/tpm/executable_tpm @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +BINDINGS_DIR="$CURRENT_DIR/bindings" +SCRIPTS_DIR="$CURRENT_DIR/scripts" + +source "$SCRIPTS_DIR/variables.sh" + +get_tmux_option() { + local option="$1" + local default_value="$2" + local option_value="$(tmux show-option -gqv "$option")" + if [ -z "$option_value" ]; then + echo "$default_value" + else + echo "$option_value" + fi +} + +tpm_path_set() { + tmux show-environment -g "$DEFAULT_TPM_ENV_VAR_NAME" >/dev/null 2>&1 +} + +# Check if configuration file exists at an XDG-compatible location, if so use +# that directory for TMUX_PLUGIN_MANAGER_PATH. Otherwise use $DEFAULT_TPM_PATH. +set_default_tpm_path() { + local xdg_tmux_path="${XDG_CONFIG_HOME:-$HOME/.config}/tmux" + local tpm_path="$DEFAULT_TPM_PATH" + + if [ -f "$xdg_tmux_path/tmux.conf" ]; then + tpm_path="$xdg_tmux_path/plugins/" + fi + + tmux set-environment -g "$DEFAULT_TPM_ENV_VAR_NAME" "$tpm_path" +} + +# Ensures TMUX_PLUGIN_MANAGER_PATH global env variable is set. +# +# Put this in `.tmux.conf` to override the default: +# `set-environment -g TMUX_PLUGIN_MANAGER_PATH "/some/other/path/"` +set_tpm_path() { + if ! tpm_path_set; then + set_default_tpm_path + fi +} + +# 1. Fetches plugin names from `@plugin` variables +# 2. Creates full plugin path +# 3. Sources all *.tmux files from each of the plugin directories +# - no errors raised if directory does not exist +# Files are sourced as tmux config files, not as shell scripts! +source_plugins() { + "$SCRIPTS_DIR/source_plugins.sh" >/dev/null 2>&1 +} + +# prefix + I - downloads TPM plugins and reloads TMUX environment +# prefix + U - updates a plugin (or all of them) and reloads TMUX environment +# prefix + alt + u - remove unused TPM plugins and reloads TMUX environment +set_tpm_key_bindings() { + local install_key="$(get_tmux_option "$install_key_option" "$default_install_key")" + tmux bind-key "$install_key" run-shell "$BINDINGS_DIR/install_plugins" + + local update_key="$(get_tmux_option "$update_key_option" "$default_update_key")" + tmux bind-key "$update_key" run-shell "$BINDINGS_DIR/update_plugins" + + local clean_key="$(get_tmux_option "$clean_key_option" "$default_clean_key")" + tmux bind-key "$clean_key" run-shell "$BINDINGS_DIR/clean_plugins" +} + +supported_tmux_version_ok() { + "$SCRIPTS_DIR/check_tmux_version.sh" "$SUPPORTED_TMUX_VERSION" +} + +main() { + if supported_tmux_version_ok; then + set_tpm_path + set_tpm_key_bindings + source_plugins + fi +} +main diff --git a/dot_tmux/plugins/tpm/lib/tmux-test/.keep b/dot_tmux/plugins/tpm/lib/tmux-test/.keep new file mode 100644 index 0000000..e69de29 diff --git a/dot_tmux/plugins/tpm/scripts/executable_check_tmux_version.sh b/dot_tmux/plugins/tpm/scripts/executable_check_tmux_version.sh new file mode 100644 index 0000000..b0aedec --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/executable_check_tmux_version.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +VERSION="$1" +UNSUPPORTED_MSG="$2" + +get_tmux_option() { + local option=$1 + local default_value=$2 + local option_value=$(tmux show-option -gqv "$option") + if [ -z "$option_value" ]; then + echo "$default_value" + else + echo "$option_value" + fi +} + +# Ensures a message is displayed for 5 seconds in tmux prompt. +# Does not override the 'display-time' tmux option. +display_message() { + local message="$1" + + # display_duration defaults to 5 seconds, if not passed as an argument + if [ "$#" -eq 2 ]; then + local display_duration="$2" + else + local display_duration="5000" + fi + + # saves user-set 'display-time' option + local saved_display_time=$(get_tmux_option "display-time" "750") + + # sets message display time to 5 seconds + tmux set-option -gq display-time "$display_duration" + + # displays message + tmux display-message "$message" + + # restores original 'display-time' value + tmux set-option -gq display-time "$saved_display_time" +} + +# this is used to get "clean" integer version number. Examples: +# `tmux 1.9` => `19` +# `1.9a` => `19` +get_digits_from_string() { + local string="$1" + local only_digits="$(echo "$string" | tr -dC '[:digit:]')" + echo "$only_digits" +} + +tmux_version_int() { + local tmux_version_string=$(tmux -V) + echo "$(get_digits_from_string "$tmux_version_string")" +} + +unsupported_version_message() { + if [ -n "$UNSUPPORTED_MSG" ]; then + echo "$UNSUPPORTED_MSG" + else + echo "Error, Tmux version unsupported! Please install Tmux version $VERSION or greater!" + fi +} + +exit_if_unsupported_version() { + local current_version="$1" + local supported_version="$2" + if [ "$current_version" -lt "$supported_version" ]; then + display_message "$(unsupported_version_message)" + exit 1 + fi +} + +main() { + local supported_version_int="$(get_digits_from_string "$VERSION")" + local current_version_int="$(tmux_version_int)" + exit_if_unsupported_version "$current_version_int" "$supported_version_int" +} +main diff --git a/dot_tmux/plugins/tpm/scripts/executable_clean_plugins.sh b/dot_tmux/plugins/tpm/scripts/executable_clean_plugins.sh new file mode 100644 index 0000000..a025524 --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/executable_clean_plugins.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +HELPERS_DIR="$CURRENT_DIR/helpers" + +source "$HELPERS_DIR/plugin_functions.sh" +source "$HELPERS_DIR/utility.sh" + +if [ "$1" == "--tmux-echo" ]; then # tmux-specific echo functions + source "$HELPERS_DIR/tmux_echo_functions.sh" +else # shell output functions + source "$HELPERS_DIR/shell_echo_functions.sh" +fi + +clean_plugins() { + local plugins plugin plugin_directory + plugins="$(tpm_plugins_list_helper)" + + for plugin_directory in "$(tpm_path)"/*; do + [ -d "${plugin_directory}" ] || continue + plugin="$(plugin_name_helper "${plugin_directory}")" + case "${plugins}" in + *"${plugin}"*) : ;; + *) + [ "${plugin}" = "tpm" ] && continue + echo_ok "Removing \"$plugin\"" + rm -rf "${plugin_directory}" >/dev/null 2>&1 + [ -d "${plugin_directory}" ] && + echo_err " \"$plugin\" clean fail" || + echo_ok " \"$plugin\" clean success" + ;; + esac + done +} + +main() { + ensure_tpm_path_exists + clean_plugins + exit_value_helper +} +main diff --git a/dot_tmux/plugins/tpm/scripts/executable_install_plugins.sh b/dot_tmux/plugins/tpm/scripts/executable_install_plugins.sh new file mode 100644 index 0000000..e2450ac --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/executable_install_plugins.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +HELPERS_DIR="$CURRENT_DIR/helpers" + +source "$HELPERS_DIR/plugin_functions.sh" +source "$HELPERS_DIR/utility.sh" + +if [ "$1" == "--tmux-echo" ]; then # tmux-specific echo functions + source "$HELPERS_DIR/tmux_echo_functions.sh" +else # shell output functions + source "$HELPERS_DIR/shell_echo_functions.sh" +fi + +clone() { + local plugin="$1" + local branch="$2" + if [ -n "$branch" ]; then + cd "$(tpm_path)" && + GIT_TERMINAL_PROMPT=0 git clone -b "$branch" --single-branch --recursive "$plugin" >/dev/null 2>&1 + else + cd "$(tpm_path)" && + GIT_TERMINAL_PROMPT=0 git clone --single-branch --recursive "$plugin" >/dev/null 2>&1 + fi +} + +# tries cloning: +# 1. plugin name directly - works if it's a valid git url +# 2. expands the plugin name to point to a GitHub repo and tries cloning again +clone_plugin() { + local plugin="$1" + local branch="$2" + clone "$plugin" "$branch" || + clone "https://git::@github.com/$plugin" "$branch" +} + +# clone plugin and produce output +install_plugin() { + local plugin="$1" + local branch="$2" + local plugin_name="$(plugin_name_helper "$plugin")" + + if plugin_already_installed "$plugin"; then + echo_ok "Already installed \"$plugin_name\"" + else + echo_ok "Installing \"$plugin_name\"" + clone_plugin "$plugin" "$branch" && + echo_ok " \"$plugin_name\" download success" || + echo_err " \"$plugin_name\" download fail" + fi +} + +install_plugins() { + local plugins="$(tpm_plugins_list_helper)" + for plugin in $plugins; do + IFS='#' read -ra plugin <<< "$plugin" + install_plugin "${plugin[0]}" "${plugin[1]}" + done +} + +verify_tpm_path_permissions() { + local path="$(tpm_path)" + # check the write permission flag for all users to ensure + # that we have proper access + [ -w "$path" ] || + echo_err "$path is not writable!" +} + +main() { + ensure_tpm_path_exists + verify_tpm_path_permissions + install_plugins + exit_value_helper +} +main diff --git a/dot_tmux/plugins/tpm/scripts/executable_source_plugins.sh b/dot_tmux/plugins/tpm/scripts/executable_source_plugins.sh new file mode 100644 index 0000000..6381d54 --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/executable_source_plugins.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +HELPERS_DIR="$CURRENT_DIR/helpers" + +source "$HELPERS_DIR/plugin_functions.sh" + +plugin_dir_exists() { + [ -d "$1" ] +} + +# Runs all *.tmux files from the plugin directory. +# Files are ran as executables. +# No errors if the plugin dir does not exist. +silently_source_all_tmux_files() { + local plugin_path="$1" + local plugin_tmux_files="$plugin_path*.tmux" + if plugin_dir_exists "$plugin_path"; then + for tmux_file in $plugin_tmux_files; do + # if the glob didn't find any files this will be the + # unexpanded glob which obviously doesn't exist + [ -f "$tmux_file" ] || continue + # runs *.tmux file as an executable + $tmux_file >/dev/null 2>&1 + done + fi +} + +source_plugins() { + local plugin plugin_path + local plugins="$(tpm_plugins_list_helper)" + for plugin in $plugins; do + IFS='#' read -ra plugin <<< "$plugin" + plugin_path="$(plugin_path_helper "${plugin[0]}")" + silently_source_all_tmux_files "$plugin_path" + done +} + +main() { + source_plugins +} +main diff --git a/dot_tmux/plugins/tpm/scripts/executable_update_plugin.sh b/dot_tmux/plugins/tpm/scripts/executable_update_plugin.sh new file mode 100644 index 0000000..e533664 --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/executable_update_plugin.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +# this script handles core logic of updating plugins + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +HELPERS_DIR="$CURRENT_DIR/helpers" + +source "$HELPERS_DIR/plugin_functions.sh" +source "$HELPERS_DIR/utility.sh" + +if [ "$1" == "--tmux-echo" ]; then # tmux-specific echo functions + source "$HELPERS_DIR/tmux_echo_functions.sh" +else # shell output functions + source "$HELPERS_DIR/shell_echo_functions.sh" +fi + +# from now on ignore first script argument +shift + +pull_changes() { + local plugin="$1" + local plugin_path="$(plugin_path_helper "$plugin")" + cd "$plugin_path" && + GIT_TERMINAL_PROMPT=0 git pull && + GIT_TERMINAL_PROMPT=0 git submodule update --init --recursive +} + +update() { + local plugin="$1" output + output=$(pull_changes "$plugin" 2>&1) + if (( $? == 0 )); then + echo_ok " \"$plugin\" update success" + echo_ok "$(echo "$output" | sed -e 's/^/ | /')" + else + echo_err " \"$plugin\" update fail" + echo_err "$(echo "$output" | sed -e 's/^/ | /')" + fi +} + +update_all() { + echo_ok "Updating all plugins!" + echo_ok "" + local plugins="$(tpm_plugins_list_helper)" + for plugin in $plugins; do + IFS='#' read -ra plugin <<< "$plugin" + local plugin_name="$(plugin_name_helper "${plugin[0]}")" + # updating only installed plugins + if plugin_already_installed "$plugin_name"; then + update "$plugin_name" & + fi + done + wait +} + +update_plugins() { + local plugins="$*" + for plugin in $plugins; do + IFS='#' read -ra plugin <<< "$plugin" + local plugin_name="$(plugin_name_helper "${plugin[0]}")" + if plugin_already_installed "$plugin_name"; then + update "$plugin_name" & + else + echo_err "$plugin_name not installed!" & + fi + done + wait +} + +main() { + ensure_tpm_path_exists + if [ "$1" == "all" ]; then + update_all + else + update_plugins "$*" + fi + exit_value_helper +} +main "$*" diff --git a/dot_tmux/plugins/tpm/scripts/executable_update_plugin_prompt_handler.sh b/dot_tmux/plugins/tpm/scripts/executable_update_plugin_prompt_handler.sh new file mode 100644 index 0000000..5e1f7d9 --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/executable_update_plugin_prompt_handler.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +HELPERS_DIR="$CURRENT_DIR/helpers" + +if [ $# -eq 0 ]; then + exit 0 +fi + +source "$HELPERS_DIR/tmux_echo_functions.sh" +source "$HELPERS_DIR/tmux_utils.sh" + +main() { + "$CURRENT_DIR/update_plugin.sh" --tmux-echo "$*" + reload_tmux_environment + end_message +} +main "$*" diff --git a/dot_tmux/plugins/tpm/scripts/helpers/plugin_functions.sh b/dot_tmux/plugins/tpm/scripts/helpers/plugin_functions.sh new file mode 100644 index 0000000..f33d215 --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/helpers/plugin_functions.sh @@ -0,0 +1,104 @@ +# using @tpm_plugins is now deprecated in favor of using @plugin syntax +tpm_plugins_variable_name="@tpm_plugins" + +# manually expanding tilde char or `$HOME` variable. +_manual_expansion() { + local path="$1" + local expanded_tilde="${path/#\~/$HOME}" + echo "${expanded_tilde/#\$HOME/$HOME}" +} + +_tpm_path() { + local string_path="$(tmux start-server\; show-environment -g TMUX_PLUGIN_MANAGER_PATH | cut -f2 -d=)/" + _manual_expansion "$string_path" +} + +_CACHED_TPM_PATH="$(_tpm_path)" + +# Get the absolute path to the users configuration file of TMux. +# This includes a prioritized search on different locations. +# +_get_user_tmux_conf() { + # Define the different possible locations. + xdg_location="${XDG_CONFIG_HOME:-$HOME/.config}/tmux/tmux.conf" + default_location="$HOME/.tmux.conf" + + # Search for the correct configuration file by priority. + if [ -f "$xdg_location" ]; then + echo "$xdg_location" + + else + echo "$default_location" + fi +} + +_tmux_conf_contents() { + user_config=$(_get_user_tmux_conf) + cat /etc/tmux.conf "$user_config" 2>/dev/null + if [ "$1" == "full" ]; then # also output content from sourced files + local file + for file in $(_sourced_files); do + cat $(_manual_expansion "$file") 2>/dev/null + done + fi +} + +# return files sourced from tmux config files +_sourced_files() { + _tmux_conf_contents | + sed -E -n -e "s/^[[:space:]]*source(-file)?[[:space:]]+(-q+[[:space:]]+)?['\"]?([^'\"]+)['\"]?/\3/p" +} + +# Want to be able to abort in certain cases +trap "exit 1" TERM +export TOP_PID=$$ + +_fatal_error_abort() { + echo >&2 "Aborting." + kill -s TERM $TOP_PID +} + +# PUBLIC FUNCTIONS BELOW + +tpm_path() { + if [ "$_CACHED_TPM_PATH" == "/" ]; then + echo >&2 "FATAL: Tmux Plugin Manager not configured in tmux.conf" + _fatal_error_abort + fi + echo "$_CACHED_TPM_PATH" +} + +tpm_plugins_list_helper() { + # lists plugins from @tpm_plugins option + echo "$(tmux start-server\; show-option -gqv "$tpm_plugins_variable_name")" + + # read set -g @plugin "tmux-plugins/tmux-example-plugin" entries + _tmux_conf_contents "full" | + awk '/^[ \t]*set(-option)? +-g +@plugin/ { gsub(/'\''/,""); gsub(/'\"'/,""); print $4 }' +} + +# Allowed plugin name formats: +# 1. "git://github.com/user/plugin_name.git" +# 2. "user/plugin_name" +plugin_name_helper() { + local plugin="$1" + # get only the part after the last slash, e.g. "plugin_name.git" + local plugin_basename="$(basename "$plugin")" + # remove ".git" extension (if it exists) to get only "plugin_name" + local plugin_name="${plugin_basename%.git}" + echo "$plugin_name" +} + +plugin_path_helper() { + local plugin="$1" + local plugin_name="$(plugin_name_helper "$plugin")" + echo "$(tpm_path)${plugin_name}/" +} + +plugin_already_installed() { + local plugin="$1" + local plugin_path="$(plugin_path_helper "$plugin")" + [ -d "$plugin_path" ] && + cd "$plugin_path" && + git remote >/dev/null 2>&1 +} diff --git a/dot_tmux/plugins/tpm/scripts/helpers/shell_echo_functions.sh b/dot_tmux/plugins/tpm/scripts/helpers/shell_echo_functions.sh new file mode 100644 index 0000000..ecaa37e --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/helpers/shell_echo_functions.sh @@ -0,0 +1,7 @@ +echo_ok() { + echo "$*" +} + +echo_err() { + fail_helper "$*" +} diff --git a/dot_tmux/plugins/tpm/scripts/helpers/tmux_echo_functions.sh b/dot_tmux/plugins/tpm/scripts/helpers/tmux_echo_functions.sh new file mode 100644 index 0000000..7a6ef0a --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/helpers/tmux_echo_functions.sh @@ -0,0 +1,28 @@ +_has_emacs_mode_keys() { + $(tmux show -gw mode-keys | grep -q emacs) +} + +tmux_echo() { + local message="$1" + tmux run-shell "echo '$message'" +} + +echo_ok() { + tmux_echo "$*" +} + +echo_err() { + tmux_echo "$*" +} + +end_message() { + if _has_emacs_mode_keys; then + local continue_key="ESCAPE" + else + local continue_key="ENTER" + fi + tmux_echo "" + tmux_echo "TMUX environment reloaded." + tmux_echo "" + tmux_echo "Done, press $continue_key to continue." +} diff --git a/dot_tmux/plugins/tpm/scripts/helpers/tmux_utils.sh b/dot_tmux/plugins/tpm/scripts/helpers/tmux_utils.sh new file mode 100644 index 0000000..238952d --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/helpers/tmux_utils.sh @@ -0,0 +1,6 @@ +HELPERS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +source "$HELPERS_DIR/plugin_functions.sh" + +reload_tmux_environment() { + tmux source-file $(_get_user_tmux_conf) >/dev/null 2>&1 +} diff --git a/dot_tmux/plugins/tpm/scripts/helpers/utility.sh b/dot_tmux/plugins/tpm/scripts/helpers/utility.sh new file mode 100644 index 0000000..de6eb35 --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/helpers/utility.sh @@ -0,0 +1,17 @@ +ensure_tpm_path_exists() { + mkdir -p "$(tpm_path)" +} + +fail_helper() { + local message="$1" + echo "$message" >&2 + FAIL="true" +} + +exit_value_helper() { + if [ "$FAIL" == "true" ]; then + exit 1 + else + exit 0 + fi +} diff --git a/dot_tmux/plugins/tpm/scripts/variables.sh b/dot_tmux/plugins/tpm/scripts/variables.sh new file mode 100644 index 0000000..5601a86 --- /dev/null +++ b/dot_tmux/plugins/tpm/scripts/variables.sh @@ -0,0 +1,13 @@ +install_key_option="@tpm-install" +default_install_key="I" + +update_key_option="@tpm-update" +default_update_key="U" + +clean_key_option="@tpm-clean" +default_clean_key="M-u" + +SUPPORTED_TMUX_VERSION="1.9" + +DEFAULT_TPM_ENV_VAR_NAME="TMUX_PLUGIN_MANAGER_PATH" +DEFAULT_TPM_PATH="$HOME/.tmux/plugins/" diff --git a/dot_tmux/plugins/tpm/tests/executable_expect_failed_plugin_download b/dot_tmux/plugins/tpm/tests/executable_expect_failed_plugin_download new file mode 100644 index 0000000..b970477 --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_expect_failed_plugin_download @@ -0,0 +1,36 @@ +#!/usr/bin/env expect + +# disables script output +log_user 0 + +spawn tmux + +# Waiting for tmux to attach. If this is not done, next command, `send` will +# not work properly. +sleep 1 + +# this is tmux prefix + I +send "I" + +# cloning might take a while +set timeout 20 + +expect_after { + timeout { exit 1 } +} + +expect { + "Installing \"non-existing-plugin\"" +} + +expect { + "\"non-existing-plugin\" download fail" +} + +expect { + "Done, press ENTER to continue" { + exit 0 + } +} + +exit 1 diff --git a/dot_tmux/plugins/tpm/tests/executable_expect_successful_clean_plugins b/dot_tmux/plugins/tpm/tests/executable_expect_successful_clean_plugins new file mode 100644 index 0000000..987c49d --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_expect_successful_clean_plugins @@ -0,0 +1,35 @@ +#!/usr/bin/env expect + +# disables script output +log_user 0 + +spawn tmux + +# Waiting for tmux to attach. If this is not done, next command, `send` will +# not work properly. +sleep 1 + +# this is tmux prefix + alt + u +send "u" + +set timeout 5 + +expect_after { + timeout { exit 1 } +} + +expect { + "Removing \"tmux-example-plugin\"" +} + +expect { + "\"tmux-example-plugin\" clean success" +} + +expect { + "Done, press ENTER to continue." { + exit 0 + } +} + +exit 1 diff --git a/dot_tmux/plugins/tpm/tests/executable_expect_successful_multiple_plugins_download b/dot_tmux/plugins/tpm/tests/executable_expect_successful_multiple_plugins_download new file mode 100644 index 0000000..cc87a26 --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_expect_successful_multiple_plugins_download @@ -0,0 +1,44 @@ +#!/usr/bin/env expect + +# disables script output +log_user 0 + +spawn tmux + +# Waiting for tmux to attach. If this is not done, next command, `send` will +# not work properly. +sleep 1 + +# this is tmux prefix + I +send "I" + +# cloning might take a while +set timeout 15 + +expect_after { + timeout { exit 1 } +} + +expect { + "Installing \"tmux-example-plugin\"" +} + +expect { + "\"tmux-example-plugin\" download success" +} + +expect { + "Installing \"tmux-copycat\"" +} + +expect { + "\"tmux-copycat\" download success" +} + +expect { + "Done, press ENTER to continue." { + exit 0 + } +} + +exit 1 diff --git a/dot_tmux/plugins/tpm/tests/executable_expect_successful_plugin_download b/dot_tmux/plugins/tpm/tests/executable_expect_successful_plugin_download new file mode 100644 index 0000000..388f05d --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_expect_successful_plugin_download @@ -0,0 +1,50 @@ +#!/usr/bin/env expect + +# disables script output +log_user 0 + +spawn tmux + +# Waiting for tmux to attach. If this is not done, next command, `send` will +# not work properly. +sleep 1 + +# this is tmux prefix + I +send "I" + +# cloning might take a while +set timeout 15 + +expect_after { + timeout { exit 1 } +} + +expect { + "Installing \"tmux-example-plugin\"" +} + +expect { + "\"tmux-example-plugin\" download success" +} + +expect { + "Done, press ENTER to continue" { + send " " + } +} + +sleep 1 +# this is tmux prefix + I +send "I" + +expect { + "Already installed \"tmux-example-plugin\"" +} + +expect { + "Done, press ENTER to continue" { + exit 0 + } +} + +exit 1 diff --git a/dot_tmux/plugins/tpm/tests/executable_expect_successful_update_of_a_single_plugin b/dot_tmux/plugins/tpm/tests/executable_expect_successful_update_of_a_single_plugin new file mode 100644 index 0000000..bcd64fe --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_expect_successful_update_of_a_single_plugin @@ -0,0 +1,55 @@ +#!/usr/bin/env expect + +# disables script output +log_user 0 + +spawn tmux + +# Waiting for tmux to attach. If this is not done, next command, `send` will +# not work properly. +sleep 1 + +# this is tmux prefix + U +send "U" + +set timeout 15 + +expect_after { + timeout { exit 1 } +} + +expect { + "Installed plugins" +} + +expect { + "tmux-example-plugin" +} + +expect { + "\"all\" - updates all plugins" +} + +expect { + "ENTER - cancels" +} + +# wait for tmux to display prompt before sending characters +sleep 1 +send "tmux-example-plugin\r" + +expect { + "Updating \"tmux-example-plugin\"" +} + +expect { + "\"tmux-example-plugin\" update success" +} + +expect { + "Done, press ENTER to continue." { + exit 0 + } +} + +exit 1 diff --git a/dot_tmux/plugins/tpm/tests/executable_expect_successful_update_of_all_plugins b/dot_tmux/plugins/tpm/tests/executable_expect_successful_update_of_all_plugins new file mode 100644 index 0000000..4f3a4a3 --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_expect_successful_update_of_all_plugins @@ -0,0 +1,59 @@ +#!/usr/bin/env expect + +# disables script output +log_user 0 + +spawn tmux + +# Waiting for tmux to attach. If this is not done, next command, `send` will +# not work properly. +sleep 1 + +# this is tmux prefix + U +send "U" + +set timeout 5 + +expect_after { + timeout { exit 1 } +} + +expect { + "Installed plugins" +} + +expect { + "tmux-example-plugin" +} + +expect { + "\"all\" - updates all plugins" +} + +expect { + "ENTER - cancels" +} + +# wait for tmux to display prompt before sending characters +sleep 1 +send "all\r" + +expect { + "Updating all plugins!" +} + +expect { + "Updating \"tmux-example-plugin\"" +} + +expect { + "\"tmux-example-plugin\" update success" +} + +expect { + "Done, press ENTER to continue." { + exit 0 + } +} + +exit 1 diff --git a/dot_tmux/plugins/tpm/tests/executable_test_plugin_clean.sh b/dot_tmux/plugins/tpm/tests/executable_test_plugin_clean.sh new file mode 100644 index 0000000..d36c468 --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_test_plugin_clean.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +TPM_DIR="$PWD" +PLUGINS_DIR="$HOME/.tmux/plugins" + +source "$CURRENT_DIR/helpers/helpers.sh" +source "$CURRENT_DIR/helpers/tpm.sh" + +manually_install_the_plugin() { + rm -rf "$PLUGINS_DIR" + mkdir -p "$PLUGINS_DIR" + cd "$PLUGINS_DIR" + git clone --quiet https://github.com/tmux-plugins/tmux-example-plugin +} + +# TMUX KEY-BINDING TESTS + +test_plugin_uninstallation_via_tmux_key_binding() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + run-shell "$TPM_DIR/tpm" + HERE + + manually_install_the_plugin + + "$CURRENT_DIR/expect_successful_clean_plugins" || + fail_helper "[key-binding] clean fails" + + teardown_helper +} + +# SCRIPT TESTS + +test_plugin_uninstallation_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + run-shell "$TPM_DIR/tpm" + HERE + + manually_install_the_plugin + + script_run_helper "$TPM_DIR/bin/clean_plugins" '"tmux-example-plugin" clean success' || + fail_helper "[script] plugin cleaning fails" + + teardown_helper +} + +test_unsuccessful_plugin_uninstallation_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + run-shell "$TPM_DIR/tpm" + HERE + + manually_install_the_plugin + chmod 000 "$PLUGINS_DIR/tmux-example-plugin" # disable directory deletion + + local expected_exit_code=1 + script_run_helper "$TPM_DIR/bin/clean_plugins" '"tmux-example-plugin" clean fail' "$expected_exit_code" || + fail_helper "[script] unsuccessful plugin cleaning doesn't fail" + + chmod 755 "$PLUGINS_DIR/tmux-example-plugin" # enable directory deletion + + teardown_helper +} + +run_tests diff --git a/dot_tmux/plugins/tpm/tests/executable_test_plugin_installation.sh b/dot_tmux/plugins/tpm/tests/executable_test_plugin_installation.sh new file mode 100644 index 0000000..94fb674 --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_test_plugin_installation.sh @@ -0,0 +1,284 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PLUGINS_DIR="$HOME/.tmux/plugins" +TPM_DIR="$PWD" + +CUSTOM_PLUGINS_DIR="$HOME/foo/plugins" +ADDITIONAL_CONFIG_FILE_1="$HOME/.tmux/additional_config_file_1" +ADDITIONAL_CONFIG_FILE_2="$HOME/.tmux/additional_config_file_2" + +source "$CURRENT_DIR/helpers/helpers.sh" +source "$CURRENT_DIR/helpers/tpm.sh" + +# TMUX KEY-BINDING TESTS + +test_plugin_installation_via_tmux_key_binding() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @plugin "tmux-plugins/tmux-example-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + "$CURRENT_DIR/expect_successful_plugin_download" || + fail_helper "[key-binding] plugin installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[key-binding] plugin download fails" + + teardown_helper +} + +test_plugin_installation_via_tmux_key_binding_set_option() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set-option -g @plugin "tmux-plugins/tmux-example-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + "$CURRENT_DIR/expect_successful_plugin_download" || + fail_helper "[key-binding][set-option] plugin installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[key-binding][set-option] plugin download fails" + + teardown_helper +} + +test_plugin_installation_custom_dir_via_tmux_key_binding() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set-environment -g TMUX_PLUGIN_MANAGER_PATH '$CUSTOM_PLUGINS_DIR' + + set -g @plugin "tmux-plugins/tmux-example-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + "$CURRENT_DIR/expect_successful_plugin_download" || + fail_helper "[key-binding][custom dir] plugin installation fails" + + check_dir_exists_helper "$CUSTOM_PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[key-binding][custom dir] plugin download fails" + + teardown_helper + rm -rf "$CUSTOM_PLUGINS_DIR" +} + +test_non_existing_plugin_installation_via_tmux_key_binding() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @plugin "tmux-plugins/non-existing-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + "$CURRENT_DIR/expect_failed_plugin_download" || + fail_helper "[key-binding] non existing plugin installation doesn't fail" + + teardown_helper +} + +test_multiple_plugins_installation_via_tmux_key_binding() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @plugin "tmux-plugins/tmux-example-plugin" + \ \ set -g @plugin 'tmux-plugins/tmux-copycat' + run-shell "$TPM_DIR/tpm" + HERE + + "$CURRENT_DIR/expect_successful_multiple_plugins_download" || + fail_helper "[key-binding] multiple plugins installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[key-binding] plugin download fails (tmux-example-plugin)" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || + fail_helper "[key-binding] plugin download fails (tmux-copycat)" + + teardown_helper +} + +test_plugins_installation_from_sourced_file_via_tmux_key_binding() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + source '$ADDITIONAL_CONFIG_FILE_1' + set -g @plugin 'tmux-plugins/tmux-example-plugin' + run-shell "$TPM_DIR/tpm" + HERE + + mkdir ~/.tmux + echo "set -g @plugin 'tmux-plugins/tmux-copycat'" > "$ADDITIONAL_CONFIG_FILE_1" + + "$CURRENT_DIR/expect_successful_multiple_plugins_download" || + fail_helper "[key-binding][sourced file] plugins installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[key-binding][sourced file] plugin download fails (tmux-example-plugin)" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || + fail_helper "[key-binding][sourced file] plugin download fails (tmux-copycat)" + + teardown_helper +} + +test_plugins_installation_from_multiple_sourced_files_via_tmux_key_binding() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + \ \ source '$ADDITIONAL_CONFIG_FILE_1' + source-file '$ADDITIONAL_CONFIG_FILE_2' + run-shell "$TPM_DIR/tpm" + HERE + + mkdir ~/.tmux + echo "set -g @plugin 'tmux-plugins/tmux-example-plugin'" > "$ADDITIONAL_CONFIG_FILE_1" + echo " set -g @plugin 'tmux-plugins/tmux-copycat'" > "$ADDITIONAL_CONFIG_FILE_2" + + "$CURRENT_DIR/expect_successful_multiple_plugins_download" || + fail_helper "[key-binding][multiple sourced files] plugins installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[key-binding][multiple sourced files] plugin download fails (tmux-example-plugin)" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || + fail_helper "[key-binding][multiple sourced files] plugin download fails (tmux-copycat)" + + teardown_helper +} + +# SCRIPT TESTS + +test_plugin_installation_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @plugin "tmux-plugins/tmux-example-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-example-plugin" download success' || + fail_helper "[script] plugin installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[script] plugin download fails" + + script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-example-plugin"' || + fail_helper "[script] plugin already installed message fail" + + teardown_helper +} + +test_plugin_installation_custom_dir_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set-environment -g TMUX_PLUGIN_MANAGER_PATH '$CUSTOM_PLUGINS_DIR' + + set -g @plugin "tmux-plugins/tmux-example-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-example-plugin" download success' || + fail_helper "[script][custom dir] plugin installation fails" + + check_dir_exists_helper "$CUSTOM_PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[script][custom dir] plugin download fails" + + script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-example-plugin"' || + fail_helper "[script][custom dir] plugin already installed message fail" + + teardown_helper + rm -rf "$CUSTOM_PLUGINS_DIR" +} + +test_non_existing_plugin_installation_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @plugin "tmux-plugins/non-existing-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + local expected_exit_code=1 + script_run_helper "$TPM_DIR/bin/install_plugins" '"non-existing-plugin" download fail' "$expected_exit_code" || + fail_helper "[script] non existing plugin installation doesn't fail" + + teardown_helper +} + +test_multiple_plugins_installation_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @plugin "tmux-plugins/tmux-example-plugin" + \ \ set -g @plugin 'tmux-plugins/tmux-copycat' + run-shell "$TPM_DIR/tpm" + HERE + + script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-example-plugin" download success' || + fail_helper "[script] multiple plugins installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[script] plugin download fails (tmux-example-plugin)" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || + fail_helper "[script] plugin download fails (tmux-copycat)" + + script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-copycat"' || + fail_helper "[script] multiple plugins already installed message fail" + + teardown_helper +} + +test_plugins_installation_from_sourced_file_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + source '$ADDITIONAL_CONFIG_FILE_1' + set -g @plugin 'tmux-plugins/tmux-example-plugin' + run-shell "$TPM_DIR/tpm" + HERE + + mkdir ~/.tmux + echo "set -g @plugin 'tmux-plugins/tmux-copycat'" > "$ADDITIONAL_CONFIG_FILE_1" + + script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-copycat" download success' || + fail_helper "[script][sourced file] plugins installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[script][sourced file] plugin download fails (tmux-example-plugin)" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || + fail_helper "[script][sourced file] plugin download fails (tmux-copycat)" + + script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-copycat"' || + fail_helper "[script][sourced file] plugins already installed message fail" + + teardown_helper +} + +test_plugins_installation_from_multiple_sourced_files_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + \ \ source '$ADDITIONAL_CONFIG_FILE_1' + source-file '$ADDITIONAL_CONFIG_FILE_2' + set -g @plugin 'tmux-plugins/tmux-example-plugin' + run-shell "$TPM_DIR/tpm" + HERE + + mkdir ~/.tmux + echo " set -g @plugin 'tmux-plugins/tmux-copycat'" > "$ADDITIONAL_CONFIG_FILE_1" + echo "set -g @plugin 'tmux-plugins/tmux-sensible'" > "$ADDITIONAL_CONFIG_FILE_2" + + script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-sensible" download success' || + fail_helper "[script][multiple sourced files] plugins installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[script][multiple sourced files] plugin download fails (tmux-example-plugin)" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || + fail_helper "[script][multiple sourced files] plugin download fails (tmux-copycat)" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-sensible/" || + fail_helper "[script][multiple sourced files] plugin download fails (tmux-sensible)" + + script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-sensible"' || + fail_helper "[script][multiple sourced files] plugins already installed message fail" + + teardown_helper +} + +run_tests diff --git a/dot_tmux/plugins/tpm/tests/executable_test_plugin_installation_legacy.sh b/dot_tmux/plugins/tpm/tests/executable_test_plugin_installation_legacy.sh new file mode 100644 index 0000000..b1d0cf6 --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_test_plugin_installation_legacy.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PLUGINS_DIR="$HOME/.tmux/plugins" +TPM_DIR="$PWD" + +source "$CURRENT_DIR/helpers/helpers.sh" +source "$CURRENT_DIR/helpers/tpm.sh" + +# TMUX KEY-BINDING TESTS + +test_plugin_installation_via_tmux_key_binding() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @tpm_plugins "tmux-plugins/tmux-example-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + # opens tmux and test it with `expect` + $CURRENT_DIR/expect_successful_plugin_download || + fail_helper "[key-binding] plugin installation fails" + + # check plugin dir exists after download + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[key-binding] plugin download fails" + + teardown_helper +} + +test_legacy_and_new_syntax_for_plugin_installation_work_via_tmux_key_binding() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @tpm_plugins " \ + tmux-plugins/tmux-example-plugin \ + " + set -g @plugin 'tmux-plugins/tmux-copycat' + run-shell "$TPM_DIR/tpm" + HERE + + # opens tmux and test it with `expect` + "$CURRENT_DIR"/expect_successful_multiple_plugins_download || + fail_helper "[key-binding] multiple plugins installation fails" + + # check plugin dir exists after download + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[key-binding] plugin download fails (tmux-example-plugin)" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || + fail_helper "[key-binding] plugin download fails (tmux-copycat)" + + teardown_helper +} + +# SCRIPT TESTS + +test_plugin_installation_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @tpm_plugins "tmux-plugins/tmux-example-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-example-plugin" download success' || + fail_helper "[script] plugin installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[script] plugin download fails" + + script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-example-plugin"' || + fail_helper "[script] plugin already installed message fail" + + teardown_helper +} + +test_legacy_and_new_syntax_for_plugin_installation_work_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @tpm_plugins " \ + tmux-plugins/tmux-example-plugin \ + " + set -g @plugin 'tmux-plugins/tmux-copycat' + run-shell "$TPM_DIR/tpm" + HERE + + script_run_helper "$TPM_DIR/bin/install_plugins" '"tmux-example-plugin" download success' || + fail_helper "[script] multiple plugin installation fails" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-example-plugin/" || + fail_helper "[script] plugin download fails (tmux-example-plugin)" + + check_dir_exists_helper "$PLUGINS_DIR/tmux-copycat/" || + fail_helper "[script] plugin download fails (tmux-copycat)" + + script_run_helper "$TPM_DIR/bin/install_plugins" 'Already installed "tmux-copycat"' || + fail_helper "[script] multiple plugins already installed message fail" + + teardown_helper +} + +run_tests diff --git a/dot_tmux/plugins/tpm/tests/executable_test_plugin_sourcing.sh b/dot_tmux/plugins/tpm/tests/executable_test_plugin_sourcing.sh new file mode 100644 index 0000000..c06f1fe --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_test_plugin_sourcing.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +TPM_DIR="$PWD" +PLUGINS_DIR="$HOME/.tmux/plugins" + +CUSTOM_PLUGINS_DIR="$HOME/foo/plugins" + +source "$CURRENT_DIR/helpers/helpers.sh" +source "$CURRENT_DIR/helpers/tpm.sh" + +check_binding_defined() { + local binding="$1" + tmux list-keys | grep -q "$binding" +} + +create_test_plugin_helper() { + local plugin_path="$PLUGINS_DIR/tmux_test_plugin/" + rm -rf "$plugin_path" + mkdir -p "$plugin_path" + + while read line; do + echo "$line" >> "$plugin_path/test_plugin.tmux" + done + chmod +x "$plugin_path/test_plugin.tmux" +} + +check_tpm_path() { + local correct_tpm_path="$1" + local tpm_path="$(tmux start-server\; show-environment -g TMUX_PLUGIN_MANAGER_PATH | cut -f2 -d=)" + [ "$correct_tpm_path" == "$tpm_path" ] +} + +test_plugin_sourcing() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @plugin "doesnt_matter/tmux_test_plugin" + run-shell "$TPM_DIR/tpm" + HERE + + # manually creates a local tmux plugin + create_test_plugin_helper <<- HERE + tmux bind-key R run-shell foo_command + HERE + + tmux new-session -d # tmux starts detached + check_binding_defined "R run-shell foo_command" || + fail_helper "Plugin sourcing fails" + + teardown_helper +} + +test_default_tpm_path() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + run-shell "$TPM_DIR/tpm" + HERE + + check_tpm_path "${PLUGINS_DIR}/" || + fail_helper "Default TPM path not correct" + + teardown_helper +} + +test_custom_tpm_path() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set-environment -g TMUX_PLUGIN_MANAGER_PATH '$CUSTOM_PLUGINS_DIR' + run-shell "$TPM_DIR/tpm" + HERE + + check_tpm_path "$CUSTOM_PLUGINS_DIR" || + fail_helper "Custom TPM path not correct" + + teardown_helper +} + +run_tests diff --git a/dot_tmux/plugins/tpm/tests/executable_test_plugin_update.sh b/dot_tmux/plugins/tpm/tests/executable_test_plugin_update.sh new file mode 100644 index 0000000..4924d16 --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/executable_test_plugin_update.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +TPM_DIR="$PWD" +PLUGINS_DIR="$HOME/.tmux/plugins" + +source "$CURRENT_DIR/helpers/helpers.sh" +source "$CURRENT_DIR/helpers/tpm.sh" + +manually_install_the_plugin() { + mkdir -p "$PLUGINS_DIR" + cd "$PLUGINS_DIR" + git clone --quiet https://github.com/tmux-plugins/tmux-example-plugin +} + +# TMUX KEY-BINDING TESTS + +test_plugin_update_via_tmux_key_binding() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @plugin "tmux-plugins/tmux-example-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + manually_install_the_plugin + + "$CURRENT_DIR/expect_successful_update_of_all_plugins" || + fail_helper "[key-binding] 'update all plugins' fails" + + "$CURRENT_DIR/expect_successful_update_of_a_single_plugin" || + fail_helper "[key-binding] 'update single plugin' fails" + + teardown_helper +} + +# SCRIPT TESTS + +test_plugin_update_via_script() { + set_tmux_conf_helper <<- HERE + set -g mode-keys vi + set -g @plugin "tmux-plugins/tmux-example-plugin" + run-shell "$TPM_DIR/tpm" + HERE + + manually_install_the_plugin + + local expected_exit_code=1 + script_run_helper "$TPM_DIR/bin/update_plugins" 'usage' "$expected_exit_code" || + fail_helper "[script] running update plugins without args should fail" + + script_run_helper "$TPM_DIR/bin/update_plugins tmux-example-plugin" '"tmux-example-plugin" update success' || + fail_helper "[script] plugin update fails" + + script_run_helper "$TPM_DIR/bin/update_plugins all" '"tmux-example-plugin" update success' || + fail_helper "[script] update all plugins fails" + + teardown_helper +} + +run_tests diff --git a/dot_tmux/plugins/tpm/tests/helpers/tpm.sh b/dot_tmux/plugins/tpm/tests/helpers/tpm.sh new file mode 100644 index 0000000..1594afb --- /dev/null +++ b/dot_tmux/plugins/tpm/tests/helpers/tpm.sh @@ -0,0 +1,13 @@ +check_dir_exists_helper() { + [ -d "$1" ] +} + +# runs the scripts and asserts it has the correct output and exit code +script_run_helper() { + local script="$1" + local expected_output="$2" + local expected_exit_code="${3:-0}" + $script 2>&1 | + grep "$expected_output" >/dev/null 2>&1 && # grep -q flag quits the script early + [ "${PIPESTATUS[0]}" -eq "$expected_exit_code" ] +}