initial refactoring

This commit is contained in:
Noah Masur
2025-01-20 22:35:40 -05:00
parent a4b5e05f8f
commit c7933f8502
209 changed files with 5998 additions and 5308 deletions

View File

@ -1,39 +0,0 @@
{ config, lib, ... }:
{
# Shell history sync
options.atuin.enable = lib.mkEnableOption "Atuin";
config = {
home-manager.users.${config.user} = lib.mkIf config.atuin.enable {
programs.atuin = {
enable = true;
flags = [
"--disable-up-arrow"
"--disable-ctrl-r"
];
settings = {
auto_sync = true;
update_check = false;
sync_address = "https://api.atuin.sh";
search_mode = "fuzzy";
filter_mode = "host"; # global, host, session, directory
search_mode_shell_up_key_binding = "fuzzy";
filter_mode_shell_up_key_binding = "session";
style = "compact"; # or auto,full
show_help = true;
history_filter = [ ];
secrets_filter = true;
enter_accept = false;
keymap_mode = "vim-normal";
};
};
};
# Give root user the same setup
home-manager.users.root.programs.atuin = config.home-manager.users.${config.user}.programs.atuin;
};
}

View File

@ -1,22 +0,0 @@
{
config,
pkgs,
lib,
...
}:
{
# Convenience utilities from charm.sh
options.charm.enable = lib.mkEnableOption "Charm utilities.";
config.home-manager.users.${config.user} = lib.mkIf config.charm.enable {
home.packages = with pkgs; [
glow # Markdown previews
skate # Key-value store
charm # Manage account and filesystem
pop # Send emails from a TUI
];
};
}

View File

@ -1,18 +0,0 @@
{ ... }:
{
imports = [
./atuin.nix
./bash
./charm.nix
./direnv.nix
./fish
./fzf.nix
./git.nix
./github.nix
./jujutsu.nix
./nixpkgs.nix
./starship.nix
./utilities.nix
./work.nix
];
}

View File

@ -1,36 +0,0 @@
{ config, ... }:
{
# Enables quickly entering Nix shells when changing directories
home-manager.users.${config.user}.programs.direnv = {
enable = true;
nix-direnv.enable = true;
config = {
whitelist = {
prefix = [ config.dotfilesPath ];
};
};
};
# programs.direnv.direnvrcExtra = ''
# layout_postgres() {
# export PGDATA="$(direnv_layout_dir)/postgres"
# export PGHOST="$PGDATA"
#
# if [[ ! -d "PGDATA" ]]; then
# initdb
# cat >> "$PGDATA/postgres.conf" <<- EOF
# listen_addresses = '''
# unix_socket_directories = '$PGHOST'
# EOF
# echo "CREATE DATABASE $USER;" | postgres --single -E postgres
# fi
# }
# '';
# Prevent garbage collection
nix.extraOptions = ''
keep-outputs = true
keep-derivations = true
'';
}

View File

@ -1,154 +0,0 @@
{
config,
pkgs,
lib,
...
}:
{
users.users.${config.user}.shell = pkgs.fish;
programs.fish.enable = true; # Needed for LightDM to remember username
home-manager.users.${config.user} = {
# Packages used in abbreviations and aliases
home.packages = with pkgs; [ curl ];
programs.fish = {
enable = true;
shellAliases = {
# Version of bash which works much better on the terminal
bash = "${pkgs.bashInteractive}/bin/bash";
# Use eza (exa) instead of ls for fancier output
ls = "${pkgs.eza}/bin/eza --group";
# Move files to XDG trash on the commandline
trash = lib.mkIf pkgs.stdenv.isLinux "${pkgs.trash-cli}/bin/trash-put";
};
functions = {
commandline-git-commits = {
description = "Insert commit into commandline";
body = builtins.readFile ./functions/commandline-git-commits.fish;
};
copy = {
description = "Copy file contents into clipboard";
body = "cat $argv | pbcopy"; # Need to fix for non-macOS
};
edit = {
description = "Open a file in Vim";
body = builtins.readFile ./functions/edit.fish;
};
envs = {
description = "Evaluate a bash-like environment variables file";
body = ''set -gx (cat $argv | tr "=" " " | string split ' ')'';
};
fcd = {
description = "Jump to directory";
argumentNames = "directory";
body = builtins.readFile ./functions/fcd.fish;
};
fish_user_key_bindings = {
body = builtins.readFile ./functions/fish_user_key_bindings.fish;
};
ip = {
body = builtins.readFile ./functions/ip.fish;
};
json = {
description = "Tidy up JSON using jq";
body = "pbpaste | jq '.' | pbcopy"; # Need to fix for non-macOS
};
note = {
description = "Edit or create a note";
argumentNames = "filename";
body = builtins.readFile ./functions/note.fish;
};
recent = {
description = "Open a recent file in Vim";
body = builtins.readFile ./functions/recent.fish;
};
search-and-edit = {
description = "Search and open the relevant file in Vim";
body = builtins.readFile ./functions/search-and-edit.fish;
};
syncnotes = {
description = "Full git commit on notes";
body = builtins.readFile ./functions/syncnotes.fish;
};
_which = {
description = "Identify the path to a program in the shell";
body = "command --search (string sub --start=2 $argv)";
};
};
interactiveShellInit = ''
fish_vi_key_bindings
bind yy fish_clipboard_copy
bind Y fish_clipboard_copy
bind -M visual y fish_clipboard_copy
bind -M default p fish_clipboard_paste
set -g fish_vi_force_cursor
set -g fish_cursor_default block
set -g fish_cursor_insert line
set -g fish_cursor_visual block
set -g fish_cursor_replace_one underscore
'';
loginShellInit = "";
shellAbbrs = {
# Directory aliases
l = "ls -lh";
lh = "ls -lh";
ll = "ls -alhF";
la = "ls -a";
c = "cd";
"-" = "cd -";
mkd = "mkdir -pv";
# Convert a program into its full path
"=" = {
position = "anywhere";
regex = "=\\w+";
function = "_which";
};
# System
s = "sudo";
sc = "systemctl";
scs = "systemctl status";
sca = "systemctl cat";
m = "make";
t = "trash";
# Vim (overwritten by Neovim)
v = "vim";
vl = "vim -c 'normal! `0'";
# Notes
sn = "syncnotes";
# Fun CLI Tools
weather = "curl wttr.in/$WEATHER_CITY";
moon = "curl wttr.in/Moon";
# Cheat Sheets
ssl = "openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr";
fingerprint = "ssh-keyscan myhost.com | ssh-keygen -lf -";
publickey = "ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub";
forloop = "for i in (seq 1 100)";
# Docker
dc = "$DOTS/bin/docker_cleanup";
dr = "docker run --rm -it";
db = "docker build . -t";
};
shellInit = "";
};
home.sessionVariables.fish_greeting = "";
programs.starship.enableFishIntegration = true;
programs.zoxide.enableFishIntegration = true;
programs.fzf.enableFishIntegration = true;
};
}

View File

@ -1,56 +0,0 @@
{ config, pkgs, ... }:
{
# FZF is a fuzzy-finder for the terminal
home-manager.users.${config.user} = {
programs.fzf.enable = true;
programs.fish = {
functions = {
projects = {
description = "Jump to a project";
body = ''
set projdir ( \
fd \
--search-path $HOME/dev \
--type directory \
--exact-depth 2 \
| ${pkgs.proximity-sort}/bin/proximity-sort $PWD \
| sed 's/\\/$//' \
| fzf --tiebreak=index \
)
and cd $projdir
and commandline -f execute
'';
};
};
shellAbbrs = {
lsf = "ls -lh | fzf";
};
};
# Global fzf configuration
home.sessionVariables =
let
fzfCommand = "fd --type file";
in
{
FZF_DEFAULT_COMMAND = fzfCommand;
FZF_CTRL_T_COMMAND = fzfCommand;
FZF_DEFAULT_OPTS = "-m --height 50% --border";
};
home.packages = [
(pkgs.writeShellApplication {
name = "jqr";
runtimeInputs = [
pkgs.jq
pkgs.fzf
];
text = builtins.readFile ./bash/scripts/jqr.sh;
})
];
};
}

View File

