Writing an application which interacts with a CLI in Windows

Hello everyone,
I am working on writing an application which will (among other things) will aggregate data coming out of our source control system (Perforce) in Windows. I am attempting to get the data I need using System.cmd but instead of the output being written to a list as separate lines (as I would hope), I get one huge string. I suspect the problem is I am not accounting for Windows newline characters here. Is there a simple solution to this that allows me to read in line by line or am I looking at attempting to regex the input. I’d like to avoid that if possible as there are newline characters in the data itself aside from the actual newlines returned by Perforce.

For reference, the command I am using is: p4_results = System.cmd “p4”, [“changes”, “@2017/10/24,@now”], into: []

I can contrive an example if it would help.

1 Like

Nobody has an answer?

Have you tried something like String.split(output, ["\n"]) for a start?

1 Like

Thanks for the reply. That may be what I have to do- I had just really preferred to avoid it. For one thing- it is very possible there are newline characters in the data itself so splitting (or regex captures) will have to be done with some extra care.

Well think about it for a moment. The executable you are running is simply writing characters to the output stream which is then captured into “one huge string”. So there is no way for System.cmd to know which characters sequences are the “true line breaks” and which ones are embedded in the “data”. Even if you could use something like IO.stream(:stdio, :line) it would likely be fooled by the “embedded line breaks” and give you partial lines.

So you will have to devise some context sensitive method for breaking that string down into sensible “components” that can each be processed separately.

2 Likes

Yeah, I suspect you are right.

I think I have some direction where to start. It seems if I can split via the \n\r sequences, the true beginnings of a commit message are somewhat predictable so I can terminate groups of lines via those.

Thanks everyone- I’ll give it a shot

You could look at the formatting options to get an easier to script output. It seems -Ztag, -F, or -G (calling through a Python wrapper) could be useful.

https://www.perforce.com/blog/fun-formatting

https://www.perforce.com/perforce/r15.1/manuals/p4guide/chapter.scripting.html

Good idea!! Thank you!

Line breaks are a bit of a pain since three different schemes exist in the wild: \r\n on Windows, \r on classic Mac and some other various odd file formats, and \n on Unix/modern Mac. You want to detect any of them as a line break but you don’t want to break twice on \r\n.

I usually do something like this if I’m not sure what platform a file came from:

String.split(body, ~r{(\r\n|\r|\n)})

1 Like