Skip to content

Commit

Permalink
Update SelectCommandArgument to properly handle POSIX style options…
Browse files Browse the repository at this point in the history
… for CLI commands (#4016)
  • Loading branch information
daxian-dbw committed May 14, 2024
1 parent 4023f06 commit 61f598d
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 1 deletion.
24 changes: 23 additions & 1 deletion PSReadLine/KillYank.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation.Language;
using System.Text.RegularExpressions;
using Microsoft.PowerShell.Internal;

namespace Microsoft.PowerShell
Expand All @@ -29,6 +30,10 @@ class YankLastArgState
private YankLastArgState _yankLastArgState;
private int _visualSelectionCommandCount;

// Pattern to check for CLI parameters like '--json'.
// Valid characters are 'a-z', 'A-Z', '0-9', '_' (all covered by '\w'), and '-'.
private static readonly Regex s_cliOptionPattern = new(@"^--[\w-]+$", RegexOptions.Compiled);

/// <summary>
/// Mark the current location of the cursor for use in a subsequent editing command.
/// </summary>
Expand Down Expand Up @@ -480,7 +485,7 @@ public static void SelectCommandArgument(ConsoleKeyInfo? key = null, object arg
var argument = cmdAst.CommandElements[j] switch
{
CommandParameterAst paramAst => paramAst.Argument,
ExpressionAst expAst => expAst,
ExpressionAst exprAst => ProcessExpressionAst(exprAst),
_ => null,
};

Expand Down Expand Up @@ -614,6 +619,7 @@ public static void SelectCommandArgument(ConsoleKeyInfo? key = null, object arg
_singleton.VisualSelectionCommon(() => SetCursorPosition(newEndCursor), forceSetMark: true);


// ===== Local Functions =====
// Get the script block AST's whose extent contains the cursor.
bool GetScriptBlockAst(Ast ast)
{
Expand All @@ -639,6 +645,22 @@ bool GetScriptBlockAst(Ast ast)
? ast.Extent.EndOffset - 1 > cursor
: ast.Extent.EndOffset >= cursor;
}

// Process an expression AST to check if it's a CLI posix style option.
static ExpressionAst ProcessExpressionAst(ExpressionAst exprAst)
{
if (exprAst is StringConstantExpressionAst strAst
&& strAst.StringConstantType is StringConstantType.BareWord
&& strAst.Value.StartsWith("--")
&& s_cliOptionPattern.IsMatch(strAst.Value))
{
// It's a CLI posix style option, like '--json' or '--machine-type',
// so we treat it as a parameter.
return null;
}

return exprAst;
}
}

/// <summary>
Expand Down
50 changes: 50 additions & 0 deletions test/KillYankTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,56 @@ public void SelectCommandArgument_VariousArgs()
_.Escape));
}

[SkippableFact]
public void SelectCommandArgument_CLIArgs()
{
TestSetup(KeyMode.Cmd);

Test("", Keys(
"az webapp --name MyWebApp --resource-group MyResourceGroup",
_.Alt_a, CheckThat(() => AssertScreenIs(1,
TokenClassification.Command, "az",
TokenClassification.None, ' ',
TokenClassification.Selection, "webapp",
TokenClassification.None, ' ',
TokenClassification.Parameter, "--name",
TokenClassification.None, " MyWebApp ",
TokenClassification.Parameter, "--resource-group",
TokenClassification.None, " MyResourceGroup ")),

_.Alt_a, CheckThat(() => AssertScreenIs(1,
TokenClassification.Command, "az",
TokenClassification.None, " webapp ",
TokenClassification.Parameter, "--name",
TokenClassification.None, ' ',
TokenClassification.Selection, "MyWebApp",
TokenClassification.None, ' ',
TokenClassification.Parameter, "--resource-group",
TokenClassification.None, " MyResourceGroup ")),

_.Alt_a, CheckThat(() => AssertScreenIs(1,
TokenClassification.Command, "az",
TokenClassification.None, " webapp ",
TokenClassification.Parameter, "--name",
TokenClassification.None, " MyWebApp ",
TokenClassification.Parameter, "--resource-group",
TokenClassification.None, ' ',
TokenClassification.Selection, "MyResourceGroup")),

// Verify that we can loop through the arguments.
_.Alt_a, CheckThat(() => AssertScreenIs(1,
TokenClassification.Command, "az",
TokenClassification.None, ' ',
TokenClassification.Selection, "webapp",
TokenClassification.None, ' ',
TokenClassification.Parameter, "--name",
TokenClassification.None, " MyWebApp ",
TokenClassification.Parameter, "--resource-group",
TokenClassification.None, " MyResourceGroup ")),

_.Escape));
}

[SkippableFact]
public void SelectCommandArgument_HereStringArgs()
{
Expand Down

1 comment on commit 61f598d

@ToshiroMifune123
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi Daxian My name is Manuel Im from Uruguay and im a total dummy at coding im traying to make the code for a trivia game of medical diagnose as if you were playing to be Doctor House but i dont find the way of making the code work or even making the python code upload the json. im sure youre loaded with tons of work but here i live in a very small town and i dont know how to reach a codder. ive done some courses researched all i could by myself but im working on this idea to develop a game app wich i hope can get me at least out of some financial problems. i know is a lot to ask and the game is in spanish, if you cant help its ok i undesrtand i send you the drive link to the code and the Json. https://drive.google.com/drive/folders/1KbO5gSfxaCLPpxqrTijSiOBelbOKfWyM?usp=sharing
Many thanks for your time and im totally aware is not your job helping newbies

Please sign in to comment.