1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-11-08 11:36:05 +01:00
home-manager/modules/lib/shell.nix
Austin Horstman a8dbb4e325 lib/shell: add formatShellArrayContent function for intelligent width optimization
Add shared utility function that formats shell arrays with smart width optimization.
Packs multiple items per line based on available width (~78 chars per line) while
maintaining readability. Includes helper functions wrapLines and formatMultiLine.

Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
2025-09-27 13:18:01 -05:00

102 lines
3.5 KiB
Nix

{ lib }:
let
mkShellIntegrationOption =
name:
{
config,
baseName ? name,
extraDescription ? "",
}:
let
attrName = "enable${baseName}Integration";
in
lib.mkOption {
default = config.home.shell.${attrName};
defaultText = lib.literalMD "[](#opt-home.shell.${attrName})";
example = false;
description = "Whether to enable ${name} integration.${
lib.optionalString (extraDescription != "") ("\n\n" + extraDescription)
}";
type = lib.types.bool;
};
in
rec {
# Produces a Bourne shell like statement that prepend new values to
# an possibly existing variable, using sep(arator).
# Example:
# prependToVar ":" "PATH" [ "$HOME/bin" "$HOME/.local/bin" ]
# => "$HOME/bin:$HOME/.local/bin:${PATH:+:}\$PATH"
prependToVar =
sep: n: v:
"${lib.concatStringsSep sep v}\${${n}:+${sep}}\$${n}";
# Produces a Bourne shell like variable export statement.
export = n: v: ''export ${n}="${toString v}"'';
# Given an attribute set containing shell variable names and their
# assignment, this function produces a string containing an export
# statement for each set entry.
exportAll = vars: lib.concatStringsSep "\n" (lib.mapAttrsToList export vars);
# Wrap a list of strings to a given line width.
# Packs as many items as possible per line without exceeding maxWidth.
# Returns a list of strings, each representing a line.
#
# Example: wrapLines ["item1" "item2" "very-long-item" "item3"] 20
# => ["item1 item2" "very-long-item" "item3"]
wrapLines =
items: maxWidth:
let
step =
acc: item:
let
potentialLine = if acc.currentLine == "" then item else "${acc.currentLine} ${item}";
in
if lib.stringLength potentialLine <= maxWidth then
acc // { currentLine = potentialLine; }
else
acc
// {
finishedLines = acc.finishedLines ++ [ acc.currentLine ];
currentLine = item;
};
foldResult = lib.foldl' step {
finishedLines = [ ];
currentLine = "";
} items;
in
foldResult.finishedLines ++ lib.optional (foldResult.currentLine != "") foldResult.currentLine;
# Formats a list of items for shell array content with intelligent width optimization.
# IMPORTANT: This formats the CONTENTS of an array (what goes inside parentheses),
# not a complete array definition. Use lib.hm.zsh.define for complete definitions.
#
# Uses lib.escapeShellArg for robust shell escaping (handles spaces, quotes, special chars).
# Packs multiple items per line to optimize terminal width (~78 chars per line).
# Short arrays (≤3 items, ≤80 chars total) use single-line format.
#
# Example outputs:
# Empty: ""
# Simple: item1 item2 item3
# With spaces: 'item one' 'item two' 'item three'
# Long arrays: \n item1 item2 item3\n item4 item5\n
#
# Built from composable helpers: wrapLines, formatMultiLine
formatShellArrayContent =
items:
let
quotedItems = lib.map lib.escapeShellArg items;
formatMultiLine = lines: "\n ${lib.concatStringsSep "\n " lines}\n";
wrapped = wrapLines quotedItems 78;
in
formatMultiLine wrapped;
mkBashIntegrationOption = mkShellIntegrationOption "Bash";
mkFishIntegrationOption = mkShellIntegrationOption "Fish";
mkIonIntegrationOption = mkShellIntegrationOption "Ion";
mkNushellIntegrationOption = mkShellIntegrationOption "Nushell";
mkZshIntegrationOption = mkShellIntegrationOption "Zsh";
}