pkgxdev / pkgx

the last thing you’ll install
https://pkgx.sh
Apache License 2.0
8.81k stars 1.36k forks source link

Retrieve env prompt prefixes for use in p10k #992

Closed ChampiYann closed 3 months ago

ChampiYann commented 3 months ago

Hi,

I just started using pkgx and I already love it. One of the things I couldn't get to work was to get de (+pkg) to show up at the beginning of my command prompt. I am using p10k but even without I still can't get it to work. It is possible to build custom prompt extensions in p10k so I would like to try that but I can't find where I would be able to find the currently activated environments. Can anyone tell me how I would be able to list them?

Thanks!

dosubot[bot] commented 3 months ago

Hey @ChampiYann! Great to see you diving into the depths of pkgx and p10k. I remember our last dance around the digital bonfire. How’s the coding journey treating you this time?

To display the (+pkg) prefix in your command prompt with a p10k setup, you can utilize the output from the internal.activate case in your app.ts file. Specifically, the line that logs the activated packages with a + prefix before their names:

console.error(`%s %s`, blurple('env'), pkgs.map(x => `+${utils.pkg.str(x)}`).join(' '))

This line of code formats the activated packages to have a + prefix and joins them with a space. To integrate this with a p10k command prompt setup, you would need to capture this output and set it as part of your prompt. This can be done by modifying your .p10k.zsh or equivalent configuration file to execute a command that triggers this specific functionality in your app.ts, capturing its output, and then including that output in your prompt.

For example, if you had a way to execute your application such that it only performed the internal.activate action, you might add something like this to your .p10k.zsh:

function pkgx_env_prompt() {
  # Assuming `app.ts` can be executed to just output the activated environments
  local pkgx_output="$(deno run --allow-env src/app.ts --internal-activate)"
  [[ -n "$pkgx_output" ]] && echo "$pkgx_output"
}

# Then in your POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS or POWERLEVEL9K_LEFT_PROMPT_ELEMENTS
# add a custom element that calls this function
POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(... pkgx_env_prompt ...)

This is a hypothetical example. You would need to adjust the execution command (deno run --allow-env src/app.ts --internal-activate) to match how your application should be called to output only the activated environments as seen in the internal.activate case in your app.ts.

Remember, for this to work:

Regarding your question about the internal.activate function in the pkgx codebase, it is designed to be invoked programmatically, as it is an exported asynchronous function that takes a directory path (dir) and an options object as its parameters. The options object includes a powder property, which is an array of PackageRequirement, and a logger property, which is of type Logger. This function is not directly tied to a specific command-line command within the provided context. Instead, it is meant to be called by other parts of the pkgx codebase or potentially by external scripts/modules that import and use this functionality.

The function performs several key operations:

  1. Validates the provided directory path.
  2. Constructs a development environment by installing packages and setting up environment variables.
  3. Handles user-supplied environment variables.
  4. Generates shell commands for activating and deactivating the development environment.

Given the context, to invoke this function, one would need to call it from another TypeScript or JavaScript file, passing the required dir and options object. There's no indication of a specific command-line interface command provided in the context that would directly trigger this function. It's part of the internal API of the pkgx package, meant for programmatic use.

Example of how it might be invoked in code (not directly from the provided context but based on the function signature):

import activate from 'src/modes/internal.activate.ts';

// Example directory and options
const dir = new Path('/path/to/directory');
const options = {
  powder: [{ /* PackageRequirement objects */ }],
  logger: {/* Logger object */}
};

// Invoke the function
activate(dir, options).then(() => {
  console.log('Activation complete.');
}).catch(error => {
  console.error('Activation failed:', error);
});

This example assumes the existence of Path, PackageRequirement, and Logger types or classes that are compatible with the activate function's parameters.

The structure of the PackageRequirement object that is passed as part of the options to the internal.activate function in the pkgx codebase, based on the provided context, includes the following properties:

Therefore, the PackageRequirement object structure is:

{
  project: string;
  constraint: string;
  update?: boolean;
}

I hope this helps! If you have any more questions, feel free to ask.

Sources

#### About Dosu This response is meant to be useful and save you time. It is **not meant to be a precise solution**, but rather a starting point for your own research. Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant. If you want to continue the conversation, start your reply with @dosu-bot.
ChampiYann commented 3 months ago

I fixed it in a different and, I guess, more correct way by using the PKGX_POWDER and PKGX_PKGENV environment variables. This is the p10k prompt function I came up with:

  function prompt_pkgx() {
    # Check if POWDER and PKGENV variables are set
    if [ -z "$PKGX_POWDER" ] || [ -z "$PKGX_PKGENV" ]; then
      return
    fi

    # Variable to store matched values
    matched_values=""

    # Loop through each value in POWDER
    for powder_value in ${(s: :)PKGX_POWDER}; do
      # Loop through each value in PKGENV
      for pkgenv_value in ${(s: :)PKGX_PKGENV}; do
        # Check if PKGENV value starts with POWDER value
        if [[ "$pkgenv_value" == "$powder_value"* ]]; then
            # Append the matched value to the variable
            matched_values="$matched_values $pkgenv_value"
        fi
      done
    done

    p10k segment -i PACKAGE_ICON -t "$matched_values" -r
  }

The function first checks if the variables exit. If so, it'll loop over PKGX_POWDER and look for matches in PKGX_PKGENV in order to get de version of the used powder. It then creates a segment with those pkg env values.

The result looks like this: p10k-pkgx

Of course, with p10k you can put the segment anywhere you want. I just decided to add it above the prompt line on the right.

jhheider commented 3 months ago

That's pretty cool, @ChampiYann ; we'll have to find a place in the docs for that.