@ -1,195 +0,0 @@
{
config,
pkgs,
lib,
...
}:
let
home-packages = config.home-manager.users.${config.user}.home.packages;
in
{
options = {
gitName = lib.mkOption {
type = lib.types.str;
description = "Name to use for git commits";
};
gitEmail = lib.mkOption {
type = lib.types.str;
description = "Email to use for git commits";
};
};
config = {
home-manager.users.root.programs.git = {
enable = true;
extraConfig.safe.directory = config.dotfilesPath;
};
home-manager.users.${config.user} = {
programs.git = {
enable = true;
userName = config.gitName;
userEmail = config.gitEmail;
extraConfig = {
core.pager = "${pkgs.git}/share/git/contrib/diff-highlight/diff-highlight | less -F";
interactive.difffilter = "${pkgs.git}/share/git/contrib/diff-highlight/diff-highlight";
pager = {
branch = "false";
};
safe = {
directory = config.dotfilesPath;
};
pull = {
ff = "only";
};
push = {
autoSetupRemote = "true";
};
init = {
defaultBranch = "master";
};
rebase = {
autosquash = "true";
};
gpg = {
format = "ssh";
ssh.allowedSignersFile = "~/.config/git/allowed-signers";
};
# commit.gpgsign = true;
# tag.gpgsign = true;
};
ignores = [
".direnv/**"
"result"
];
includes = [
{
path = "~/.config/git/personal";
condition = "gitdir:~/dev/personal/";
}
];
};
# Personal git config
# TODO: fix with variables
xdg.configFile."git/personal".text = ''
[user]
name = "${config.fullName}"
email = "7386960+nmasur@users.noreply.github.com"
signingkey = ~/.ssh/id_ed25519
[commit]
gpgsign = true
[tag]
gpgsign = true
'';
xdg.configFile."git/allowed-signers".text = ''
7386960+nmasur@users.noreply.github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+AbmjGEwITk5CK9y7+Rg27Fokgj9QEjgc9wST6MA3s
'';
programs.fish.shellAbbrs = {
g = "git";
gs = "git status";
gd = "git diff";
gds = "git diff --staged";
gdp = "git diff HEAD^";
ga = "git add";
gaa = "git add -A";
gac = "git commit -am";
gc = "git commit -m";
gca = "git commit --amend --no-edit";
gcae = "git commit --amend";
gu = "git pull";
gp = "git push";
gl = "git log --graph --decorate --oneline -20";
gll = "git log --graph --decorate --oneline";
gco = "git checkout";
gcom = ''git switch (git symbolic-ref refs/remotes/origin/HEAD | cut -d"/" -f4)'';
gcob = "git switch -c";
gb = "git branch";
gpd = "git push origin -d";
gbd = "git branch -d";
gbD = "git branch -D";
gdd = {
position = "anywhere";
setCursor = true;
expansion = "BRANCH=% git push origin -d $BRANCH and git branch -d $BRANCH";
};
gr = "git reset";
grh = "git reset --hard";
gm = "git merge";
gcp = "git cherry-pick";
cdg = "cd (git rev-parse --show-toplevel)";
};
# Required for fish commands
home.packages = with pkgs; [
fish
fzf
bat
];
programs.fish.functions =
lib.mkIf (builtins.elem pkgs.fzf home-packages && builtins.elem pkgs.bat home-packages)
{
git = {
body = builtins.readFile ./fish/functions/git.fish;
};
git-add-fuzzy = {
body = builtins.readFile ./fish/functions/git-add-fuzzy.fish;
};
git-fuzzy-branch = {
argumentNames = "header";
body = builtins.readFile ./fish/functions/git-fuzzy-branch.fish;
};
git-checkout-fuzzy = {
body = ''
set branch (git-fuzzy-branch "checkout branch...")
and git checkout $branch
'';
};
git-delete-fuzzy = {
body = ''
set branch (git-fuzzy-branch "delete branch...")
and git branch -d $branch
'';
};
git-force-delete-fuzzy = {
body = ''
set branch (git-fuzzy-branch "force delete branch...")
and git branch -D $branch
'';
};
git-delete-both = {
argumentNames = "branch";
body = ''
git push origin -d $branch
git branch -d $branch
'';
};
git-merge-fuzzy = {
body = ''
set branch (git-fuzzy-branch "merge from...")
and git merge $branch
'';
};
git-show-fuzzy = {
body = builtins.readFile ./fish/functions/git-show-fuzzy.fish;
};
git-commits = {
body = builtins.readFile ./fish/functions/git-commits.fish;
};
git-history = {
body = builtins.readFile ./fish/functions/git-history.fish;
};
uncommitted = {
description = "Find uncommitted git repos";
body = builtins.readFile ./fish/functions/uncommitted.fish;
};
};
};
};
}

