cbucher / console

This is a modified version of Console 2 for a better experience under Windows Vista/7/8/10 and a better visual rendering.
https://github.com/cbucher/console/wiki
GNU General Public License v2.0
2.93k stars 231 forks source link

-r argument #427

Closed polyvertex closed 7 years ago

polyvertex commented 7 years ago

Hi! Thanks for forking Console2 and putting so much work into it.

The -r option seems restrictive at use due to the fact that all the arguments you want to pass to the shell must fit into -r's option (unless I missed something?). Is there a way to pass your arguments to the shell as-is, without having to worry about quoting?

cbucher commented 7 years ago

The purpose of -r is to pass arguments to the shell command line. ConsoleZ cannot reinvent your shell options. Using or not ConsoleZ, the easiest way is to create a script file.

For example, create a .bat file for cmd.exe...

polyvertex commented 7 years ago

I understand the use of -r, this is more of a feature request than a "how to" question. Creating a trampoline script seems more inconvenient than easy and, if I may, I don't think ConsoleZ needs to "reinvent" the options of the target shell: just to pass them as-is from one command line to another.

For doing so, ConsoleZ would need a well-known delimiter so it can cut its command line and pass the right part of the command line to the right shell. Perhaps one way to do it is the traditional Unix way by using something similar to --? In practice, I'm aware that -r may be specified several times so just -- might not fit here. For that reason, a more recognizable one like --@[N] for example, where N is optional and a positive integer that matches the index of the previously specified -t option in the command line.

Examples:

  1. Console.exe -t bash -d C:\WINDOWS -t cmd -d D:\ --@ ls -al --color=auto --@ echo "Hello World"
  2. Console.exe -t bash -d C:\WINDOWS -t cmd -d D:\ -t ncft --@2 echo Hello

In example 1, the command ls -al --color=auto is passed to the shell of the first specified tab, which is bash here. Command echo "Hello World" is passed to the shell after, and so on... Using the index would then allow to target a specific shell like in the second example.

An important thing to note is that this addition is backward-compatible. -r could still be used instead of its --@ variant. And in case both variants happen to be used for the same -t option, you may decide at implementation time either to overwrite the existing state, or just fail (which is the option I would recommend to avoid any confusion and unexpected behavior).

Would you see any cons against this feature?

cbucher commented 7 years ago

Is there a way to pass your arguments to the shell as-is, without having to worry about quoting?

How do you handle commands with -c/-w/-ws/-t/... without quoting them? Without quoting is impossible!

Example 1, I don't understand how commands at the end can be correctly dispatched to tabs. Example 2, better but no consistent with current command line syntax.

If you specify multiple -t options, you can specify multiple -d and -r options as well. In that case, each -t, -d and -r option will be grouped together.

Here, you don't define commands (passed on shell command line) but inputs (simulating what you type on keyboard). This is really different! How to handle line returns, specials key combinations, ...? Because if you add this feature people, will want to use it to enter password, fill a form, ...

polyvertex commented 7 years ago

How do you handle commands with -c/-w/-ws/-t/... without quoting them?

The point of this feature is not about "not quoting", it's about giving the ability to actually pass a command line to the shell on a one-to-one basis instead of having a whole command line concatenated into a single argument (i.e. the -r option), with all the escaping issues that this implies.

This inheritance from Console2 is flawed by design (no pun intended), because it forces the user to specify a whole command line into a single argument, or to use the inconvenient alternative of a trampoline script where it should be avoidable in many cases.

This leads us to the traditional -- sequence, which exists for that very purpose. The idea behind it could be adapted to ConsoleZ and that is the reason of this feature request.

Example 1, I don't understand how commands at the end can be correctly dispatched to tabs

Sequentially. If no N index (one-based) is specified, the command line behind the first --@ occurrence would be associated to the first specified tab, the second occurrence goes to the second tab and so on.

To elaborate on how it works: this automatically allows the user to have more complex mixtures like: console.exe ... --@ A --@3 B --@ C

Where A would go to the first tab specified on the command line, B to the third specified tab and C to the fourth tab.

Example 2, better but no consistent with current command line syntax

The implementation proposed here allows both backward-compatibility (again, the -r option could still be used) and an easier and more standard way to pass a command line to a shell. I fail to see how it can do any harm to ConsoleZ.

polyvertex commented 7 years ago

@cbucher any news on this? Sorry to bump but it's unclear to me whether you actually understood the whole thing and if you would even consider having it integrated in ConsoleZ.

cbucher commented 7 years ago

instead of having a whole command line concatenated into a single argument (i.e. the -r option), with all the escaping issues that this implies.

This is what quoting means.

You have to choose between:

I will follow the advice given to me on gitter: rename "initial command" into "shell arguments". -r is an option to add arguments to the shell command line. This option is not flowed just badly named and documented. Each choice has a reason behind it!

To elaborate on how it works: this automatically allows the user to have more complex mixtures like: console.exe ... --@ A --@3 B --@ C

Really too complex (and inconsistent if I want to pass --@ as shell argument). I don't understand why you want too pass a complex command line to the shell from ConsoleZ command line. Create multiple tabs (specifying shell arguments into tab settings) or start scripts are best solutions: easy, readable, maintainable....

polyvertex commented 7 years ago

I have absolutely no problem with the documentation or the way it is worded so I'm not sure what makes you think it is related to this feature request, which, again, is not a "how-to" question. It seems more to me that you mix up this request with the repeated questions you received so far about -r. Also, your "documentation" argument does not really stand in front of the simple fact that requiring the caller (which is not necessarily the end-user and can be another app) to compact a whole command line into a single argument is a de facto design flaw.

As I suggested it already, the stopper does not have to precisely be --@ and yes, of course it should be unique enough (that's the whole point of a delimiter after all), but that does not mean it must be hard-coded: if you want to get picky it could also be specifiable via an option to allow the caller to override the hard-coded default if necessary. With the obvious constraint that the option must be specified early enough in the command line. So no potential issue here neither.

And your nitpick about the index part of the stopper simply should not be since: first, as shown in the examples it is optional to use it, second ConsoleZ already stores the "initial commands" it reads from the command line in an indexed fashion, so this particular mechanism would come for free at implementation time.

Sorry to see that apparently you will not compromise on accepting a feature that you do not seem to fully grasp anyway. Unfortunately, in addition to the main lines and implementation details I exposed in previous comments, I fail to see how I could elaborate further on this except by repeating that the idea behind having an arg-parsing stopper, which seems new to you, is widely spread, especially on Unix systems, and that there is absolutely nothing "complex" about it, either at use or implementation time.

Hopefully you will mature this and come back to it later by reopening this ticket. Thanks for taking the time to answer

cbucher commented 7 years ago

The subject of an issue is located in the first comment and the title. So this issue is primary a question not a feature request.

Also, your "documentation" argument does not really stand in front of the simple fact that requiring the caller (which is not necessarily the end-user and can be another app) to compact a whole command line into a single argument is a de facto design flaw.

!?! This is not an argument... It was just a remark on how to choose better words in documentation. By the way, your specification is a real design flaw. (It's wrong and inconsistent.)

And your nitpick about the index part of the stopper simply should not be since: first, as shown in the examples it is optional to use it, second ConsoleZ already stores the "initial commands" it reads from the command line in an indexed fashion, so this particular mechanism would come for free at implementation time.

If you call "nitpick" the fact of demonstrate an inconsistency...

Sorry to see that apparently you will not compromise on accepting a feature that you do not seem to fully grasp anyway. Unfortunately, in addition to the main lines and implementation details I exposed in previous comments, I fail to see how I could elaborate further on this except by repeating that the idea behind having an arg-parsing stopper, which seems new to you, is widely spread, especially on Unix systems, and that there is absolutely nothing "complex" about it, either at use or implementation time.

Sorry to see that apparently you will not understand how a command line is parsed. Command line rules:

This is not how ConsoleZ parse the command line, but how Windows parse the command line (and all OSes i know).

There is the definition of "arg-parsing stopper" that I know:

A stopper is a special value that, when encountered in the command line arguments, terminates the processing, and classifies the rest of the strings as arguments, independently of their form.

It can be only one stopper by definition.

polyvertex commented 7 years ago

The subject of an issue is located in the first comment and the title. So this issue is primary a question not a feature request.

Well, I can open a new issue if you really wish so, it's no bother.

It seems that you got offended by my words. If that's so, I apologize, they were not meant to be offensive. In regards to the feature request itself however, I sincerely encourage you to re-read carefully my first reply, everything is in there really.

I mean, didn't it even occur to you that during the whole process of answering me here you may have slightly underrated the meaning of what you were reading? Just one tiny example for the sake of it: when I wrote ConsoleZ already stores the "initial commands" it reads from the command line in an indexed fashion, it implied that I actually had a look to ConsoleZ's source code and more precisely the arg parsing part, then followed the execution flow up to the OpenProcess call (or CreateProcessWithLogonW, depending).

Knowing that, perhaps (hopefully) your next reading(s) of this thread will offer you a new and enlightening perspective that would show you that, one way or another, there's a real and technical benefit in it for your fork because:

cbucher commented 7 years ago

ConsoleZ as well as Console2 just do it wrong

I disagree. I don't like the syntax. But as I said: each choice has a reason behind it. -t is a marker that indicates the begin of a tab declaration and implicitly the end of previous tab declaration. This is consistent.

If you want to add shell arguments to multiple tabs, you have few choices:

  1. You can pass the "shell arguments" as a command line arguments (that's previous author choice)
  2. You can choose complex marker to indicate end of shell arguments, praying for nobody use it in shell arguments (syntax is flawed, praying doesn't work) console.exe -t tab1 -sa dir /b complex_marker -t tab2 -sa dir /b complex_marker -sa: begin shell arguments declaration
  3. You can choose simpler marker and allow overriding the separator (syntax can be dangerous, user is responsive for choosing a good separator valid for all tabs) console.exe -os --@-- -t tab1 -sa dir /b --@-- -t tab2 -sa dir /b --@-- -os: override shell arguments end marker
  4. You can define the marker as first argument following -sa (always complex but better): console.exe -t tab1 -sa --@1-- dir /b --@1-- -t tab2 -sa --@2-- dir /b --@2--

A specification must be right. You cannot say a choice is wrong just because you don't like it.

I you restrict the idea to only one tab, then syntax becomes easy to read: console.exe -t tab1 -sa dir /b

But why pass complex shell arguments int ConsoleZ command line? Why simply don't use workspaces or create multiples tabs? I never have a response to these question. I sincerely interested by a practical case.

polyvertex commented 7 years ago

But why pass complex shell arguments int ConsoleZ command line?

I addressed that already, but well... The caller may not be necessary the end-user himself but another app for example. Thus, it becomes way more convenient to allow the caller to just forward the final shell's arguments blindly.

Regarding the delimiter itself, I notified already that it could be over-writable at runtime via an option specified early enough in the command line, and also that it just had to be unique enough. I suppose you skipped that part as well?

I disagree. I don't like the syntax ... ... A specification must be right. You cannot say a choice is wrong just because you don't like it.

Non-technical and contradictory statements that perfectly illustrates the underlying problem of this thread?

My sentence ConsoleZ as well as Console2 just do it wrong when it comes to parsing the arguments intended to their child processes is not out of a personal preference: again (fourth time!), requiring the caller to compact a whole command line into a single argument is an issue that, ideally, should be addressed. Hence the opening of this ~"how-to" question~ feature request.

Honestly, this isn't going anywhere: your last 4 bullet points basically are an edit of what I wrote in previous replies. Plus I don't see where I mentioned anything about this being final, formal, or a "specification". Something else coming up from your hat? Like the way the documentation is worded or the way a ticket has to be formatted maybe?

cbucher commented 7 years ago

I disagree. I don't like the syntax ... ... A specification must be right. You cannot say a choice is wrong just because you don't like it.

Non-technical and contradictory statements that perfectly illustrates the underlying problem of this thread?

How can you see a contradictory? You compare a "feeling" with a "technical fact"... I think you have some comprehension issues.

I don't like the syntax ..

like is a feeling I indicates that it is a personal felling

A specification must be right.

In computer science, specification purpose is to help with the implementation of systems and software. right means that the algorithm (described by the specification) will be consistent: it's like a mathematical proof. In the context of this subject, a command line parsing algorithm is right if there is only one way to interpret it and if you cannot alter the parsing with argument values (properly escaped).

Concerning choices:

  1. I don't like using -r because value escaping is complicated, but escaping is a problem common to all applications... ConsoleZ doesn't create a new problem. The algorithm parsing is right if caller properly escape quotes.

  2. The algorithm parsing is wrong. Proof: if the complex_marker is used in shell argument, you alter the parsing

  3. The algorithm parsing is right if caller properly choose a good marker. Can be easy to read, but complex to use in a script/program because the script/program have to compute a good marker. In this case escaping is easier.

  4. The algorithm parsing is right if caller properly choose a good markers. Better than 3 if you concatenate tabs.

My sentence ConsoleZ as well as Console2 just do it wrong when it comes to parsing the arguments intended to their child processes is not out of a personal preference: again (fourth time!)

The algorithm is right, it use the CommandLineToArgvW API... What is your definition of right and wrong?

Honestly, this isn't going anywhere: your last 4 bullet points basically are an edit of what I wrote in previous replies.

You confuse bullet and number... Number 1 is the current -r option. The one you want replace.... (-->epic fail ...) Number 2 is wrong.

Your proposal is different: shell arguments are declared at the end of command line breaking the logic of -t. So you have to introduce a number to match tab with this parameter. Personally I found this ugly.

Your specification was wrong (you can alter the parsing with argument values) until you add

it could also be specifiable via an option to allow the caller to override the hard-coded default if necessary.

But you close the issue when you post this comment...

But why pass complex shell arguments int ConsoleZ command line?

I addressed that already, but well... The caller may not be necessary the end-user himself but another >app for example. Thus, it becomes way more convenient to allow the caller to just forward the >final shell's arguments blindly.

This is an imprecise idea not a practical case. If I have to play the riddles: Does your practical case need to launch multiple tabs on the same line?

polyvertex commented 7 years ago

I'm sorry but you still absolutely, fully, completely, utterly miss the point of this feature. The examples you gave in your previous comment (a.k.a. the clumsy edit of the initial idea) just annihilate the benefits of using a delimiter. Worse, they break backward-compatibility which contrasts well with your usage rate of "consistent" and alike. In the end, I'm not quite sure how big is this nebula you go through before writing your messages but what I'm sure of however is that you went far, far away for something that is ridiculously simple to use and to implement out of too much confidence about your knowledge and your take on the situation (and to be honest, take it as you want but it got awkward). Lucky me I didn't make a PR first.

So I repeat, in the unlikely case you genuinely want to understand this feature which, again, is widely spread and could be useful for ConsoleZ: my first reply remains the only material you need. The rest is just me unsuccessfully trying to open the eyes of a horse with a mystical leaning on a wrong way. Until then, I give up and I'm better off doing grocery shopping.

"The hardest part remains to explain it to the maintainer" ©

cbucher commented 7 years ago

my first reply remains the only material you need.

You have chosen to close this issue rather than adapt your proposal. You declined to discuss and improve your syntax. You refused the fact that your syntax was inconsistent and wrong.

Sorry but you have a very bad behaviour!

I'm sorry but you still absolutely, fully, completely, utterly miss the point of this feature.

That's your way of thinking: If people want to modify/fix my idea, then they don't understand the idea. This is insulting. Seriously, you really think I don't understand you want to pass shell arguments without escaping (raw)!?!

The examples you gave in your previous comment (a.k.a. the clumsy edit of the initial idea) just annihilate the benefits of using a delimiter.

No 😞

Worse, they break backward-compatibility which contrasts well with your usage rate of "consistent" and alike.

No😞

It can be only one "arg-parsing stopper" in a command line. So the logical solution is to restrict the new feature:

In this case, syntax is easy to read, consistent, ...

polyvertex commented 7 years ago

I did try to explain, just read my first messageS. It just seems you try hard not to read: again it's not my idea, it's a widely spread and very simple trick that is used to delimit group(s) of arguments (more on that below). Note that the plural in "group(s)" is crucial here for you to understand the nature of our delimiter. A delimiter delimits! The name "stopper" tricked you because you ignored all about it so you just googled it and copy-pasted what you "know" here. But doing so, you forgot to connect the dots with this feature request. "Delimiter" and "stopper" illustrate two views of the same trick.

It's fine not to know. We all learn right? What's not fine however is to use the imperative form and make bare statements without technical background to emphasize your pov on something you unwillingly made clear beforehand that you ignored all about. Maybe that's the reason why you felt insulted?

I say it in a nice way but your "logical solution" at the end of your last message just demonstrates how persisting you are on not getting it. Sure it works. Despite the unnecessary restriction of having only one delimiter. But you loose the benefit of having the ~shell args~, sorry, "keyboard input", at the end of the command line and separated from ConsoleZ's options (it's in bold). Plus it mechanically makes this new format non backward-compatible despite your single "No". The first clue is that you imply the -t option, which should be left aside, as well as every other ConsoleZ' options. For you to understand the reason of this, you first have to know that such a delimiter is usually used to separate args of the called program to the ones that are to be passed to the forked one(s). I.e. its child(ren) process(es). Again this is just how things are, despite all the "logic" you try to put in to prove otherwise. See the delimiter as a better -r if it helps.

The only legitimate concern you had is that many users of ConsoleZ may find the use of the delimiter, the way I presented it (including its indexed form), too far from the usual usage one has of a command line (i.e. program-then-options-period). But this is just a detail you should not be concerned about and here is why:

Also, perhaps a better default delimiter may be ---, which feels less CamelCase than --@ IMHO. Initially I chose @ to illustrate the at in "at tab 1", "at tab 2", ...

Now I hope you understand why this request cannot not be "adapted" to something you write out of ignorance (albeit being written with an imperative form). I mean there's just no debate possible if you do not understand the background of the initial idea.

cbucher commented 7 years ago

A long comment has no purpose but losing time. (Needless to remind me that I came into this game, I regret it.) Be factual. I never seen this syntax, that's right, so simply give a link to this mysterious tool. But at least I can easily see an obvious security breach (command script injection) and I will happy to discuss with the author ;-)

Stop to invent what I think. The important is what I write. Stop to explain the purpose of your proposal ... I understood ... the first time.

cbucher commented 7 years ago

This is an attempt of constructive summary (with some new explanations).

Your first proposal:

  1. Console.exe -t bash -d C:\WINDOWS -t cmd -d D:\ --@ ls -al --color=auto --@ echo "Hello World"
  2. Console.exe -t bash -d C:\WINDOWS -t cmd -d D:\ -t ncft --@2 echo Hello

Why I don't like it:

Syntax is right or wrong?

A modification lost in a long closure comment

an option to allow the caller to override the hard-coded default if necessary

Why I don't like it:

Syntax is right or wrong?

My attempt to improve your syntax

  1. You can define the marker as first argument following -sa (always complex but better): console.exe -t tab1 -sa --@1-- dir /b --@1-- -t tab2 -sa --@2-- >dir /b --@2--

Why I like it:

Syntax is right or wrong?

My preferred solution (the stopper)

It's restricting the usage to only one tab. But this restriction really is a problem? In mono-instance you can launch tab by tab.

Remark: Restriction doesn't break the logic of -t. There is no contradiction.

console.exe -t powershell -t cmd --@ -Command "Write-Host 'yolo --@'"

Syntax is right or wrong?

polyvertex commented 7 years ago

You must be a goat (or a very smart troll). You skipped the part where an option may be added to change the default hard-coded delimiter (that you requested btw): the uniqueness of the delimiter is not an issue. You also skipped my last comment: my syntax does not break the per-tab args grouping logic (not even in the source code), it separates ConsoleZ's options from the args to be passed to the shells.

In the end you make it less useful. Out of good will perhaps, but still. My problem is not that you change my proposal, my problem is that you do it for the wrong reasons.

cbucher commented 7 years ago

But you loose the benefit of having the shell args, sorry, "keyboard input", at the end of the command line and separated from ConsoleZ's options (it's in bold).

Hum I'm perplex.

This is passing shell command line arguments: console.exe -t cmd --@ /U /K "echo hello world"

This is executing a command in the shell. It requires that ConsoleZ simulates keyboard inputs to enter the command. console.exe -t cmd --@ echo hello world

cbucher commented 7 years ago

You must be a goat (or a very smart troll). You skipped the part where an option may be added to change the default hard-coded delimiter (that you requested btw): the uniqueness of the delimiter is not an issue.

You didn't read... see A modification lost in a long closure comment

You also skipped my last comment: my syntax does not break the per-tab args grouping logic (not even in the source code), it separates ConsoleZ's options from the args to be passed to the shells.

I find the separation disturbing. This is personal. I specifically used a section called "Why I don't like it". But this is not important. No matter where you place this arguments, the syntax is unsafe if you have more than one tab.

In the end you make it less useful. Out of good will perhaps, but still. My problem is not that you change my proposal, my problem is that you do it for the wrong reasons.

I am unmasked. I work in secret for a group of people that want to write correct and safe code.

I think that a script can launch one tab at a time : Console.exe -t powershell -sa -NoExit -Command "Write-Host 'Hello World' -ForeGroundColor yellow" Console.exe -t cmd -d D:\ -sa /U /K echo "Hello World" instead of: Console.exe -t powershell -t cmd -d D:\ --@ -NoExit -Command "Write-Host 'Hello World' -ForeGroundColor yellow" --@2 /U /K echo "Hello World" Script can also create a temporary workspace file. Script can launch console application without ConsoleZ. you just have to attach these applications in ConsoleZ. Script can generate a temporary script containing initial commands for each tab.

Temporary workspace file is the only solution if you want a split tab.

Unless you have a script that can handle only one variable, I do not see why you have to put everything on a single command line.

Discussion stops here.

polyvertex commented 7 years ago

Absolutely, your fork, your way