Skip to content

Commit a65a92d

Browse files
cmd args quotes handled by parse(args[])
1 parent ccb6a66 commit a65a92d

File tree

8 files changed

+82
-29
lines changed

8 files changed

+82
-29
lines changed

UltraMapper.CommandLine.Example/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace UltraMapper.CommandLine.Example
99
class Program
1010
{
1111
static void Main( string[] args )
12-
{
12+
{
1313
//--add ("John Smith" 26 account=( number=AC2903X balance=3500.00 creditcards=[(CRD01 1000.00) (CRD02 2000.00)]))
1414
ConsoleLoop.Start<CustomerCommands>( args );
1515
}

UltraMapper.CommandLine.Example/UltraMapper.CommandLine.Example.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,10 @@
183183
<Private>True</Private>
184184
</Reference>
185185
<Reference Include="UltraMapper, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
186-
<HintPath>..\packages\UltraMapper.0.2.55\lib\net47\UltraMapper.dll</HintPath>
186+
<HintPath>..\packages\UltraMapper.0.2.59\lib\net47\UltraMapper.dll</HintPath>
187187
</Reference>
188-
<Reference Include="UltraMapper.Parsing, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
189-
<HintPath>..\packages\UltraMapper.Parsing.1.0.0\lib\net47\UltraMapper.Parsing.dll</HintPath>
188+
<Reference Include="UltraMapper.Parsing, Version=0.2.13.0, Culture=neutral, processorArchitecture=MSIL">
189+
<HintPath>..\packages\UltraMapper.Parsing.2.0.0\lib\net47\UltraMapper.Parsing.dll</HintPath>
190190
</Reference>
191191
</ItemGroup>
192192
<ItemGroup>

UltraMapper.CommandLine.Example/packages.config

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@
4848
<package id="System.Threading.Timer" version="4.3.0" targetFramework="net472" />
4949
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net472" />
5050
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net472" />
51-
<package id="UltraMapper" version="0.2.55" targetFramework="net472" />
52-
<package id="UltraMapper.Parsing" version="1.0.0" targetFramework="net472" />
51+
<package id="UltraMapper" version="0.2.59" targetFramework="net472" />
52+
<package id="UltraMapper.Parsing" version="2.0.0" targetFramework="net472" />
5353
</packages>

UltraMapper.CommandLine.UnitTest/UltraMapper.CommandLine.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<Authors>Mauro Sampietro</Authors>
88
<Copyright>2021</Copyright>
99
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
10-
<langversion>latest</langversion>
10+
<langversion>latest</langversion>
1111
</PropertyGroup>
1212

1313
<ItemGroup>

UltraMapper.CommandLine.UnitTest/UltraMapper.Extensions/UltraMapperExt.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using System;
23
using UltraMapper.MappingExpressionBuilders;
34
using UltraMapper.Parsing;
45
using UltraMapper.Parsing.Extensions;
@@ -41,14 +42,14 @@ public class Level3
4142
[TestMethod]
4243
public void BasicMapByParamName()
4344
{
44-
//funziona solo assegnando a tutti i valori un nome (per adesso)
45-
var args = new string[]
45+
var commands = new string[]
4646
{
4747
$"--{nameof( Commands.PropertyA )} {nameof( Commands.PropertyA )}",
4848
$"--{nameof( Commands.PropertyB )} {nameof( Commands.PropertyB ).GetHashCode()}",
4949
$"--{nameof( Commands.SomeCommand )} (a=a b=11 sublevel2=(d=d e=e sublevel3=(g=g h=h)))"
5050
};
5151

52+
var args = String.Join( " ", commands );
5253
var target = CommandLine.Instance.Parse<Commands>( args );
5354

5455
Assert.IsTrue( target.PropertyA == nameof( Commands.PropertyA ) );
@@ -64,13 +65,14 @@ public void BasicMapByParamName()
6465
[TestMethod]
6566
public void BasicMapByParamIndex()
6667
{
67-
var args = new string[]
68+
var commands = new string[]
6869
{
6970
$"--{nameof( Commands.PropertyA )} a",
7071
$"--{nameof( Commands.PropertyB )} 11",
7172
$"--{nameof( Commands.SomeCommand )} (a1 b1 (d e (g h)))"
7273
};
7374

75+
var args = String.Join( " ", commands );
7476
var target = CommandLine.Instance.Parse<Commands>( args );
7577

7678
Assert.IsTrue( target.PropertyA == "a" );
@@ -178,6 +180,6 @@ public void DirectNestedPropertyAssignment() //Is it actually useful?
178180
var parsed = CommandLine.Instance.Parse<Commands>( args );
179181

180182
Assert.IsTrue( parsed.SomeCommand.SubLevel2.SubLevel3.G == "g" );
181-
}
183+
}
182184
}
183185
}

UltraMapper.CommandLine/CommandLine.cs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,24 +82,47 @@ public CommandLine( ICommandLineParser parser,
8282
return this.Parse( str, new T() );
8383
}
8484