View File

@ -1,89 +0,0 @@
{
config,
pkgs,
lib,
...
}:
{
unfreePackages = [ "gh-copilot" ];
home-manager.users.${config.user} = {
programs.gh = lib.mkIf config.home-manager.users.${config.user}.programs.git.enable {
enable = true;
gitCredentialHelper.enable = true;
settings.git_protocol = "https";
extensions = [
pkgs.gh-collaborators
pkgs.gh-dash
pkgs.gh-copilot
];
};
programs.fish = lib.mkIf config.home-manager.users.${config.user}.programs.gh.enable {
shellAbbrs = {
ghr = "gh repo view -w";
gha = "gh run list | head -1 | awk '{ print \\$\\(NF-2\\) }' | xargs gh run view";
grw = "gh run watch";
grf = "gh run view --log-failed";
grl = "gh run view --log";
ghpr = "gh pr create && sleep 3 && gh run watch";
# https://github.com/cli/cli/discussions/4067
prs = "gh search prs --state=open --review-requested=@me";
};
functions = {
repos = {
description = "Clone GitHub repositories";
argumentNames = "organization";
body = ''
set directory (gh-repos $organization)
and cd $directory
'';
};
};
};
home.packages = [
(pkgs.writeShellScriptBin "gh-repos" ''
case $1 in
t2) organization="take-two" ;;
d2c) organization="take-two-t2gp" ;;
t2gp) organization="take-two-t2gp" ;;
pd) organization="private-division" ;;
dots) organization="playdots" ;;
*) organization="nmasur" ;;
esac
selected=$(gh repo list "$organization" \
--limit 1000 \
--no-archived \
--json=name,description,isPrivate,updatedAt,primaryLanguage \
| jq -r '.[] | .name + "," + if .description == "" then "-" else .description |= gsub(","; " ") | .description end + "," + .updatedAt + "," + .primaryLanguage.name' \
| (echo "REPO,DESCRIPTION,UPDATED,LANGUAGE"; cat -) \
| column -s , -t \
| fzf \
--header-lines=1 \
--layout=reverse \
--height=100% \
--bind "ctrl-o:execute:gh repo view -w ''${organization}/{1}" \
--bind "shift-up:preview-half-page-up" \
--bind "shift-down:preview-half-page-down" \
--preview "GH_FORCE_TTY=49% gh repo view ''${organization}/{1} | glow -" \
--preview-window up
)
[ -n "''${selected}" ] && {
directory="$HOME/dev/work"
if [ $organization = "nmasur" ]; then directory="$HOME/dev/personal"; fi
repo=$(echo "''${selected}" | awk '{print $1}')
repo_full="''${organization}/''${repo}"
if [ ! -d "''${directory}/''${repo}" ]; then
gh repo clone "$repo_full" "''${directory}/''${repo}"
fi
echo "''${directory}/''${repo}"
}
'')
];
};
}

View File

@ -1,18 +0,0 @@
{ config, ... }:
{
config = {
home-manager.users.${config.user}.programs.jujutsu = {
enable = true;
# https://github.com/martinvonz/jj/blob/main/docs/config.md
settings = {
user = {
name = config.home-manager.users.${config.user}.programs.git.userName;
email = config.home-manager.users.${config.user}.programs.git.userEmail;
};
};
};
};
}

View File

