Skip to content

Support non-script based file configuration of options #635

Open

Description

@imacks

Relying on profile.ps1 may not fit scenarios where we want to set-executionpolicy to ban scripts.

Would it be possible to populate options from the registry or json file? I would image modifying PSConsoleReadlineOptions is all that it takes?

Activity

  1. changed the title [-]persist options in registry[/-] [+]Support non-script based file configuration of options[/+] on Feb 21, 2018
  2. lzybkr commented on Feb 21, 2018

    @lzybkr
    Contributor

    I'm definitely open to the idea.

    Now that PSReadLine is portable to Mac/Linux, we should avoid the registry.

    If this is implemented, my priorities are:

    • Be portable between:
      • Windows/Non-Windows
      • Full CLR/Core CLR
    • Avoid new dependencies, e.g. don't require shipping Newtonsoft.Json
      • Helps avoid introducing versioning problems w/ popular nuget packages
      • Helps simplify bringing this feature back into Windows

    I think this rules out json and probably yaml (writing yet another parser is usually not a good idea.)

    When I originally considered the problem of configuration, I settled on script because I hated xml. I still hate xml, but it might be the simplest option.

    Maybe a better (but more complicated option) - use script, but don't execute it, instead interpret the Ast. You couldn't use arbitrary script, e.g. you could only call Set-PSReadLIneOption and Set-PSReadLineKeyHandler, pass only constants, no variables except perhaps reading environment variables, etc. It would be similar to the PowerShell data language (psd1 files) - so maybe we would just check for the file PSReadLineConfig.psd1 in the same directory as the user profile or something like that.

  3. imacks commented on Feb 22, 2018

    @imacks
    Author

    wow that sounds great. I am happy to work on this feature if you like

  4. nightroman commented on Feb 22, 2018

    @nightroman
    Contributor

    Or we can use a real script PSReadLine.profile.ps1 and "invoke" it by reading, creating a script block and invoking it. This bypasses the execution policy.

  5. lzybkr commented on Feb 22, 2018

    @lzybkr
    Contributor

    Invoking wouldn't work in restricted language mode.

  6. imacks commented on Feb 22, 2018

    @imacks
    Author

    I don't know. Why insist on a script when all we want to do is something simple? For my case, I just customized HKCU:\Console\ColorTable## to solarized and can't see anything dark gray with the default PSReadLine options. All I want to do is set parameter color to something that is not dark gray!

  7. nightroman commented on Feb 22, 2018

    @nightroman
    Contributor

    I thought OP was talking about execution policy. It does not imply restricted language mode, it just does not allow invoke script directly. But they still may be invoked in many ways.

  8. nightroman commented on Feb 22, 2018

    @nightroman
    Contributor

    Macks (@imacks) The script approach has some advantages. Personally, I would prefer it regardless of the execution policy, at least to make my usual profile cleaner.

  9. imacks commented on Feb 22, 2018

    @imacks
    Author

    Roman Kuzmin 1967-2026 (@nightroman) i don’t see a problem with script or xml or whatnot, so long as we can keep it as a simple way to change the defaults. I mean, the profile is always there.

  10. lzybkr commented on Feb 22, 2018

    @lzybkr
    Contributor

    Roman Kuzmin 1967-2026 (@nightroman) - PSReadLine has extra security concerns that other modules might not when it ships with Windows, so I need to avoid exposing potentially exploitable holes.

    That said, there is a way to invoke the script without violating the machine lockdown policy.

    Macks (@imacks) - thanks for offering to implement this. I think the script solution is better than xml because:

    • it should be less code
    • script blocks in xml can be painful if you need to escape anything
    • nobody wants xml :)

    We'll need code similar to the following to invoke the configuration script block and not create a security hole.

    var origLanguageMode = runspace.LanguageMode;
    try {
        if (SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Enforce)
        {
            runspace.LanguageMode = PSLanguageMode.ConstrainedLanguage;
        }
        scriptBlock.Invoke();
    } finally {
        runspace.LanguageMode  = origLanguageMode;
    }
  11. imacks commented on Feb 23, 2018

    @imacks
    Author

    So... it is a file. What options are in there?

    Here's what I can think of (convertfrom-stringdata styled capable of handling env variables)

    EditMode = default
    ContinuationPrompt = >>>
    ContinuationPromptColor = green
     ExtraPromptLineCount = default
     #  AddToHistoryHandler = null
     HistoryNoDuplicates = default
                MaximumHistoryCount = default
                MaximumKillRingCount = default
                HistorySearchCursorMovesToEnd = default
                ShowToolTips = true
                DingDuration = 15
                DingTone = default
                BellStyle = default
                CompletionQueryItems = default
                WordDelimiters = default
                HistorySearchCaseSensitive = default
                HistorySaveStyle = default
                AnsiEscapeTimeout = default
       HistorySavePath = ${env:userprofile}/.history.log
    
    CommentColor   =DarkGreen
    KeywordColor   = Green
        StringColor    = DarkCyan
           OperatorColor  = DarkGray
           VariableColor  = Green
          CommandColor   = Yellow
         ParameterColor = DarkGray
            TypeColor      = Gray
          NumberColor    = White
           MemberColor    = Gray
            EmphasisColor  = Cyan
            ErrorColor  = Red
  12. lzybkr commented on Feb 23, 2018

    @lzybkr
    Contributor

    Oh, Roman Kuzmin 1967-2026 (@nightroman) was just suggesting you still use a ps1 file like you would today, but PSReadLine would invoke it in a way that is not affected by the execution policy.

    I use the following pattern in my profile to make it feel more like a configuration and less like calling a bunch of commands:

    $options =
    @{
        PromptText = '> '
        AddToHistoryHandler = {
            param([string]$line)
            return $line.Length -gt 3 -and $line[0] -ne ' ' -and $line[0] -ne ';'
        }
        HistorySavePath = "${env:HOMEDRIVE}${env:HOMEPATH}/PSReadLine_history.txt"
        EditMode = 'Emacs'
        ExtraPromptLineCount = 1
        Colors = @{
            Error = "$([char](0x1b))[44;91m"
        }
    }
    Set-PSReadLineOption @options

    I suppose one option is to mimic the module manifest, basically remove the first and last lines in my example above, then apply the options. This would also need to allow specifying key bindings, maybe like:

    @{
        KeyBindings = @{
            UpArrow = 'HistorySearchBackward'
            DownArrow = 'HistorySearchForward'
            'Alt+F1' = @{
                BriefDescription = 'CommandHelp'
                LongDescription = 'Open the help window for the current command'
                ScriptBlock = { ... }
            }
        }
    }
  13. bgshacklett commented on Feb 23, 2018

    @bgshacklett

    There's precedent for this kind of configuration data in .psd1 files with DSC as well:
    https://docs.microsoft.com/en-us/powershell/dsc/separatingenvdata

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions