tmuxp search - tmuxp.cli.search

CLI for tmuxp search subcommand.

Search workspace configuration files by name, session, path, and content.

Examples

>>> from tmuxp.cli.search import SearchToken, normalize_fields

Parse field aliases to canonical names:

>>> normalize_fields(["s", "name"])
('session_name', 'name')

Create search tokens from query terms:

>>> from tmuxp.cli.search import parse_query_terms, DEFAULT_FIELDS
>>> tokens = parse_query_terms(["name:dev", "editor"], default_fields=DEFAULT_FIELDS)
>>> tokens[0]
SearchToken(fields=('name',), pattern='dev')
>>> tokens[1]
SearchToken(fields=('name', 'session_name', 'path', 'window', 'pane'), pattern='editor')
tmuxp.cli.search.FIELD_ALIASES: dict[str, str] = {'n': 'name', 'name': 'name', 'p': 'path', 'pane': 'pane', 'path': 'path', 's': 'session_name', 'session': 'session_name', 'session_name': 'session_name', 'w': 'window', 'window': 'window'}

Field name aliases for search queries

tmuxp.cli.search.VALID_FIELDS: frozenset[str] = frozenset({'name', 'pane', 'path', 'session_name', 'window'})

Valid field names after alias resolution

tmuxp.cli.search.DEFAULT_FIELDS: tuple[str, ...] = ('name', 'session_name', 'path', 'window', 'pane')

Default fields to search when no field prefix is specified

class tmuxp.cli.search.SearchToken(fields: tuple[str, ...], pattern: str)[source]

Bases: NamedTuple

Parsed search token with target fields and raw pattern.

fields

Canonical field names to search (e.g., (‘name’, ‘session_name’)).

Type:

tuple[str, …]

pattern

Raw search pattern before regex compilation.

Type:

str

Examples

>>> token = SearchToken(fields=("name",), pattern="dev")
>>> token.fields
('name',)
>>> token.pattern
'dev'
fields: tuple[str, ...]

Alias for field number 0

pattern: str

Alias for field number 1

_asdict()[source]

Return a new dict which maps field names to their values.

_field_defaults = {}
_fields = ('fields', 'pattern')
classmethod _make(iterable)[source]

Make a new SearchToken object from a sequence or iterable

_replace(**kwds)[source]

Return a new SearchToken object replacing specified fields with new values

class tmuxp.cli.search.SearchPattern(fields: tuple[str, ...], raw: str, regex: re.Pattern[str])[source]

Bases: NamedTuple

Compiled search pattern with regex and metadata.

fields

Canonical field names to search.

Type:

tuple[str, …]

raw

Original pattern string before compilation.

Type:

str

regex

Compiled regex pattern for matching.

Type:

re.Pattern[str]

Examples

>>> import re
>>> pattern = SearchPattern(
...     fields=("name",),
...     raw="dev",
...     regex=re.compile("dev"),
... )
>>> pattern.fields
('name',)
>>> bool(pattern.regex.search("development"))
True
fields: tuple[str, ...]

Alias for field number 0

raw: str

Alias for field number 1

regex: Pattern[str]

Alias for field number 2

_asdict()[source]

Return a new dict which maps field names to their values.

_field_defaults = {}
_fields = ('fields', 'raw', 'regex')
classmethod _make(iterable)[source]

Make a new SearchPattern object from a sequence or iterable

_replace(**kwds)[source]

Return a new SearchPattern object replacing specified fields with new values

exception tmuxp.cli.search.InvalidFieldError(field)[source]

Bases: ValueError

Raised when an invalid field name is specified.

Examples

>>> raise InvalidFieldError("invalid")
Traceback (most recent call last):
    ...
tmuxp.cli.search.InvalidFieldError: Unknown search field: 'invalid'. ...
tmuxp.cli.search.normalize_fields(fields)[source]

Normalize field names using aliases.

Return type:

tuple[str, ...]

Parameters:

fields (list[str] | None) – Field names or aliases to normalize. If None, returns DEFAULT_FIELDS.

Returns:

Tuple of canonical field names.

Return type:

tuple[str, …]

Raises:

InvalidFieldError – If a field name is not recognized.

Examples

>>> normalize_fields(None)
('name', 'session_name', 'path', 'window', 'pane')
>>> normalize_fields(["s", "n"])
('session_name', 'name')
>>> normalize_fields(["session_name", "path"])
('session_name', 'path')
>>> normalize_fields(["invalid"])
Traceback (most recent call last):
    ...
tmuxp.cli.search.InvalidFieldError: Unknown search field: 'invalid'. ...
tmuxp.cli.search._parse_field_prefix(term)[source]

Extract field prefix from a search term.

Return type:

tuple[str | None, str]

Parameters:

term (str) – Search term, possibly with field prefix (e.g., “name:dev”).

Returns:

Tuple of (field_prefix, pattern). field_prefix is None if no prefix.

Return type:

tuple[str | None, str]

Examples

>>> _parse_field_prefix("name:dev")
('name', 'dev')
>>> _parse_field_prefix("s:myproject")
('s', 'myproject')
>>> _parse_field_prefix("development")
(None, 'development')
>>> _parse_field_prefix("path:/home/user")
('path', '/home/user')
>>> _parse_field_prefix("window:")
('window', '')
tmuxp.cli.search.parse_query_terms(terms, *, default_fields=('name', 'session_name', 'path', 'window', 'pane'))[source]

Parse query terms into search tokens.

Each term can optionally have a field prefix (e.g., “name:dev”). Terms without prefixes search the default fields.

Return type:

list[SearchToken]

Parameters:
  • terms (list[str]) – Query terms to parse.

  • default_fields (tuple[str, ...]) – Fields to search when no prefix is specified.

Returns:

List of parsed search tokens.

Return type:

list[SearchToken]

Raises:

InvalidFieldError – If a field prefix is not recognized.

Examples

>>> tokens = parse_query_terms(["dev"])
>>> tokens[0].fields
('name', 'session_name', 'path', 'window', 'pane')
>>> tokens[0].pattern
'dev'
>>> tokens = parse_query_terms(["name:dev", "s:prod"])
>>> tokens[0]
SearchToken(fields=('name',), pattern='dev')
>>> tokens[1]
SearchToken(fields=('session_name',), pattern='prod')
>>> tokens = parse_query_terms(["window:editor", "shell"])
>>> tokens[0].fields
('window',)
>>> tokens[1].fields
('name', 'session_name', 'path', 'window', 'pane')

Unknown prefixes are treated as literal patterns (allows URLs, etc.):

>>> tokens = parse_query_terms(["http://example.com"])
>>> tokens[0].pattern
'http://example.com'
>>> tokens[0].fields  # Searches default fields
('name', 'session_name', 'path', 'window', 'pane')
tmuxp.cli.search._has_uppercase(pattern)[source]

Check if pattern contains uppercase letters.

Used for smart-case detection.

Return type:

bool

Parameters:

pattern (str) – Pattern to check.

Returns:

True if pattern contains at least one uppercase letter.

Return type:

bool

Examples

>>> _has_uppercase("dev")
False
>>> _has_uppercase("Dev")
True
>>> _has_uppercase("DEV")
True
>>> _has_uppercase("123")
False
>>> _has_uppercase("")
False
tmuxp.cli.search.compile_search_patterns(tokens, *, ignore_case=False, smart_case=False, fixed_strings=False, word_regexp=False)[source]

Compile search tokens into regex patterns.

Return type:

list[SearchPattern]

Parameters:
  • tokens (list[SearchToken]) – Parsed search tokens to compile.

  • ignore_case (bool) – If True, always ignore case. Default False.

  • smart_case (bool) – If True, ignore case unless pattern has uppercase. Default False.

  • fixed_strings (bool) – If True, treat patterns as literal strings, not regex. Default False.

  • word_regexp (bool) – If True, match whole words only. Default False.

