Recent

Author Topic: The separator in the command line  (Read 2703 times)

DEN1983

  • New member
  • *
  • Posts: 8
The separator in the command line
« on: July 18, 2024, 07:30:33 am »
Hi everybody!

How can I change the command line parameter separator?
I want to change the space to a backslash so that the ParamStr and ParamCount functions parse the string by backslash(\).
Maybe there is something like DefaultFormatSettings.......Separator ?

I have Windows 10 and Lazarus 3.4
« Last Edit: July 18, 2024, 07:32:56 am by DEN1983 »

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: The separator in the command line
« Reply #1 on: July 18, 2024, 07:39:22 am »
How can I change the command line parameter separator?
You can't for Paramstr and Paramcount unless you modify the compiler's RTL.

You would have to implement your own parameter handling if you want something like that.
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

DEN1983

  • New member
  • *
  • Posts: 8
Re: The separator in the command line
« Reply #2 on: July 18, 2024, 07:50:32 am »
You would have to implement your own parameter handling if you want something like that.
Thank you.
I'm ready.
Where to start throw links..

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: The separator in the command line
« Reply #3 on: July 18, 2024, 08:06:07 am »
I'm ready.
Where to start throw links..
This is not a Pascal related question rather an OS one.

Just like any other programing language the commandline is always assumed to have arguments separated by a space so all existing functionality is geared towards that.

So your google is just as good as mine (which btw landed me here)

The rest is a matter of parsing the resulting string exactly the way you want it to be parsed.
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

Thaddy

  • Hero Member
  • *****
  • Posts: 16158
  • Censorship about opinions does not belong here.
