diff --git a/src/pathsd.nim b/src/pathsd.nim index d7cb728..28b75b4 100644 --- a/src/pathsd.nim +++ b/src/pathsd.nim @@ -1,4 +1,4 @@ -import std/[algorithm, dirs, logging, options, paths, strutils, syncio] +import std/[algorithm, dirs, envvars, logging, options, paths, strutils, syncio] import strformat import commandant @@ -19,6 +19,7 @@ Usage: pathsd [options] search_path ... Options: -s --shell target shell (defaults to bash) + -d --dedupe deduplicate the final paths -v --verbose turn debugging messages on -q --quiet supress all logging messages --version show the version @@ -63,7 +64,7 @@ proc readPart(path: Path): seq[string] = return result -proc main*(searchPaths: seq[string]): MainResult = +proc main*(searchPaths: seq[string], envParts: seq[string], dedupe: bool): MainResult = var parts: seq[string] = @[] logger.log(lvlDebug, fmt"Processing search paths: {searchPaths}") @@ -84,6 +85,16 @@ proc main*(searchPaths: seq[string]): MainResult = for partPath in partPaths: parts = parts & readPart(partPath) + parts = parts & envParts + + if dedupe == true: + var dedupedParts: seq[string] = @[] + for part in parts: + if dedupedParts.contains(part) == false: + dedupedParts.add(part) + + parts = dedupedParts + return MainResult(output: parts, errorCode: QuitSuccess) @@ -93,6 +104,7 @@ when isMainModule: commandant.option(shell, string, "shell", "s", "bash") flag(verbose, "verbose", "v") flag(quiet, "quiet", "q") + flag(dedupe, "dedupe", "d") exitoption("help", "h", help_string, QuitFailure) exitoption("version", "", version_string, QuitFailure) errorproc(handleCommandantError) @@ -105,7 +117,11 @@ when isMainModule: logger.levelThreshold = loggerLevel - var mainResult = main(searchPaths) + var envParts: seq[string] = @[] + var envPath = envvars.getEnv("PATH") + envParts = envPath.split(":") + + var mainResult = main(searchPaths, envParts, dedupe) if mainResult.output != @[] and mainResult.errorCode == QuitSuccess: var output: string = "" @@ -113,7 +129,7 @@ when isMainModule: case shell of "bash": let pathComponents = join(mainResult.output, ":") - output = fmt"""export PATH="{pathComponents}":$PATH""" + output = fmt"""export PATH="{pathComponents}"""" if output != "": echo(output) diff --git a/tests/pathsd/test_main.nim b/tests/pathsd/test_main.nim index 225b440..2ec1df3 100644 --- a/tests/pathsd/test_main.nim +++ b/tests/pathsd/test_main.nim @@ -7,13 +7,17 @@ suite "Test main() proc": setup: const fixturesPath = Path(currentSourcePath) / Path("..") / Path("..") / Path("fixtures") const pathsdFixturePath = fixturesPath / Path("paths.d") - const expectedOutput = @["/Users/bilbo/opt/bin", "/opt/homebrew/bin", "/opt/homebrew/sbin"] + const envParts = @["/usr/local/bin", "/usr/bin"] + const expectedOutput = @[ + "/Users/bilbo/opt/bin", "/opt/homebrew/bin", "/opt/homebrew/sbin", + "/usr/local/bin", "/usr/bin", + ] pathsd.logger.levelThreshold = lvlNone test "Test happy path": # When - var mainResult = pathsd.main(@[pathsdFixturePath.string]) + var mainResult = pathsd.main(@[pathsdFixturePath.string], envParts, false) # Then check mainResult.output == expectedOutput @@ -21,10 +25,28 @@ suite "Test main() proc": test "Test skipping search paths that don't exist": # When - var mainResult = pathsd.main(@[ - pathsdFixturePath.string, - (fixturesPath / Path("idontexist")).string, - ]) + var mainResult = pathsd.main( + @[ + pathsdFixturePath.string, + (fixturesPath / Path("idontexist")).string, + ], + envParts, + false, + ) + + # Then + check mainResult.output == expectedOutput + + test "Test dedupe": + # Given + const localEnvParts = @[ + "/usr/local/bin", "/usr/bin", "/Users/bilbo/opt/bin", + ] + + # When + var mainResult = pathsd.main( + @[pathsdFixturePath.string], localEnvParts, true, + ) # Then check mainResult.output == expectedOutput