#[derive(Debug, Clone)]
pub struct TooltipContent {
pub function: &'static str,
pub description: &'static str,
pub examples: &'static [&'static str],
pub tip: Option<&'static str>,
}
impl TooltipContent {
pub const fn new(
function: &'static str,
description: &'static str,
examples: &'static [&'static str],
tip: Option<&'static str>,
) -> Self {
Self {
function,
description,
examples,
tip,
}
}
}
pub static TOOLTIP_CONTENT: &[TooltipContent] = &[
TooltipContent::new(
"map",
"Apply expression to each element of an array",
&[
"map(.name) # extract field from each",
"map(. + 1) # increment each number",
"map(select(.active)) # filter to active items",
"map({id, name}) # reshape each object",
],
Some("Use [.[] | expr] for same result - less memory for large arrays"),
),
TooltipContent::new(
"select",
"Filter elements that match a condition",
&[
"select(.age > 18) # numeric filter",
"select(.status == \"active\") # exact match",
"select(.tags | contains([\"important\"])) # array check",
"select(.name | test(\"^test\"; \"i\")) # regex match",
],
Some("For null-safe checks, use select(.field? // false)"),
),
TooltipContent::new(
"sort_by",
"Sort array elements by a computed value",
&[
"sort_by(.name) # sort by field",
"sort_by(.date) | reverse # sort descending",
"sort_by(-.price) # descending (cleaner)",
"sort_by(.price | tonumber) # ensure numeric",
],
Some("Use sort_by(-.field) instead of sort_by(.field) | reverse"),
),
TooltipContent::new(
"group_by",
"Group array elements by a computed key",
&[
"group_by(.category) # group by field",
"group_by(.type) | map({type: .[0].type, count: length})",
"group_by(.date[:10]) # group by date part",
],
Some("Output sorted by key; use map({key: .[0].field, values: .})"),
),
TooltipContent::new(
"unique_by",
"Remove duplicates based on a computed key",
&[
"unique_by(.id) # dedupe by ID",
"unique_by(.email | ascii_downcase) # case-insensitive",
"unique_by([.first, .last]) # by multiple fields",
],
Some(
"Keeps FIRST occurrence; output is SORTED; use group_by | map(first) to preserve order",
),
),
TooltipContent::new(
"min_by",
"Find element with minimum value by expression",
&[
"min_by(.price) # object with lowest price",
"min_by(.date) # earliest by date",
"min_by(.name | length) # shortest name",
],
Some("Returns entire object; use .field after: max_by(.score).score"),
),
TooltipContent::new(
"max_by",
"Find element with maximum value by expression",
&[
"max_by(.score) # object with highest score",
"max_by(.date | fromdateiso8601) # most recent by ISO date",
"max_by(.name | length) # longest name",
],
Some("Returns entire object; use .field after: max_by(.score).score"),
),
TooltipContent::new(
"limit",
"Take only first N results from a generator",
&[
"limit(5; .[]) # first 5 elements",
"limit(10; recurse) # limit recursion",
"limit(3; .[] | select(.active)) # first 3 matches",
"[limit(100; inputs)] # first 100 JSONL lines",
],
Some("More efficient than [:5] - stops early; essential with recurse"),
),
TooltipContent::new(
"nth",
"Get the nth element from a generator",
&[
"nth(0) # first element (same as first)",
"nth(2; .[]) # third element from array",
"nth(0; .[] | select(.valid)) # first valid element",
],
Some("Use first/last for clearer code; nth for specific positions"),
),
TooltipContent::new(
"range",
"Generate a sequence of numbers",
&[
"range(5) # 0, 1, 2, 3, 4",
"range(1; 11) # 1 to 10 (end exclusive)",
"range(0; 100; 10) # 0, 10, 20, ..., 90",
"[range(5)] | map(. * 2) # [0,2,4,6,8]",
],
Some("End is EXCLUSIVE (like Python); wrap in [range(n)] for array"),
),
TooltipContent::new(
"until",
"Repeat until condition is true",
&[
"until(. >= 100; . * 2) # returns 128 (final value only)",
"1 | until(. > 10; . + 1) # returns 11",
],
Some("Returns FINAL value only; use while for ALL intermediate values"),
),
TooltipContent::new(
"while",
"Repeat while condition is true",
&[
"[while(. < 100; . * 2)] # [1,2,4,8,16,32,64] (all values)",
"[1 | while(. <= 10; . + 1)] # [1,2,3,4,5,6,7,8,9,10]",
],
Some("Returns ALL intermediate values as stream; wrap in [] for array"),
),
TooltipContent::new(
"recurse",
"Recursively apply expression (depth-first traversal)",
&[
"recurse(.children[]?) # traverse tree via children field",
"recurse | .name? # get all \"name\" fields in tree",
"recurse(.next?) | .value # follow linked list",
],
Some("Use .. as shorthand; add ? for missing fields; use limit() always"),
),
TooltipContent::new(
"walk",
"Transform all values recursively (bottom-up)",
&[
"walk(if type == \"string\" then ascii_downcase else . end)",
"walk(if type == \"object\" then del(.internal) else . end)",
"walk(if . == null then \"N/A\" else . end) # replace nulls",
],
Some("Processes BOTTOM-UP (children before parents); use recurse for top-down"),
),
TooltipContent::new(
"with_entries",
"Transform object's key-value pairs",
&[
"with_entries(.value |= . + 1) # increment all values",
"with_entries(select(.value != null)) # remove null values",
"with_entries(.key |= \"prefix_\" + .) # prefix all keys",
"with_entries(select(.key | startswith(\"public_\")))",
],
Some("Shorthand for to_entries | map(...) | from_entries"),
),
TooltipContent::new(
"has",
"Check if object has a specific key",
&[
"has(\"email\") # check if key exists",
"select(has(\"config\")) # filter objects that have config",
"if has(\"error\") then .error else \"ok\" end",
"has(\"key\") and .key != null # key exists AND not null",
],
Some("Only checks key existence; use .key? // default for null-safe access"),
),
TooltipContent::new(
"del",
"Delete keys or paths from object/array",
&[
"del(.password, .secret) # remove sensitive fields",
"del(.users[0]) # remove first array element",
"del(.config.debug) # remove nested field",
"map(del(.internal)) # remove field from all objects",
],
Some("For pattern matching: with_entries(select(.key | test(\"x\") | not))"),
),
TooltipContent::new(
"getpath",
"Get value using dynamic path array",
&[
"getpath([\"user\", \"address\", \"city\"]) # nested access",
"getpath([\"items\", 0]) # get first item",
"getpath($path) # variable path",
],
Some("Use .a.b.c for static paths; getpath for dynamic/computed paths"),
),
TooltipContent::new(
"setpath",
"Set value using dynamic path array",
&[
"setpath([\"config\", \"enabled\"]; true) # set nested",
"setpath([\"items\", 0]; \"new\") # set by index",
],
Some("Creates intermediate objects/arrays as needed"),
),
TooltipContent::new(
"delpaths",
"Delete multiple paths at once",
&[
"delpaths([[\"a\"], [\"b\", \"c\"]]) # delete paths",
"delpaths([paths(type == \"null\")]) # delete nulls",
"delpaths([paths(. == \"\")]) # delete empty",
],
Some("Combine with [paths(...)] - more efficient than chaining del()"),
),
TooltipContent::new(
"split",
"Split string to array by delimiter",
&[
"split(\",\") # \"a,b,c\" -> [\"a\",\"b\",\"c\"]",
"split(\"\\n\") | map(select(. != \"\")) # split lines",
"[.items[].name] | join(\" | \") # join values",
],
Some("Use splits(\"\\\\s+\") for regex splitting (e.g., by whitespace)"),
),
TooltipContent::new(
"join",
"Join array to string with delimiter",
&[
"join(\", \") # [\"a\",\"b\"] -> \"a, b\"",
"[.items[].name] | join(\" | \") # join field values",
],
Some("Ensure all elements are strings first with map(tostring) if needed"),
),
TooltipContent::new(
"ltrimstr",
"Remove prefix from string",
&[
"ltrimstr(\"https://\") # remove URL scheme",
"ltrimstr(\"v\") | tonumber # parse version number",
],
Some("Safe if prefix doesn't exist (returns unchanged); use sub() for regex"),
),
TooltipContent::new(
"rtrimstr",
"Remove suffix from string",
&[
"rtrimstr(\".json\") # remove file extension",
".filename | rtrimstr(\".bak\") # remove backup suffix",
],
Some("Safe if suffix doesn't exist (returns unchanged); use sub() for regex"),
),
TooltipContent::new(
"startswith",
"Check if string starts with prefix",
&[
"select(startswith(\"http\")) # filter URLs",
"select(.path | startswith(\"/api/\")) # filter API paths",
"if endswith(\".json\") then \"JSON\" else \"other\" end",
],
Some("For case-insensitive: use test(\"^pattern\"; \"i\") instead"),
),
TooltipContent::new(
"endswith",
"Check if string ends with suffix",
&[
"select(endswith(\".json\")) # filter by suffix",
"select(.email | endswith(\"@company.com\")) # by domain",
],
Some("For case-insensitive: use test(\"pattern$\"; \"i\") instead"),
),
TooltipContent::new(
"test",
"Test if string matches regex pattern",
&[
"test(\"^[0-9]+$\") # all digits",
"test(\"[a-z]\"; \"i\") # case-insensitive",
"select(test(\"error|warning\"; \"i\")) # filter logs",
"test(\"\\\\d{4}-\\\\d{2}-\\\\d{2}\") # date YYYY-MM-DD",
],
Some("Flags: i=case-insensitive, x=extended, m=multiline, s=single-line"),
),
TooltipContent::new(
"match",
"Extract regex match information",
&[
"match(\"v([0-9]+)\\\\.([0-9]+)\") | .captures[].string",
"match(\"\\\\d+\"; \"g\") | .string # all matches (global)",
],
Some("Use capture() for named groups - returns object with field names"),
),
TooltipContent::new(
"capture",
"Extract named capture groups from regex",
&[
"capture(\"(?<user>[^@]+)@(?<domain>.+)\") # email",
"capture(\"(?<y>\\\\d{4})-(?<m>\\\\d{2})-(?<d>\\\\d{2})\") # date",
],
Some("Returns object with named fields; cleaner than match()"),
),
TooltipContent::new(
"scan",
"Find all regex matches (returns stream)",
&[
"[scan(\"[0-9]+\")] # extract all numbers as array",
"[scan(\"\\\\w+\")] # extract all words",
"scan(\"https?://[^\\\\s]+\") # extract all URLs",
"[scan(\"[A-Z]{2,}\")] | unique # find all acronyms",
],
Some("Returns STREAM, not array - wrap in [] to collect"),
),
TooltipContent::new(
"splits",
"Split by regex pattern (returns stream)",
&[
"[splits(\"\\\\s+\")] # split by whitespace",
"[splits(\"[,;]\\\\s*\")] # split by comma or semicolon",
"[splits(\"::\")] | .[1] # get second segment",
],
Some("Returns STREAM; use split() for literal delimiters"),
),
TooltipContent::new(
"sub",
"Replace first regex match",
&[
"sub(\"old\"; \"new\") # replace first occurrence",
"sub(\"^v\"; \"\") # remove leading 'v'",
],
Some("Use gsub() to replace ALL occurrences"),
),
TooltipContent::new(
"gsub",
"Replace all regex matches",
&[
"gsub(\"\\\\s+\"; \" \") # normalize whitespace",
"gsub(\"[^a-zA-Z0-9]\"; \"_\") # sanitize to alphanumeric",
"gsub(\"(?<n>\\\\d+)\"; \"[\\(.n)]\") # wrap numbers in brackets",
],
Some("Use capture groups in replacement with \\(.name) syntax"),
),
TooltipContent::new(
"contains",
"Check if value contains another",
&[
"contains(\"error\") # string contains substring",
".tags | contains([\"urgent\"]) # array contains element",
"{a:1} | contains({a:1}) # object contains keys/values",
],
Some("For regex or case-insensitive matching: use test() instead"),
),
TooltipContent::new(
"inside",
"Check if value is contained by another",
&[
"\"sub\" | inside(\"substring\") # is substring",
"[1] | inside([1,2,3]) # is subarray",
],
Some("Inverse of contains: a|inside(b) == b|contains(a)"),
),
TooltipContent::new(
"index",
"Find first position of value",
&[
"index(\",\") # first comma position",
"[1,2,3,2] | index(2) # returns 1",
],
Some("Returns null if not found (not -1 like other languages)"),
),
TooltipContent::new(
"rindex",
"Find last position of value",
&[
"rindex(\"/\") # last slash position",
"[1,2,3,2] | rindex(2) # returns 3",
".path | rindex(\"/\") as $i | .[$i+1:] # filename",
],
Some("Returns null if not found (not -1 like other languages)"),
),
TooltipContent::new(
"indices",
"Find all positions of value",
&[
"indices(\",\") # all comma positions",
"[1,2,3,2] | indices(2) # returns [1,3]",
],
Some("Returns empty array if not found"),
),
TooltipContent::new(
"strftime",
"Format timestamp with custom format",
&[
"now | strftime(\"%Y-%m-%d %H:%M:%S\") # custom format",
"now | strftime(\"%B %d, %Y\") # \"January 15, 2024\"",
],
Some("%Y=year, %m=month, %d=day, %H=hour, %M=minute, %S=second"),
),
TooltipContent::new(
"strptime",
"Parse date string with custom format",
&[
"\"2024-01-15\" | strptime(\"%Y-%m-%d\") | .[0]",
"\"Jan 15, 2024\" | strptime(\"%b %d, %Y\") | mktime",
],
Some("Returns [seconds, tz_offset]; use .[0] or mktime for timestamp"),
),
TooltipContent::new(
"fromdate",
"Parse ISO 8601 date string to timestamp",
&[
"\"2024-01-15T10:30:00Z\" | fromdate # to timestamp",
".created_at | fromdate | . + 86400 | todate # add 1 day",
"[.events[].date | fromdate] | min | todate # earliest",
],
Some("ISO 8601 only; use strptime for custom formats"),
),
TooltipContent::new(
"todate",
"Format timestamp as ISO 8601",
&[
"now | todate # current time as ISO 8601",
".timestamp | todate # format unix timestamp",
],
Some("ISO 8601 only; use strftime for custom formats"),
),
TooltipContent::new(
"keys",
"Get object keys or array indices",
&[
"keys # sorted keys: [\"a\",\"b\",\"c\"]",
"keys | length # count of keys",
"keys | map(select(startswith(\"_\"))) # private keys only",
],
Some("SORTS output alphabetically; use keys_unsorted to preserve order"),
),
TooltipContent::new(
"keys_unsorted",
"Get object keys in original order",
&[
"keys_unsorted # preserve original order",
".config | keys_unsorted # list config keys as defined",
],
Some("Use when order matters (e.g., preserving config file order)"),
),
TooltipContent::new(
"values",
"Get all values from object or array",
&[
"values # all values (strips keys)",
".config | values | add # sum all config values",
"values | map(select(. != null)) # non-null values only",
],
Some("Same as .[] but clearer intent; does NOT filter nulls"),
),
TooltipContent::new(
"sort",
"Sort array ascending",
&[
"sort # sort ascending",
"sort | reverse # sort descending",
"sort | unique # sort and dedupe",
],
Some("Works on numbers, strings, mixed; use sort_by(.field) for objects"),
),
TooltipContent::new(
"reverse",
"Reverse array order",
&[
"reverse # reverse array order",
".logs | reverse | first # most recent log entry",
],
Some("Use .[-1] instead of reverse | first for just the last element"),
),
TooltipContent::new(
"unique",
"Remove duplicate values (sorts output)",
&[
"unique # remove duplicates",
"[.items[].category] | unique # unique values of field",
"unique | length # count distinct values",
],
Some("Output is always SORTED; use unique_by(.field) for objects"),
),
TooltipContent::new(
"flatten",
"Flatten nested arrays",
&[
"flatten # flatten all levels",
"flatten(1) # flatten one level only",
"[[1,2],[3,[4,5]]] | flatten # [1,2,3,4,5]",
".pages[].items | flatten # combine paginated results",
],
Some("Use add to concatenate arrays without deep flattening"),
),
TooltipContent::new(
"add",
"Sum numbers or concatenate arrays/strings",
&[
"[.items[].price] | add # sum prices",
"[\"a\",\"b\",\"c\"] | add # \"abc\" (string concat)",
"[[1,2],[3,4]] | add # [1,2,3,4] (array concat)",
"[.counts[]] | add // 0 # sum with default 0 for empty",
],
Some("Returns NULL for empty arrays - use // 0 or // \"\" for defaults"),
),
TooltipContent::new(
"length",
"Length of string/array/object, absolute value of number",
&[
"length # element count",
".items | length # array length",
"select(length > 0) # filter non-empty",
"select(.name | length <= 50) # max name length",
],
Some("Returns 0 for null; for byte length use utf8bytelength"),
),
TooltipContent::new(
"first",
"First element from array or generator",
&[
"first # first element",
"first(.[] | select(.valid)) # first valid item",
"last(inputs) # last line from JSONL",
],
Some("More efficient than .[0] for generators and large streams"),
),
TooltipContent::new(
"last",
"Last element from array or generator",
&[
"last # last element",
"last(.[] | select(.type == \"error\")) # last error",
],
Some("Use .[-1] for arrays; last() essential for generators"),
),
TooltipContent::new(
"min",
"Minimum value in array",
&[
"min # minimum value",
"[.items[].price] | min # lowest price",
],
Some("Returns value, not object; returns null for empty; use min_by()"),
),
TooltipContent::new(
"max",
"Maximum value in array",
&[
"max # maximum value",
"[.scores[]] | max # highest score",
],
Some("Returns value, not object; returns null for empty; use max_by()"),
),
TooltipContent::new(
"transpose",
"Transpose matrix (swap rows and columns)",
&[
"[[1,2],[3,4]] | transpose # [[1,3],[2,4]]",
"[.names, .ages] | transpose # zip arrays",
"[.headers, .values] | transpose | map({(.[0]): .[1]}) | add",
],
Some("Great for zipping arrays; uses nulls for different lengths"),
),
TooltipContent::new(
"to_entries",
"Convert object to key-value pairs",
&[
"to_entries # object to [{key,value},...]",
"to_entries | map(.value += 1) | from_entries",
],
Some("Use with_entries for transform+convert in one step"),
),
TooltipContent::new(
"from_entries",
"Convert key-value pairs to object",
&[
"from_entries # [{key,value},...] to object",
"[{key:\"a\",value:1}] | from_entries # {\"a\":1}",
],
Some("Also accepts {name,value} or {k,v} pairs"),
),
TooltipContent::new(
"paths",
"Get all paths in structure",
&[
"paths # all paths in structure",
"[paths(type == \"string\")] # paths to all strings",
],
Some("Use with getpath/setpath for dynamic access"),
),
TooltipContent::new(
"leaf_paths",
"Get paths to leaf values only",
&[
"[paths(scalars)] # recommended alternative",
"leaf_paths # deprecated - avoid",
],
Some("DEPRECATED in jq 1.7+; use paths(scalars) instead"),
),
TooltipContent::new(
"type",
"Get the type name of a value",
&[
"type # \"string\", \"number\", etc.",
"select(type == \"object\") # filter by type",
".[] | select(type != \"null\") # remove nulls",
"group_by(type) # group by type",
],
Some("Use arrays, objects, etc. for type filtering - cleaner and faster"),
),
TooltipContent::new(
"tostring",
"Convert to string",
&[
".id | tostring # ensure string type",
"(.count | tostring) + \" items\" # string concatenation",
],
Some("Use @json for JSON-encoded string; tostring on strings is no-op"),
),
TooltipContent::new(
"tonumber",
"Convert to number",
&[
".price | tonumber # parse string to number",
".amount | tonumber? // 0 # safe parse with default",
],
Some("Throws error on invalid input - use tonumber? // default"),
),
TooltipContent::new(
"tojson",
"Convert value to JSON string",
&[
"tojson # encode value as JSON string",
".config | tojson # serialize object to JSON",
".data | tojson | @base64 # encode JSON as base64",
],
Some("Use @json format string for similar effect; tojson always valid JSON"),
),
TooltipContent::new(
"fromjson",
"Parse JSON string to value",
&[
"fromjson # parse JSON string",
".payload | fromjson # decode JSON field",
".json_str | fromjson? // {} # safe parse with default",
],
Some("Throws error on invalid JSON - use fromjson? // default for safety"),
),
TooltipContent::new(
"arrays",
"Filter to keep only arrays",
&[".[] | arrays # keep only arrays"],
Some("Cleaner than select(type == \"array\")"),
),
TooltipContent::new(
"objects",
"Filter to keep only objects",
&[
".[] | objects # keep only objects",
".[] | objects | .name # names from object children only",
],
Some("Cleaner than select(type == \"object\")"),
),
TooltipContent::new(
"iterables",
"Filter to keep arrays and objects",
&[
"iterables # arrays and objects",
".[] | iterables # only nested structures",
],
Some("Opposite of scalars"),
),
TooltipContent::new(
"booleans",
"Filter to keep only booleans",
&[".[] | booleans # keep only booleans"],
Some("Cleaner than select(type == \"boolean\")"),
),
TooltipContent::new(
"numbers",
"Filter to keep only numbers",
&[".[] | numbers # keep only numbers"],
Some("Cleaner than select(type == \"number\")"),
),
TooltipContent::new(
"strings",
"Filter to keep only strings",
&[".[] | strings # keep only strings"],
Some("Cleaner than select(type == \"string\")"),
),
TooltipContent::new(
"nulls",
"Filter to keep only nulls",
&[".[] | nulls # keep only nulls"],
Some("Use // to provide default for null values"),
),
TooltipContent::new(
"scalars",
"Filter to keep non-iterable values (primitives)",
&[
".. | scalars # all leaf values in tree",
"[.. | scalars] | unique # all unique primitive values",
],
Some("Opposite of iterables; perfect for extracting leaf values"),
),
TooltipContent::new(
"floor",
"Round down toward negative infinity",
&[
"floor # 2.7 -> 2, -2.7 -> -3",
". * 100 | floor / 100 # truncate to 2 decimals",
],
Some("Rounds toward negative infinity (not toward zero)"),
),
TooltipContent::new(
"ceil",
"Round up toward positive infinity",
&[
"ceil # 2.1 -> 3, -2.1 -> -2",
". * 100 | ceil / 100 # round up to 2 decimals",
],
Some("Rounds toward positive infinity"),
),
TooltipContent::new(
"round",
"Round to nearest integer",
&[
"round # 2.5 -> 3, 2.4 -> 2",
". * 100 | round / 100 # round to 2 decimal places",
],
Some("Rounds half away from zero"),
),
TooltipContent::new(
"sqrt",
"Square root",
&[
"sqrt # 16 -> 4",
". | sqrt | floor # integer square root",
],
Some("Returns float even for perfect squares; use floor/round"),
),
TooltipContent::new(
"abs",
"Absolute value",
&[
"abs # -5 -> 5",
"(.a - .b) | abs # distance between values",
],
Some("Works on numbers only"),
),
TooltipContent::new(
"now",
"Current Unix timestamp",
&[
"now # current timestamp (float)",
"now | floor # current timestamp (integer)",
"now | strftime(\"%Y-%m-%d\") # today's date",
"now | todate # current time as ISO 8601",
],
Some("Returns seconds since epoch as FLOAT with microsecond precision"),
),
TooltipContent::new(
"empty",
"Produce no output (filter out current value)",
&[
"empty # produces nothing",
"if .skip then empty else . end # conditionally omit",
"select(. >= 0) # same as above, cleaner",
],
Some("Useful in conditionals; often select() is cleaner"),
),
TooltipContent::new(
"error",
"Raise an error and stop processing",
&[
"error(\"Invalid input\") # error with message",
"if .required == null then error(\"Missing field\") else . end",
"try .data catch error(\"No data\") # re-throw with message",
],
Some("Catch with: try expr catch \"fallback\"; errors go to stderr"),
),
TooltipContent::new(
"not",
"Logical NOT",
&[
"not # invert boolean",
"select(.active | not) # select inactive items",
"select(has(\"error\") | not) # objects without error field",
],
Some("Note: 0 and \"\" are TRUTHY in jq (unlike JavaScript)"),
),
TooltipContent::new(
"ascii_downcase",
"Convert ASCII letters to lowercase",
&[
"ascii_downcase # \"Hello\" -> \"hello\"",
".name | ascii_downcase # normalize for comparison",
],
Some("ASCII only (a-z, A-Z); non-ASCII chars unchanged"),
),
TooltipContent::new(
"ascii_upcase",
"Convert ASCII letters to uppercase",
&[
"ascii_upcase # \"hello\" -> \"HELLO\"",
"select(.code | ascii_upcase == \"USA\") # case-insensitive",
],
Some("ASCII only (a-z, A-Z); non-ASCII chars unchanged"),
),
TooltipContent::new(
"env",
"Access environment variables",
&[
"env.HOME # get HOME variable",
"env.USER # get current username",
"env.API_KEY // error(\"API_KEY not set\") # required env var",
],
Some("Use $ENV for object of all env vars"),
),
];
pub fn get_tooltip_content(function: &str) -> Option<&'static TooltipContent> {
TOOLTIP_CONTENT.iter().find(|c| c.function == function)
}
#[cfg(test)]
#[path = "tooltip_content_tests.rs"]
mod tooltip_content_tests;