85-
public T Parse<T>( string[] args ) where T : class, new()
85+
public T Parse<T>( string str, T instance ) where T : class
8686
{
87-
return this.Parse( String.Join( " ", args ), new T() );
87+
if( String.IsNullOrWhiteSpace( str ) )
88+
return instance;
89+
90+
this.HelpProvider.Initialize( typeof( T ) );
91+
92+
var commands = this.Parser.Parse( str ).ToList();
93+
commands = this.ParamsAdapter.Adapt<T>( commands ).ToList();
94+
95+
this.Mapper.Map( commands, instance );
96+
return instance;
8897
}
8998

90-
public T Parse<T>( string[] args, T instance ) where T : class
99+
/// <summary>
100+
/// Specific for arguments passed from cmd.
101+
/// (Quotes are preprocessed by the operating system)
102+
/// </summary>
103+
/// <typeparam name="T"></typeparam>
104+
/// <param name="args"></param>
105+
/// <returns></returns>
106+
public T Parse<T>( string[] args ) where T : class, new()
91107
{
92-
return this.Parse( String.Join( " ", args ), instance );
108+
return this.Parse( args, new T() );
93109
}
94110

95-
public T Parse<T>( string str, T instance ) where T : class
111+
/// <summary>
112+
/// Specific for arguments passed from cmd
113+
/// (Quotes are preprocessed by the operating system)
114+
/// </summary>
115+
/// <typeparam name="T"></typeparam>
116+
/// <param name="args"></param>
117+
/// <returns></returns>
118+
public T Parse<T>( string[] args, T instance ) where T : class
96119
{
97-
if( String.IsNullOrWhiteSpace( str ) )
120+
if( args == null || args.Length == 0 )
98121
return instance;
99122

100123
this.HelpProvider.Initialize( typeof( T ) );
101124

102-
var commands = this.Parser.Parse( str ).ToList();
125+
var commands = this.Parser.Parse( args ).ToList();
103126
commands = this.ParamsAdapter.Adapt<T>( commands ).ToList();
104127

105128
this.Mapper.Map( commands, instance );

UltraMapper.CommandLine/ConsoleLoop.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ namespace UltraMapper.CommandLine
44
{
55
public class ConsoleLoop
66
{
7-
public static void Start<T>( string[] args,
7+
public static void Start<T>( string[] args,
88
Action<T> onParsed = null ) where T : class, new()
99
{
1010
Start( args, new T(), onParsed );
1111
}
1212

13-
public static void Start<T>( string[] args, T instance,
13+
public static void Start<T>( string[] args, T instance,
1414
Action<T> onParsed = null ) where T : class
1515
{
1616
var autoparser = CommandLine.Instance;
@@ -22,13 +22,19 @@ public static void Start<T>( string[] args, T instance,
2222
{
2323
Console.Write( "> " );
2424

25-
string commandLine = (args == null || args.Length == 0) ?
26-
Console.ReadLine() : String.Join( " ", args );
25+
if( args == null || args.Length == 0 )
26+
{
27+
string commandLine = Console.ReadLine();
2728

28-
autoparser.Parse( commandLine, instance );
29-
onParsed?.Invoke( instance );
30-
31-
args = null;
29+
autoparser.Parse( commandLine, instance );
30+
onParsed?.Invoke( instance );
31+
}
32+
else
33+
{
34+
autoparser.Parse( args, instance );
35+
onParsed?.Invoke( instance );
36+
args = null;
37+
}
3238
}
3339
catch( UndefinedCommandException argumentEx )
3440
{

UltraMapper.CommandLine/Parsers/DefaultParser.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,31 @@ public sealed class DefaultParser : ICommandLineParser
122122

123123
public IEnumerable<ParsedCommand> Parse( string[] commands )
124124
{
125-
//just rejoin and resplit in case a single string in the array contains more than one command
125+
//Allegedly an array of commands has already been processed and split (and quotes removed)
126+
//by the command line. In theory every item equals a param, so it should be safe to quote
127+
//every single array item containing a whitespace and just rejoin and resplit the array.
128+
//
129+
//Moreover it should be ok in case a single string in the array contains more than one command
126130
//or commands span more than one string.
127-
return this.Parse( String.Join( " ", commands ) );
131+
132+
IEnumerable<string> requote( string[] cmds )
133+
{
134+
foreach( var item in cmds )
135+
{
136+
if( item.Any( c => Char.IsWhiteSpace( c ) ) )
137+
{
138+
if( !item.StartsWith( "\"" ) )
139+
yield return $"\"{item}\"";
140+
}
141+
else
142+
{
143+
yield return item;
144+
}
145+
}
146+
}
147+
148+
var quotedCommands = requote( commands );
149+
return this.Parse( String.Join( " ", quotedCommands ) );
128150
}
129151

130152
public IEnumerable<ParsedCommand> Parse( string commandLine )
@@ -212,7 +234,7 @@ private IEnumerable<IParsedParam> GetCommandParams( IEnumerable<string> paramete
212234
paramValue = paramValue.Substring( 1, paramValue.Length - 2 );
213235

214236
var subMatches = BalancedParenthesesRegex.Matches( paramValue );
215-
// if( subMatches.Count > 1 )
237+
// if( subMatches.Count > 1 )
216238
{
217239
var subParams = subMatches.Cast<Match>()
218240
.Select( c => c.Groups[ "params" ].Value );

0 commit comments

Comments
 (0)