Returns:

List of compiled search patterns.

Return type:

list[SearchPattern]

Raises:

re.error – If a pattern is invalid regex (when fixed_strings=False).

Examples

Basic compilation:

>>> tokens = [SearchToken(fields=("name",), pattern="dev")]
>>> patterns = compile_search_patterns(tokens)
>>> patterns[0].raw
'dev'
>>> bool(patterns[0].regex.search("development"))
True

Case-insensitive matching:

>>> tokens = [SearchToken(fields=("name",), pattern="DEV")]
>>> patterns = compile_search_patterns(tokens, ignore_case=True)
>>> bool(patterns[0].regex.search("development"))
True

Smart-case (uppercase = case-sensitive):

>>> tokens = [SearchToken(fields=("name",), pattern="Dev")]
>>> patterns = compile_search_patterns(tokens, smart_case=True)
>>> bool(patterns[0].regex.search("Developer"))
True
>>> bool(patterns[0].regex.search("developer"))
False

Smart-case (lowercase = case-insensitive):

>>> tokens = [SearchToken(fields=("name",), pattern="dev")]
>>> patterns = compile_search_patterns(tokens, smart_case=True)
>>> bool(patterns[0].regex.search("DEVELOPMENT"))
True

Fixed strings (escape regex metacharacters):

>>> tokens = [SearchToken(fields=("name",), pattern="dev.*")]
>>> patterns = compile_search_patterns(tokens, fixed_strings=True)
>>> bool(patterns[0].regex.search("dev.*project"))
True
>>> bool(patterns[0].regex.search("development"))
False

Word boundaries:

>>> tokens = [SearchToken(fields=("name",), pattern="dev")]
>>> patterns = compile_search_patterns(tokens, word_regexp=True)
>>> bool(patterns[0].regex.search("my dev project"))
True
>>> bool(patterns[0].regex.search("development"))
False
class tmuxp.cli.search.WorkspaceFields[source]

Bases: TypedDict

Extracted searchable fields from a workspace file.

name

Workspace name (file stem without extension).

Type:

str

path

Path to workspace file (with ~ contraction).

Type:

str

session_name

Session name from config, or empty string if not found.

Type:

str

windows

List of window names from config.

Type:

list[str]

panes

List of pane commands/shell_commands from config.

Type:

list[str]

Examples

>>> fields: WorkspaceFields = {
...     "name": "dev",
...     "path": "~/.tmuxp/dev.yaml",
...     "session_name": "development",
...     "windows": ["editor", "shell"],
...     "panes": ["vim", "git status"],
... }
>>> fields["name"]
'dev'
name: str
path: str
session_name: str
windows: list[str]
panes: list[str]
class tmuxp.cli.search.WorkspaceSearchResult[source]

Bases: TypedDict

Search result for a workspace that matched.

filepath

Absolute path to the workspace file.

Type:

str

source

Source location: “local” or “global”.

Type:

str

fields

Extracted searchable fields.

Type:

WorkspaceFields

matches

Mapping of field name to matched strings for highlighting.

Type:

dict[str, list[str]]

Examples

>>> result: WorkspaceSearchResult = {
...     "filepath": "/home/user/.tmuxp/dev.yaml",
...     "source": "global",
...     "fields": {
...         "name": "dev",
...         "path": "~/.tmuxp/dev.yaml",
...         "session_name": "development",
...         "windows": ["editor"],
...         "panes": [],
...     },
...     "matches": {"name": ["dev"]},
... }
>>> result["source"]
'global'
filepath: str
source: str
fields: WorkspaceFields
matches: dict[str, list[str]]
tmuxp.cli.search.extract_workspace_fields(filepath)[source]

Extract searchable fields from a workspace file.

Parses the workspace configuration and extracts name, path, session_name, window names, and pane commands for searching.

Return type:

WorkspaceFields

Parameters:

filepath (pathlib.Path) – Path to the workspace file.

Returns:

Dictionary of extracted fields.

Return type:

WorkspaceFields

Examples

>>> import tempfile
>>> import pathlib
>>> content = '''
... session_name: my-project
... windows:
...   - window_name: editor
...     panes:
...       - vim
...       - shell_command: git status
...   - window_name: shell
... '''
>>> with tempfile.NamedTemporaryFile(
...     suffix='.yaml', delete=False, mode='w'
... ) as f:
...     _ = f.write(content)
...     temp_path = pathlib.Path(f.name)
>>> fields = extract_workspace_fields(temp_path)
>>> fields["session_name"]
'my-project'
>>> sorted(fields["windows"])
['editor', 'shell']
>>> 'vim' in fields["panes"]
True
>>> temp_path.unlink()
tmuxp.cli.search._get_field_values(fields, field_name)[source]

Get values for a field, normalizing to list.

Return type:

list[str]

Parameters:
  • fields (WorkspaceFields) – Extracted workspace fields.

  • field_name (str) – Canonical field name to retrieve.

Returns:

List of values for the field.

Return type:

list[str]

Examples

>>> fields: WorkspaceFields = {
...     "name": "dev",
...     "path": "~/.tmuxp/dev.yaml",
...     "session_name": "development",
...     "windows": ["editor", "shell"],
...     "panes": ["vim"],
... }
>>> _get_field_values(fields, "name")
['dev']
>>> _get_field_values(fields, "windows")
['editor', 'shell']
>>> _get_field_values(fields, "window")
['editor', 'shell']
tmuxp.cli.search.evaluate_match(fields, patterns, *, match_any=False)[source]

Evaluate if workspace fields match search patterns.

Return type:

tuple[bool, dict[str, list[str]]]

Parameters:
  • fields (WorkspaceFields) – Extracted workspace fields to search.

  • patterns (list[SearchPattern]) – Compiled search patterns.

  • match_any (bool) – If True, match if ANY pattern matches (OR logic). If False, ALL patterns must match (AND logic). Default False.

Returns:

Tuple of (matched, {field_name: [matched_strings]}). The matches dict contains actual matched text for highlighting.

Return type:

tuple[bool, dict[str, list[str]]]

Examples

>>> import re
>>> fields: WorkspaceFields = {
...     "name": "dev-project",
...     "path": "~/.tmuxp/dev-project.yaml",
...     "session_name": "development",
...     "windows": ["editor", "shell"],
...     "panes": ["vim", "git status"],
... }

Single pattern match:

>>> pattern = SearchPattern(
...     fields=("name",),
...     raw="dev",
...     regex=re.compile("dev"),
... )
>>> matched, matches = evaluate_match(fields, [pattern])
>>> matched
True
>>> "name" in matches
True

AND logic (default) - all patterns must match:

>>> p1 = SearchPattern(fields=("name",), raw="dev", regex=re.compile("dev"))
>>> p2 = SearchPattern(fields=("name",), raw="xyz", regex=re.compile("xyz"))
>>> matched, _ = evaluate_match(fields, [p1, p2], match_any=False)
>>> matched
False

OR logic - any pattern can match:

>>> matched, _ = evaluate_match(fields, [p1, p2], match_any=True)
>>> matched
True

Window field search:

>>> p_win = SearchPattern(
...     fields=("window",),
...     raw="editor",
...     regex=re.compile("editor"),
... )
>>> matched, matches = evaluate_match(fields, [p_win])
>>> matched
True
>>> "window" in matches
True
tmuxp.cli.search.find_search_matches(workspaces, patterns, *, match_any=False, invert_match=False)[source]

Find workspaces matching search patterns.

Return type:

list[WorkspaceSearchResult]

