Skip to content

Path segment: Multiple non-consecutive capture groups #6334

Open
@Bertie690

Description

@Bertie690

Code of Conduct

  • I agree to follow this project's Code of Conduct

What would you like to see changed?

I know this feature was implemented only very recently, but I still found something that could be improved. (Sorry!)

Existing Behavior

At the present moment, the path segment regex replaces the first capture group found with the corresponding value in the config, leaving the rest of the string completely untouched.
https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/src/segments/path.go#L639

This (while consistent with mapped_locations' preservation of subsequent portions of the path) presents an issue: what if you need something more than a mere 1 location substitution?

The Situation

My situation is similar to the one in my prior issues, with an enclosing github folder I want replaced with an icon:

"mapped_locations": {
	"/mnt/c": "C:/",
	"re:(.*/Users/taylo/Documents/GitHub).*": "github-icon"
}

This works fine in and of itself.

However, I place all my git worktrees for the current repo in a separate folder to keep track (repoName.worktrees/branch-name), and would like to have oh-my-posh additionally display "repoName" for these folders1.
In other words, I want something like this:

C:/Users/taylo/Documents/GitHub/repoName.worktrees/branch-name/XXX

to turn into this:

github-icon/repoName/XXX

Unfortunately, there appears to be no way to do these 2 things simultaneously while preserving the original path and successive sub-elements. Given the lack of variable expansion in regexp.FindStringSubmatch, neither of these work:

	"re:(.*/Users/taylo/Documents/GitHub/(?P<repoName>.*).worktrees/.*)": "github-icon/$repoName"
	"re:(.*/Users/taylo/Documents/GitHub/(.*).worktrees/.*)": "github-icon/$2"

While doing regexp.Expand could solve this, the existing code for finding submatches would have to be changed to use indices (not to mention 3 or more replacements gets you into some some really ugly nested capture groups).

Proposals

After all that context, I have 3 main ideas for potential solutions to this (in no particular order):

  1. Allow regex mapped location to replace successive capture groups with the corresponding values.
  • Pros:
    • Simple for users and fairly consistent with existing implementation.
  • Cons:
    • Questionable how to represent it inside config and/or JSON schema without breaking existing configs or changing implementations. Having a special delimiter sequence (comma, colon, etc.) risks breaking mappings containing those sequences, and allowing an array of values for this specific purpose would raise issues with how to interpret it for normal mapped locations.
    • Nested capture groups would seem to pose an interesting dilemmna - what do we replace if we have mappings for both.
    • IDK how you'd implement it in an idiomatic way that doesn't involve calling strings.Replace repeatedly or changing existing function behavior.
  1. Add a config boolean toggle (proposed name mapped_locations_regex_replaceAll) to make values for regex patterns be treated as literal replacement expressions passed directly to regex.ReplaceAllString2.
  • Pros:
    • Codebase already contains a function to facilitate "regex replace all" in the regexp package (yay code reuse)
    • Should be easier to implement and has more extensibility for nerds like me.
  • Cons:
    • Inconsistent with normal replacement syntax for restrictions outside the capture group. A basic expression like "re:(.*/Users/taylo/Documents/GitHub)/apple": "github-icon" would end up becoming "re:.*/Users/taylo/Documents/GitHub(/apple)": "github-icon$1" (since we want to preserve the succeeding "/apple")
  1. Go with what I proposed in Path Segment: Add support for recursive location mapping #6166 - adding a toggle to check all mapping lines and perform each replacement in turn. Execution order could probably be the exact reverse of normal (shortest first to ensure prefixes get mapped first)3.
  • Pros:
    • Keeps existing syntax while also allowing for more complex use cases (albeit with a few hoops)
  • Cons:
    • Probably not terribly performant to perform regex.FindStringSubmatch and strings.Replace once per mapping (even if it would make said mappings somewhat less complex). Whether it would be any less performant than using several capture groups and replacement patterns (or whether any change would actually make a noticeable difference) is up for debate.

Notes

I'm fairly impartial on what solution is finally implemented, though I tried to keep my suggestions backwards compatible with existing configs (seen as this is a feature already in the wild).
Thanks for reading.

Footnotes

  1. I already have the git segment in my config, so showing the extra folders is just wasting my already fairly limited terminal space.

  2. I doubt adding an additional prefix (rer: or whatnot) solely for these regexes is a good idea.

  3. I know the issue was closed as completed earlier, but it's merely an idea.

Metadata

Metadata

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions