diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..cf1ab25 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +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 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. + +For more information, please refer to diff --git a/functions/git_ahead.fish b/functions/git_ahead.fish new file mode 100644 index 0000000..f7e7bea --- /dev/null +++ b/functions/git_ahead.fish @@ -0,0 +1,8 @@ +function git_ahead -a ahead behind diverged none + command git rev-list --count --left-right "@{upstream}...HEAD" 2>/dev/null | command awk " + /^0\t0/ { print \"$none\" ? \"$none\" : \"\"; exit 0 } + /^[0-9]+\t0/ { print \"$behind\" ? \"$behind\" : \"-\"; exit 0 } + /^0\t[0-9]+/ { print \"$ahead\" ? \"$ahead\" : \"+\"; exit 0 } + // { print \"$diverged\" ? \"$diverged\" : \"±\"; exit 0 } + " +end diff --git a/functions/git_branch_name.fish b/functions/git_branch_name.fish new file mode 100644 index 0000000..f08675e --- /dev/null +++ b/functions/git_branch_name.fish @@ -0,0 +1,15 @@ +function git_branch_name -d "Get the name of the current Git branch, tag or sha1" + set -l branch_name (command git symbolic-ref --short HEAD 2>/dev/null) + + if test -z "$branch_name" + set -l tag_name (command git describe --tags --exact-match HEAD 2>/dev/null) + + if test -z "$tag_name" + command git rev-parse --short HEAD 2>/dev/null + else + printf "%s\n" "$tag_name" + end + else + printf "%s\n" "$branch_name" + end +end diff --git a/functions/git_is_detached_head.fish b/functions/git_is_detached_head.fish new file mode 100644 index 0000000..8703b7a --- /dev/null +++ b/functions/git_is_detached_head.fish @@ -0,0 +1,3 @@ +function git_is_detached_head -d "Test if the repository is in a detached HEAD state" + git_is_repo; and not command git symbolic-ref HEAD 2>/dev/null > /dev/null +end diff --git a/functions/git_is_dirty.fish b/functions/git_is_dirty.fish new file mode 100644 index 0000000..608a055 --- /dev/null +++ b/functions/git_is_dirty.fish @@ -0,0 +1,3 @@ +function git_is_dirty -d "Test if there are changes not staged for commit" + git_is_repo; and not command git diff --no-ext-diff --quiet --exit-code 2>/dev/null +end diff --git a/functions/git_is_empty.fish b/functions/git_is_empty.fish new file mode 100644 index 0000000..6047591 --- /dev/null +++ b/functions/git_is_empty.fish @@ -0,0 +1,3 @@ +function git_is_empty -d "Test if a repository is empty" + git_is_repo; and test -z (command git rev-list -n 1 --all 2>/dev/null) +end diff --git a/functions/git_is_repo.fish b/functions/git_is_repo.fish new file mode 100644 index 0000000..1f69a06 --- /dev/null +++ b/functions/git_is_repo.fish @@ -0,0 +1,5 @@ +function git_is_repo -d "Test if the current directory is a Git repository" + if not command git rev-parse --git-dir > /dev/null 2>/dev/null + return 1 + end +end diff --git a/functions/git_is_staged.fish b/functions/git_is_staged.fish new file mode 100644 index 0000000..885ba93 --- /dev/null +++ b/functions/git_is_staged.fish @@ -0,0 +1,3 @@ +function git_is_staged -d "Test if there are changes staged for commit" + git_is_repo; and not command git diff --cached --no-ext-diff --quiet --exit-code 2>/dev/null +end diff --git a/functions/git_is_stashed.fish b/functions/git_is_stashed.fish new file mode 100644 index 0000000..25a5a3b --- /dev/null +++ b/functions/git_is_stashed.fish @@ -0,0 +1,3 @@ +function git_is_stashed -d "Test if there are changes in the Git stash" + command git rev-parse --verify --quiet refs/stash > /dev/null 2>/dev/null +end diff --git a/functions/git_is_tag.fish b/functions/git_is_tag.fish new file mode 100644 index 0000000..ab18b29 --- /dev/null +++ b/functions/git_is_tag.fish @@ -0,0 +1,3 @@ +function git_is_tag -d "Test if HEAD is on top of a tag (can be simple, annotated or signed)" + git_is_detached_head; and command git describe --tags --exact-match HEAD 2>/dev/null > /dev/null +end diff --git a/functions/git_is_touched.fish b/functions/git_is_touched.fish new file mode 100644 index 0000000..1b3b622 --- /dev/null +++ b/functions/git_is_touched.fish @@ -0,0 +1,3 @@ +function git_is_touched -d "Test if there are any changes in the working tree" + git_is_staged; or git_is_dirty +end diff --git a/functions/git_repository_root.fish b/functions/git_repository_root.fish new file mode 100644 index 0000000..4be29f2 --- /dev/null +++ b/functions/git_repository_root.fish @@ -0,0 +1,3 @@ +function git_repository_root -d "Get the top level directory of the current git repository" + git_is_repo; and command git rev-parse --show-toplevel +end diff --git a/functions/git_untracked_files.fish b/functions/git_untracked_files.fish new file mode 100644 index 0000000..f70a919 --- /dev/null +++ b/functions/git_untracked_files.fish @@ -0,0 +1,15 @@ +function git_untracked_files -d "Get the number of untracked files in a repository" + git_is_repo; and command git ls-files --others --exclude-standard | command awk ' + + BEGIN { + n = 0 + } + + { n++ } + + END { + print n + exit !n + } + ' +end diff --git a/functions/host_info.fish b/functions/host_info.fish new file mode 100644 index 0000000..dc3bdf0 --- /dev/null +++ b/functions/host_info.fish @@ -0,0 +1,16 @@ +function host_info -d "Get user and hostname information" -a format + set -l host (uname -n) + command id -un | command awk -v host="$host" -v format="$format" ' + BEGIN { if (format == "") format = "user@host" } + { + user = $0 + if (!sub("usr", substr(user, 1, 1), format)) { + sub("user", user, format) + } + len = split(host, host_info, ".") + sub("host", host_info[1], format) + sub("domain", len > 1 ? host_info[2] : "", format) + print(format) + } + ' +end diff --git a/functions/humanize_duration.fish b/functions/humanize_duration.fish new file mode 100644 index 0000000..eeb999f --- /dev/null +++ b/functions/humanize_duration.fish @@ -0,0 +1,19 @@ +function humanize_duration -d "Make a time interval human readable" + command awk ' + function hmTime(time, stamp) { + split("h:m:s:ms", units, ":") + for (i = 2; i >= -1; i--) { + if (t = int( i < 0 ? time % 1000 : time / (60 ^ i * 1000) % 60 )) { + stamp = stamp t units[sqrt((i - 2) ^ 2) + 1] " " + } + } + if (stamp ~ /^ *$/) { + return "0ms" + } + return substr(stamp, 1, length(stamp) - 1) + } + { + print hmTime($0) + } + ' +end diff --git a/functions/last_job_id.fish b/functions/last_job_id.fish new file mode 100644 index 0000000..fc01a18 --- /dev/null +++ b/functions/last_job_id.fish @@ -0,0 +1,3 @@ +function last_job_id + jobs $argv | command awk '/^[0-9]+\t/ { print status = $1 } END { exit !status }' +end diff --git a/functions/pwd_info.fish b/functions/pwd_info.fish new file mode 100644 index 0000000..69fdca0 --- /dev/null +++ b/functions/pwd_info.fish @@ -0,0 +1,43 @@ +function pwd_info -a separator -d "Print easy-to-parse information the current working directory" + set -l home ~ + set -l git_root (command git rev-parse --show-toplevel ^ /dev/null) + + command pwd -P | awk -v home="$home" -v git_root="$git_root" -v separator="$separator" -v dir_length="$fish_prompt_pwd_dir_length" ' + function base(string) { + sub(/^\/?.*\//, "", string) + return string + } + function dirs(string, printLastName, prefix, path) { + len = split(string, parts, "/") + for (i = 1; i < len; i++) { + name = dir_length == 0 ? parts[i] : substr(parts[i], 1, dir_length ? dir_length : 1) + if (parts[i] == "" || name == ".") { + continue + } + path = path prefix name + prefix = separator + } + return (printLastName == 1) ? path prefix parts[len] : path + } + function remove(thisString, fromString) { + sub(thisString, "", fromString) + return fromString + } + { + if (git_root == home) { + git_root = "" + } + if (git_root == "") { + printf("%s\n%s\n%s\n", + $0 == home || $0 == "/" ? "" : base($0), + dirs(remove(home, $0)), + "") + } else { + printf("%s\n%s\n%s\n", + base(git_root), + dirs(remove(home, git_root)), + $0 == git_root ? "" : dirs(remove(git_root, $0), 1)) + } + } + ' +end diff --git a/functions/pwd_is_home.fish b/functions/pwd_is_home.fish new file mode 100644 index 0000000..2d52e6a --- /dev/null +++ b/functions/pwd_is_home.fish @@ -0,0 +1,8 @@ +function pwd_is_home + switch "$PWD" + case ~{,/\*} + return 0 + case \* + return 1 + end +end