Parameters:
  • workspaces (list[tuple[pathlib.Path, str]]) – List of (filepath, source) tuples to search. Source is “local” or “global”.

  • patterns (list[SearchPattern]) – Compiled search patterns.

  • match_any (bool) – If True, match if ANY pattern matches (OR logic). Default False (AND).

  • invert_match (bool) – If True, return workspaces that do NOT match. Default False.

Returns:

List of matching workspace results with match information.

Return type:

list[WorkspaceSearchResult]

Examples

>>> import tempfile
>>> import pathlib
>>> import re
>>> content = "session_name: dev-session" + chr(10) + "windows: []"
>>> with tempfile.NamedTemporaryFile(
...     suffix='.yaml', delete=False, mode='w'
... ) as f:
...     _ = f.write(content)
...     temp_path = pathlib.Path(f.name)
>>> pattern = SearchPattern(
...     fields=("session_name",),
...     raw="dev",
...     regex=re.compile("dev"),
... )
>>> results = find_search_matches([(temp_path, "global")], [pattern])
>>> len(results)
1
>>> results[0]["source"]
'global'

Invert match returns non-matching workspaces:

>>> pattern_nomatch = SearchPattern(
...     fields=("name",),
...     raw="nonexistent",
...     regex=re.compile("nonexistent"),
... )
>>> results = find_search_matches(
...     [(temp_path, "global")], [pattern_nomatch], invert_match=True
... )
>>> len(results)
1
>>> temp_path.unlink()
tmuxp.cli.search.highlight_matches(text, patterns, *, colors)[source]

Highlight regex matches in text.

Return type:

str

Parameters:
  • text (str) – Text to search and highlight.

  • patterns (list[SearchPattern]) – Compiled search patterns (uses their regex attribute).

  • colors (Colors) – Color manager for highlighting.

Returns:

Text with matches highlighted, or original text if no matches.

Return type:

str

Examples

>>> from tmuxp.cli._colors import ColorMode, Colors
>>> colors = Colors(ColorMode.NEVER)
>>> pattern = SearchPattern(
...     fields=("name",),
...     raw="dev",
...     regex=re.compile("dev"),
... )
>>> highlight_matches("development", [pattern], colors=colors)
'development'

With colors enabled (ALWAYS mode):

>>> colors_on = Colors(ColorMode.ALWAYS)
>>> result = highlight_matches("development", [pattern], colors=colors_on)
>>> "dev" in result
True
>>> chr(27) in result  # Contains ANSI escape
True
tmuxp.cli.search._output_search_results(results, patterns, formatter, colors)[source]

Output search results in human-readable or JSON format.

Return type:

None

Parameters:
  • results (list[WorkspaceSearchResult]) – Search results to output.

  • patterns (list[SearchPattern]) – Patterns used for highlighting.

  • formatter (OutputFormatter) – Output formatter for JSON/NDJSON/human modes.

  • colors (Colors) – Color manager.

class tmuxp.cli.search.CLISearchNamespace(**kwargs)[source]

Bases: Namespace

Typed argparse.Namespace for tmuxp search command.

Examples

>>> ns = CLISearchNamespace()
>>> ns.query_terms = ["dev"]
>>> ns.query_terms
['dev']
color: CLIColorModeLiteral
query_terms: list[str]
field: list[str] | None
ignore_case: bool
smart_case: bool
fixed_strings: bool
word_regexp: bool
invert_match: bool
match_any: bool
output_json: bool
output_ndjson: bool
print_help: t.Callable[[], None]
tmuxp.cli.search.create_search_subparser(parser)[source]

Augment argparse.ArgumentParser with search subcommand.

Return type:

ArgumentParser

Parameters:

parser (argparse.ArgumentParser) – The parser to augment.

Returns:

The augmented parser.

Return type:

argparse.ArgumentParser

Examples

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> result = create_search_subparser(parser)
>>> result is parser
True

Entrypoint for tmuxp search subcommand.

Searches workspace files in local (cwd and parents) and global (~/.tmuxp/) directories.

Return type:

None

Parameters:

Examples

>>> # command_search() searches workspaces with given patterns