@ -1,133 +0,0 @@
{
config,
pkgs,
lib,
...
}:
{
home-manager.users.${config.user} = {
programs.fish = {
shellAbbrs = {
n = "nix";
ns = "nix-shell -p";
nsf = "nix-shell --run fish -p";
nsr = "nix-shell-run";
nps = "nix repl --expr 'import <nixpkgs>{}'";
nixo = "man configuration.nix";
nixh = "man home-configuration.nix";
nr = {
function = "rebuild-nixos";
};
nro = {
function = "rebuild-nixos-offline";
};
hm = {
function = "rebuild-home";
};
};
functions = {
nix-shell-run = {
body = ''
set program $argv[1]
if test (count $argv) -ge 2
commandline -r "nix run nixpkgs#$program -- $argv[2..-1]"
else
commandline -r "nix run nixpkgs#$program"
end
commandline -f execute
'';
};
nix-fzf = {
body = ''
commandline -i (nix-instantiate --eval --json \
-E 'builtins.attrNames (import <nixpkgs> {})' \
| jq '.[]' -r | fzf)
commandline -f repaint
'';
};
rebuild-nixos = {
body = ''
git -C ${config.dotfilesPath} add --intent-to-add --all
echo "doas nixos-rebuild switch --flake ${config.dotfilesPath}#${config.networking.hostName}"
'';
};
rebuild-nixos-offline = {
body = ''
git -C ${config.dotfilesPath} add --intent-to-add --all
echo "doas nixos-rebuild switch --option substitute false --flake ${config.dotfilesPath}#${config.networking.hostName}"
'';
};
rebuild-home = {
body = ''
git -C ${config.dotfilesPath} add --intent-to-add --all
echo "${pkgs.home-manager}/bin/home-manager switch --flake ${config.dotfilesPath}#${config.networking.hostName}";
'';
};
};
};
# Provides "command-not-found" options
programs.nix-index = {
enable = true;
enableFishIntegration = true;
};
# Create nix-index if doesn't exist
home.activation.createNixIndex =
let
cacheDir = "${config.homePath}/.cache/nix-index";
in
lib.mkIf config.home-manager.users.${config.user}.programs.nix-index.enable (
config.home-manager.users.${config.user}.lib.dag.entryAfter [ "writeBoundary" ] ''
if [ ! -d ${cacheDir} ]; then
$DRY_RUN_CMD ${pkgs.nix-index}/bin/nix-index -f ${pkgs.path}
fi
''
);
# Set automatic generation cleanup for home-manager
nix.gc = {
automatic = config.nix.gc.automatic;
options = config.nix.gc.options;
};
};
nix = {
# Set channel to flake packages, used for nix-shell commands
nixPath = [ "nixpkgs=${pkgs.path}" ];
# For security, only allow specific users
settings.allowed-users = [
"@wheel"
config.user
];
# Enable features in Nix commands
extraOptions = ''
experimental-features = nix-command flakes
warn-dirty = false
'';
gc = {
automatic = true;
options = "--delete-older-than 10d";
};
settings = {
# Add community Cachix to binary cache
# Don't use with macOS because blocked by corporate firewall
builders-use-substitutes = true;
substituters = lib.mkIf (!pkgs.stdenv.isDarwin) [ "https://nix-community.cachix.org" ];
trusted-public-keys = lib.mkIf (!pkgs.stdenv.isDarwin) [
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
# Scans and hard links identical files in the store
# Not working with macOS: https://github.com/NixOS/nix/issues/7273
auto-optimise-store = lib.mkIf (!pkgs.stdenv.isDarwin) true;
};
};
}

View File

@ -1,72 +0,0 @@
{
config,
pkgs,
lib,
...
}:
{
home-manager.users.${config.user}.programs.starship = {
enable = true;
settings = {
add_newline = false; # Don't print new line at the start of the prompt
format = lib.concatStrings [
"$directory"
"$git_branch"
"$git_commit"
"$git_status"
"$hostname"
"$cmd_duration"
"$character"
];
right_format = "$nix_shell";
character = {
success_symbol = "[](bold green)";
error_symbol = "[](bold red)";
vicmd_symbol = "[](bold green)";
};
cmd_duration = {
min_time = 5000;
show_notifications = if pkgs.stdenv.isLinux then false else true;
min_time_to_notify = 30000;
format = "[$duration]($style) ";
};
directory = {
truncate_to_repo = true;
truncation_length = 100;
};
git_branch = {
format = "[$symbol$branch]($style)";
};
git_commit = {
format = "( @ [$hash]($style) )";
only_detached = false;
};
git_status = {
format = "([$all_status$ahead_behind]($style) )";
conflicted = "=";
ahead = "";
behind = "";
diverged = "";
untracked = "";
stashed = "";
modified = "";
staged = "+";
renamed = "»";
deleted = "";
style = "red";
};
hostname = {
ssh_only = true;
format = "on [$hostname](bold red) ";
};
nix_shell = {
format = "[$symbol $name]($style)";
symbol = "";
};
python = {
format = "[\${version}\\(\${virtualenv}\\)]($style)";
};
};
};
}

View File

@ -1,77 +0,0 @@
{ config, pkgs, ... }:
let
ignorePatterns = ''
!.env*
!.github/
!.gitignore
!*.tfvars
.terraform/
.target/
/Library/'';
in
{
config = {
home-manager.users.${config.user} = {
home.packages = with pkgs; [
age # Encryption
bc # Calculator
delta # Fancy diffs
difftastic # Other fancy diffs
dig # DNS lookup
fd # find
htop # Show system processes
killall # Force quit
inetutils # Includes telnet, whois
jless # JSON viewer
jo # JSON output
jq # JSON manipulation
lf # File viewer
osc # Clipboard over SSH
qrencode # Generate qr codes
rsync # Copy folders
# ren # Rename files
# rep # Replace text in files
ripgrep # grep
sd # sed
spacer # Output lines in terminal
tealdeer # Cheatsheets
tree # View directory hierarchy
vimv-rs # Batch rename files
unzip # Extract zips
dua # File sizes (du)
du-dust # Disk usage tree (ncdu)
duf # Basic disk information (df)
];
programs.zoxide.enable = true; # Shortcut jump command
home.file = {
".rgignore".text = ignorePatterns;
".digrc".text = "+noall +answer"; # Cleaner dig commands
};
xdg.configFile."fd/ignore".text = ignorePatterns;
programs.bat = {
enable = true; # cat replacement
config = {
theme = config.theme.colors.batTheme;
pager = "less -R"; # Don't auto-exit if one screen
};
};
programs.fish.functions = {
ping = {
description = "Improved ping";
argumentNames = "target";
body = "${pkgs.prettyping}/bin/prettyping --nolegend $target";
};
};
};
};
}

View File

@ -1,59 +0,0 @@
{
config,
pkgs,
lib,
...
}:
{
home-manager.users.${config.user} = lib.mkIf pkgs.stdenv.isDarwin {
home.packages =
let
ldap_scheme = "ldaps";
magic_prefix = "take";
ldap_port = 3269;
jq_parse = pkgs.writeShellScriptBin "ljq" ''
jq --slurp \
--raw-input 'split("\n\n")|map(split("\n")|map(select(.[0:1]!="#" and length>0)) |select(length > 0)|map(capture("^(?<key>[^:]*:?): *(?<value>.*)") |if .key[-1:.key|length] == ":" then .key=.key[0:-1]|.value=(.value|@base64d) else . end)| group_by(.key) | map({key:.[0].key,value:(if .|length > 1 then [.[].value] else .[].value end)}) | from_entries)' | jq -r 'del(.[].thumbnailPhoto)'
'';
ldap_script = pkgs.writeShellScriptBin "ldap" ''
if ! [ "$LDAP_HOST" ]; then
echo "No LDAP_HOST specified!"
exit 1
fi
SEARCH_FILTER="$@"
ldapsearch -LLL \
-B -o ldif-wrap=no \
-E pr=5000/prompt \
-H "${ldap_scheme}://''${LDAP_HOST}:${builtins.toString ldap_port}" \
-D "${pkgs.lib.toUpper magic_prefix}2\\${pkgs.lib.toLower config.user}" \
-w "$(${pkgs._1password-cli}/bin/op item get T2 --fields label=password --reveal)" \
-b "dc=''${LDAP_HOST//./,dc=}" \
-s "sub" -x "(cn=''${SEARCH_FILTER})" \
| ${jq_parse}/bin/ljq
'';
ldapm_script = pkgs.writeShellScriptBin "ldapm" ''
if ! [ "$LDAP_HOST" ]; then
echo "No LDAP_HOST specified!"
exit 1
fi
${ldap_script}/bin/ldap "$@" | jq '[ .[].memberOf] | add'
'';
ldapg_script = pkgs.writeShellScriptBin "ldapg" ''
if ! [ "$LDAP_HOST" ]; then
echo "No LDAP_HOST specified!"
exit 1
fi
${ldap_script}/bin/ldap "$@" | jq '[ .[].member] | add'
'';
in
[
ldap_script
ldapm_script
ldapg_script
jq_parse
];
};
}