Re: The separator in the command line
« Reply #4 on: July 18, 2024, 08:11:17 am »
If you can guarantee there are no spaces, but only slashes, this is quite easy.
Code: Pascal  [Select][+][-]
  1. program sep;
  2. {$mode objfpc}
  3. uses
  4.   classes;
  5.  
  6. var
  7.   l:Tstringlist;
  8. begin
  9.   if paramcount > 0 then
  10.   try
  11.     l:=Tstringlist.create;
  12.     l.adddelimitedtext(paramstr(1),'\',true);    
  13.     writeln(l.text);
  14.   finally
  15.     l.free;
  16.   end;
  17. end.
Code: Bash  [Select][+][-]
  1. D:\>sep test\me\a\bit
  2. test
  3. me
  4. a
  5. bit
If there are spaces in the input it becomes a bit more complex, because the spaces increase the paramcount. (that is, unless the input is a quoted string)
« Last Edit: July 18, 2024, 08:20:05 am by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: The separator in the command line
« Reply #5 on: July 18, 2024, 08:19:05 am »
Indeed Thaddy.

You can also assure that by putting quotes around the argument in case it does contain spaces.

I did not recommend it because it depends on the interpretation of the shell/terminal how that is handled. So in case wanting to write a cross-platform solution that might cause unexpected issues.

so for TS: Just something to keep mind in case you do opt for a solution as suggested by Thaddy.
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

Thaddy

  • Hero Member
  • *****
  • Posts: 16158
  • Censorship about opinions does not belong here.
Re: The separator in the command line
« Reply #6 on: July 18, 2024, 08:49:32 am »
To demonstrate TRon's remark, have a look at this example and see why that is important:
Code: Pascal  [Select][+][-]
  1. program sep2;
  2. {$mode objfpc}
  3. uses
  4.   classes;
  5.  
  6. var
  7.   l:Tstringlist;
  8.   i:integer;
  9.   s:string = '';
  10. begin
  11.   if paramcount > 0 then
  12.   begin
  13.     for i := 1 to paramcount do
  14.       s:=s+paramstr(i);
  15.     l:=Tstringlist.create;
  16.     try
  17.       l.adddelimitedtext(s,'\',false);   // first output is true, second output is with false
  18.       writeln(l.text);
  19.     finally
  20.       l.free;
  21.     end;
  22.   end;
  23. end.
Code: Bash  [Select][+][-]
  1. sep2 "this is \" a\ test \with spa\ces
  2. this is
  3. a
  4. test
  5. withspa
  6. ces
Now, if you expect that, it is fine, otherwise you will need much more complex code.
(also experiment with true/false!)
Code: Bash  [Select][+][-]
  1. D:\>sep2 "this is \" a\ test \with spa\ces
  2. this
  3. is
  4. a
  5. test
  6. withspa
  7. ces
And experiment with this little change:
Code: Pascal  [Select][+][-]
  1. s:=s+#32+paramstr(i);// this restores the space
Code: Bash  [Select][+][-]
  1. D:\>sep2 "this is \" a\ test \with spa\ces
  2. this is
  3. a
  4. test
  5. with spa
  6. ces
Note true/false makes a big difference here, either include the slash or not.

So make a decision, otherwise you will need to write a parser yourself.
[edit]
This is a riddle with just a couple of solutions... 8) :P
Find the solution that includes the \ in the quoted string....
Have fun.
« Last Edit: July 18, 2024, 09:38:34 am by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

DEN1983

  • New member
  • *
  • Posts: 8
Re: The separator in the command line
« Reply #7 on: July 18, 2024, 05:53:43 pm »
Thaddy, TRon thank you very much.
I will try.

jollytall

  • Sr. Member
  • ****
  • Posts: 357
Re: The separator in the command line
« Reply #8 on: July 18, 2024, 07:29:50 pm »
There are many ways out there to pass parameters to a program and you might have good reasons to use \ separators. However, I still recommend to everybody to use the - almost - standard parameter formatting instead of any home-made (more elegantly said proprietary) version.
If you want your users to be able to use your program smoothly it is best to follow the standards (one - short codes, two -- long codes, mandatory, optional and no value parameters, and so on). There are various libraries for that.
I use https://github.com/zsoltszakaly/getoptionsforpascal as that knows all the standards and also provides fast, direct variable access.

Thaddy

  • Hero Member
  • *****
  • Posts: 16158
  • Censorship about opinions does not belong here.
Re: The separator in the command line
« Reply #9 on: July 18, 2024, 07:56:43 pm »
What a nonsense, it was just so serene here. Ron and i gave the correct answers. do not comment on correct code. Childish.
But there was a bonus? have you spotted that? Publish it! then you get my respect back instead of writing nonsense... :D
Short and compilable please....

@DEN1983 ignore that answer.
Solve the riddle.. :D (it is easy)
« Last Edit: July 18, 2024, 10:51:34 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: The separator in the command line
« Reply #10 on: July 19, 2024, 02:15:25 pm »
@yollytall:
There is something to be said about using standards.

It is great for end users and is mostly recognized and almost everyone understands them.

I personally dislike getopts implementation(s) and consider it necessary evil (there are far better solutions)

But that all doesn't withhold the fact that there can be numerous of reasons why someone wishes to parse/push parameters differently. You could ofc question that but in this case I did not feel the need myself to do so because TS is very explicit so I believe it is fair to assume (s/h)e knows h(is/er) business.
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

Kays

  • Hero Member
  • *****
  • Posts: 613
  • Whasup!?
    • KaiBurghardt.de
Re: The separator on the command line
« Reply #11 on: July 19, 2024, 04:14:42 pm »
[…] You can't for Paramstr and Paramcount unless you modify the compiler's RTL. […]
The splitting on blanks is not done by the RTL.
[…] This is not a Pascal related question rather an OS one. […]
Maybe there are operating systems that perform splitting, but usually the null‑terminated list of null‑terminated strings passed to execve or similar is left unaltered.
[…] How can I change the command line parameter separator? […]
The separator is maintained by the command line and the splitting is done by the command line. For example sh, bash and many other shells have a special environment variable IFS – internal field separator.
Code: Bash  [Select][+][-]
  1. IFS='\'
  2. # `read` is a shell‑builtin and respects $IFS
  3. read -r first second << 'EOT'
  4. Hello\World!
  5. EOT
  6. # prints Hello World! on two lines:
  7. printf '%s\n%s\n' "${first}" "${second}"
Yours Sincerely
Kai Burghardt

TRon

  • Hero Member
  • *****
  • Posts: 3623
Re: The separator on the command line
« Reply #12 on: July 19, 2024, 04:29:05 pm »
The splitting on blanks is not done by the RTL.
You are indeed correct that the splitting itself is not done with/by the RTL. It is assumed that the parameters are separated by a space (argc/argv).

ParamStr and ParamCount both fall back to using argc and argv so in order to change the behaviour of those functions you would have to modify the RTL (or override them and write your own custom ones).

The only way I know for sure to obtain an unaltered command line for windows is by the function that I linked to.
« Last Edit: July 19, 2024, 04:34:37 pm by TRon »
This tagline is powered by AI (AI advertisement: Free Pascal the only programming language that matters)

Thaddy

  • Hero Member
  • *****
  • Posts: 16158
  • Censorship about opinions does not belong here.
Re: The separator in the command line
« Reply #13 on: July 19, 2024, 06:18:44 pm »
Quote
Find the solution that includes the \ in the quoted string....
Have fun.
Of course the solution is available...BUT...
If I smell bad code it usually is bad code and that includes my own code.

DEN1983

  • New member
  • *
  • Posts: 8
Re: The separator in the command line
« Reply #14 on: July 23, 2024, 09:56:37 pm »
Hi everybody!
The story continues.
on Thaddy's advice, I used:
Code: Pascal  [Select][+][-]
  1.      str:=paramstr(1);
  2.      if paramcount>1 then for i := 2 to paramcount do str:=str+' '+paramstr(i);
  3.      ListStrings1.adddelimitedtext(str,'\',true);
  4.  
This works fine until two or more consecutive spaces meet.

In my program, the path to the file is passed as a parameter without quotes.
There may be a lot of spaces in the names of files and folders, for example:
nconvert C:\fol   der1\fold           er2\name    file.jpg

HOW DO I GET THIS WHOLE PATH UNCHANGED!???!!??

I only manage to get this way:
C:\fol der1\fold er2\name file.jpg
consecutive spaces are replaced by one

How do I get everything in the program that is entered on the command line unchanged as is?!
« Last Edit: July 23, 2024, 10:10:26 pm by DEN1983 »

 

TinyPortal © 2005-2018