Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

input: add a way to pipe multiple commands #15921

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Dudemanguy
Copy link
Member

@Dudemanguy Dudemanguy commented Feb 20, 2025

Very rough right now and needs work. But this is mainly to show that what I mentioned in https://github.com/mpv-player/mpv/pull/15845/files#r1962613721 is totally doable.

This lets you pipe multiple commands together in input.conf style syntax like: expand-text "${chapters}" | show-text - where | is the pipe of course and - tells the command to read the result from the preceding command. Chaining them together infinitely should work too: expand-text "test" | expand-text - | expand-text - | expand-text - | show-text - You can also specify - for multiple arguments to have the same thing substituted multiple times but not sure that has any practical use.

This only makes sense if the previous command outputs an actual result. AFAIK most of them don't, but you can use expand-text as cat basically so that's handy and the property expansion lets you do silly things like expand-text "${seeking}" | set vo -.

Main open question right now is: how many types should we even attempt to handle with this? I'm not even sure if any command right now returns anything other than a string in the result. I know in #15845 file-dialog stores a node array so that needs to be implemented here. But that's just a bunch of strings. I'm thinking the node won't ever realistically have anything other than a string or strings in it, but could be wrong.

Copy link

github-actions bot commented Feb 20, 2025

Download the artifacts for this pull request:

Windows
macOS

@kasper93
Copy link
Contributor

One thing to consider is that - is already used keyword and for example loadfile - will start playback of data from stdin. It's probably fine to override it in context of piping commands, but I just wanted to mention this.

Bonus chatter: one thing that is probably out of scope of this PR is basic manipulation of the data, say we get node map and just want to extract one value. This could be done similarly to how jq command works. For example comand-foo | bar .[0] | loadfile - which would get first element and pass it as string. Though this is rabbit hole, how much operations we want t support. I'm just throwing ideas.

@Dudemanguy
Copy link
Member Author

Dudemanguy commented Feb 21, 2025

- needs support for escaping/quoting like how you have to do it with ; if you want to use the string directly and not the command separator. I didn't implement it in the parsing yet since it has to be a bit separate from the already existing stuff.

one thing that is probably out of scope of this PR is basic manipulation of the data, say we get node map and just want to extract one value

I don't think this a bad idea in principle. But it's just hard to imagine the need ever arises outside of maybe the eventual file-dialog command? I think (didn't 100% check) that currently all of the commands that output actual usable things to the result node are simply strings so there's probably not even anything that could actually use it. That said, such a command should be pretty simple as long as we limit it to reasonable syntax.

@Dudemanguy Dudemanguy marked this pull request as ready for review February 22, 2025 00:34
@Dudemanguy
Copy link
Member Author

Quoting should work properly now. Moving the command result around is kind of awkward, but didn't really think of anything better.

@avih
Copy link
Member

avih commented Feb 22, 2025

I understand the value of this being nicely generic, and also that this is presumably a sort of proof of concept and not necessarily a fully-baked thing (judging by "Very rough right now and needs work. But this is mainly to show that what I mentioned in ... is totally doable."), so I do keep this in mind below.

Do you have real-world use cases in mind where this can be useful to do things which are impossible or inconvenient with the current input.conf syntax, other than file-dialog?

And specifically with file-dialog, at least as far as I can judge currently with regards to usability-only, it's much less convenient and more limited than the code which is currently implemented at #15845 where each command is modified, because I don't see an obvious way to automate the custom dialog options per command like that PR does - which I think was argued as an important factor with file-dialog.

Still in the context of file-dialog only, I made a more detailed comparison of the pipe approach here with a fictional approach of a dlg command or prefix which could achieve similarly generic application of the dialog with arbitrary commands like this pipe, but without losing the ability to also tailor custom dialog options for specific commands - like the existing code at the PR does.

And while few of the bullets there were addressed by @Dudemanguy, I think most of them were not. So maybe here is a better place to continue that subject?

@kasper93
Copy link
Contributor

As a proof of concept could we fix clipboard in this PR?

Replace

ctrl+v loadfile ${clipboard/text} append-play

with comething like

ctrl+v sanitize-path ${clipboard/text} | loadfile - append-play

The main objective would be to fix case like this one #15576 (comment) but not limited to we can also prevent passing (error) with clipboard fails and so on.

Do you have real-world use cases in mind where this can be useful to do things which are impossible or inconvenient with the current input.conf syntax, other than file-dialog?

See the above.

And specifically with file-dialog, at least as far as I can judge currently with regards to usability-only, it's much less convenient and more limited than the code which is currently implemented at #15845 where each command is modified, because I don't see an obvious way to automate the custom dialog options per command like that PR does - which I think was argued as an important factor with file-dialog.

The main idea was to replace set-property argument in file-dialog. Currently this is the only way to set properties with file dialog output and it's not related to commands, which are indeed implemented in the other pr.

@Dudemanguy
Copy link
Member Author

Dudemanguy commented Feb 22, 2025

Edit: sorry my mistake. The parsing in this case succeeds but there's no data and indeed no error message so it would work.

@avih
Copy link
Member

avih commented Feb 22, 2025

with comething like

ctrl+v sanitize-path ${clipboard/text} | loadfile - append-play

The main objective would be to fix case like this one #15576 (comment)

This is cute, but the suggestion at the reply to that comment feels to me much simpler - to support something like ${clipboard/filename} or ${clipboard/sanitize} or some such, because this sanitation might be specific only to clipboard (at least I think this is the only case we're aware of).

we can also prevent passing (error) with clipboard fails and so on.

That sounds interesting, but I don't see how this improves with the pipe. Wouldn't loadfile execute either way, regardless if it gets an error or something else which indicates "no value" directly from ${clipboard}, or as output from the sanitize-path command?

The main idea was to replace set-property argument in file-dialog. Currently this is the only way to set properties with file dialog output and it's not related to commands, which are indeed implemented in the other pr.

Huh... so you guys don't see the pipe as a viaable alternative to modifying specific commands for file-dialog support?

Is the set-property support in the file-dialog implementation cumbersome or too much code or inconvenient to use which makes you feel that implementing pipe support would address this need(?) better?

As I said, I do get that it's nicely generic and might be able kill many stones with one bird(!), but at least with the few cases mentioned here (clipboard sanitation, dialog -> set-property, and tailored-dialog-options-for-commands) this is either already implemented or insufficient or might be replaced with something specific and simple which fits the context (sanitation).

@kasper93
Copy link
Contributor

This is cute, but the suggestion at the reply to that comment feels to me much simpler - to support something like ${clipboard/filename} or ${clipboard/sanitize} or some such

This works only for clipboard, sanitize-path is generic command. It could even be normalize-path that already exists.

That sounds interesting, but I don't see how this improves with the pipe. Wouldn't loadfile execute either way, regardless if it gets an error

That's up to discussion. I don't think pipe chain should continue if any of the command in chain failed. What would be the point?

@avih
Copy link
Member

avih commented Feb 22, 2025

This is cute, but the suggestion at the reply to that comment feels to me much simpler - to support something like ${clipboard/filename} or ${clipboard/sanitize} or some such

This works only for clipboard, sanitize-path is generic command. It could even be normalize-path that already exists.

Yes, but the part I wrote which you forgot to quote is that currently this is the only case which we know of which needs sanitation.

It's obviously trivial to come up with other cases, but not ones which are unavoidable normally.

The clipboard on win11 from explorer is the only real use case which needs a solution, which I know of at least.

That sounds interesting, but I don't see how this improves with the pipe. Wouldn't loadfile execute either way, regardless if it gets an error

That's up to discussion. I don't think pipe chain should continue if any of the command in chain failed.

I see, so you're adding features, and it grows into a mini shell.

Off the top of my head, I think it can make sense with a pipe, but I didn't think about it enough.

At least with a shell, which I presume is the inspiration for this enhancement of input.conf syntax, it doesn't stop at the first command which fails, or even care about the exit code of any command except the last (of course, we do have pipefail with POSIX 2024, and earlier in some shell, but that is not the default, and it still doesn't stop the other commands at the pipe).

In this context, there are other concerns I raised at my post at the other PR regarding the pipe, about who interprets - and when, using a value - as argument, and general commands syntax which is used with real commands (in a shell) which help in this regards, but which are not implemented with mpv commands (yes, I know that some of these concerns were addressed or being discussed).

Eventhough I very much like the concept of a pipe, and its generality, even in mpv, and even considering that this may be useful to more things than we know of currently, from what I've seen so far, it feels to me that addressing each concern individually is still a better approach.

The clipboard error specifically does pose an issue which I think can indeed be solved well using pipe+abort-on-first-error approach suggested here, but I didn't think about it enough, and there might be other satisfactory solutions besides the pipe.

@Dudemanguy
Copy link
Member Author

As a proof of concept could we fix clipboard in this PR?

I added a sanitize-path command. I'm not sure what exactly you had in mind so it doesn't do much beyond stripping surrounding quotes.

I don't think pipe chain should continue if any of the command in chain failed. What would be the point?

The current implementation is that it does continue. At least as far as shell semantics goes, that would be the expected behavior as well.

In this context, there are other concerns I raised at my post at the other PR regarding the pipe, about who interprets - and when, using a value - as argument

I'm not sure I understand what the concerns are. - is interpreted at parsing time by the input.conf parser. Any command argument can be substituted with the - character which means it will instead take the value of the previous command value. If you want to use the literal - character you have to quote it.

@avih
Copy link
Member

avih commented Feb 22, 2025

- is interpreted at parsing time by the input.conf parser. Any command argument can be substituted with the - character which means it will instead take the value of the previous command value. If you want to use the literal - character you have to quote it.

What happens if there are two unquoted - in one command?

Hmmm.. is this an extension of the input.conf syntax? I believe until now there was zero difference between using - or "-" or '-' at input.conf syntax, but now there is a difference?

Does this difference only exist when the command is part of a pipe? does it apply to the first command in a pipe too? Will my input.conf which I wrote yesterday and has unquoted - break if this is merged?

This specific thing is a very slippery slope IMO in making the input.conf syntax more complex and fragile than it needs to be.

This is not completely without precedent though. In (posix) shell, there can indeed be difference in few cases of strings which looks completely normal but behave differently depending on quoting (like the here-document boundary word, which elsewhere is interpreted identically regardless of quotes, but in here-doc it specifies whether the content would be expanded or not, and few other cases).

However, these are also the more notorious parts of shell syntax, and IMO this behavior creep from shell is an extremely slippery slope which may be very hard to stop as more people would start using this.

We need to think very hard and long about where this could go. The pipe is cute, and so is the abort-on-first-error behavior, but I do not think mpv should implement mini-shell which interprets input.conf syntax.

We already support two builtin scripting languages which are exactly intended for things which are hard or impossible to do at input.conf. We don't want to make input.conf a NIH scripting language IMO.

Very similar to typical shell semantics. If a command writes output to
a result, the next command can now read those results and use it. The
current implementation assumes that the only command results will always
be strings and does not attempt to deal with any other type. This can
always be expanded in the future if a need arises.
@Dudemanguy
Copy link
Member Author

What happens if there are two unquoted - in one command?

Both are substituted. I'm not sure if there's any practical use for this, but I see no reason to disallow it and it would be more work to only apply it to one -.

Hmmm.. is this an extension of the input.conf syntax?

Of course, there's no other way this could work.

Does this difference only exist when the command is part of a pipe? does it apply to the first command in a pipe too? Will my input.conf which I wrote yesterday and has unquoted - break if this is merged?

So I just updated the implementation a little bit that I think addresses this in a reasonable way. The only unconditional special character this PR adds is |. I highly doubt that anybody was using that in their conf, but if so it needs to be quoted now like ;. - is only interpreted specially if there is a preceding command and it was separated by |. So for example this: expand-path foo | show-text - would print foo but this: expand-path foo ; show-text - would print -.

We need to think very hard and long about where this could go. The pipe is cute, and so is the abort-on-first-error behavior, but I do not think mpv should implement mini-shell which interprets input.conf syntax.

FWIW, there is no abort-on-first-error behavior currently. I'm undecided on that because ; currently fails at parsing time or it executes anyway depending on what exactly the user error was. Anyways, this is a fairly simple implementation that is merely an extension of the already existing multi-command syntax. It is not like this is the first instance of shell-like syntax/behavior in input.conf. We already have ; and ${variable} syntax. There is no intent or attempt to implement a "mini-shell" in this PR and I see no reason why that would suddenly start to happen. I just noticed that a very common pattern in shell, passing output from one command to another, would solve a problem kasper was trying to solve. And it turns out it can also be used to solve another issue that a user was experiencing with the clipboard. It's a generic solution that can be flexibly used in lots of ways. The required code for this is not much at all. The actual functional changes are not even 100 lines. Seems like a no brainer win-win to me.

@avih
Copy link
Member

avih commented Feb 22, 2025

Hmmm.. is this an extension of the input.conf syntax?

Of course, there's no other way this could work.

Of course there is. If the command itself decides how to interpret -, and which ones are interpreted as stdin. I already mentioned exactly this at my comment at the other PR. Then it doesn't need special handling at the parser, and this is also what happens with normal commands at the shell.

EDIT: the | part obviously needs to be at the parser, if that's what you meant. But I was asking specifically about the -, and I assumed your reply referred to that. Apologies if the question was unclear, but I meant to ask whether unquoted - is an extension.

Admittedly, I have zero experience in language design, and this is completely outside of my comfort zone, but I can still see clearly what it does and compare it to similar platforms and their advantages and weaknesses in historical perspective (shell).

The implementation of - at the parser is superficial, because currently it looks like too much work to start modifying each command for this (and I agree, it's too much work which is probably not worth it). But this is a technical debt, which is easy to do now, but may return to bite us later.

So I just updated the implementation a little bit that I think addresses this in a reasonable way. ...

Agreed, it's a bit better, and now also well specified. But the other factors remain.

FWIW, there is no abort-on-first-error behavior currently. I'm undecided on that because ; currently fails at parsing time or it executes anyway depending on what exactly the user error was. Anyways, this is a fairly simple implementation that is merely an extension of the already existing multi-command syntax.

I know and understand. The abort part was suggested just now, and I actually like it, regardless if it ends up implemented or not.

I said what's here is cute, even ignoring necessity or alternatives.

But overall, in the big picture, you have to agree that this looks like behavior creep from shell, with shortcuts to simplify the implementation (like identifying - at the parser), and with potential to grow further in behavior and features (like the abort-on-error, but also in other ways), on top of an already non standard input.conf syntax which is already hard to use with complex inputs.

And we already have two proper languages which are well specified and documented and which can do real procedural behavior, including what the pipe feature supports (i'm not even suggesting to write a script which does pipes, but it's entirely possible).

I get that it's fun to write, and maybe with some real immediate value in specific use cases, but I think the cost and the technical debt in the long term is not worth it, especially when we already have lua and js to complement input.conf in a very meaningful way.

@Dudemanguy
Copy link
Member Author

Dudemanguy commented Feb 22, 2025

Of course there is. If the command itself decides how to interpret -, and which ones are interpreted as stdin. I already mentioned exactly this at my comment at the other PR. Then it doesn't need special handling at the parser, and this is also what happens with normal commands at the shell.
EDIT: the | part obviously needs to be at the parser, if that's what you meant. But I was asking specifically about the -, and I assumed your reply referred to that. Apologies if the question was unclear, but I meant to ask whether unquoted - is an extension.

No worries. The - part could indeed be implemented in every individual command that we deem chooses to interpret this. But that, as you say later, is too much work and I would say is not worth it. Something like this should be transparent to the internal logic of every command.

But overall, in the big picture, you have to agree that this looks like behavior creep from shell, with shortcuts to simplify the implementation (like identifying - at the parser), and with potential to grow further in behavior and features (like the abort-on-error, but also in other ways), on top of an already non standard input.conf syntax which is already hard to use with complex inputs.

I don't understand why you're calling it a shortcut. - is a special character in certain circumstances. Identifying this at the parser is the most natural and logical place to do it. It is of course possible to put the special character interpretation within the commands themselves, but I don't see how this is better or desirable in any way. That greatly complicates everything and of course isn't extensible. But anyways no I don't agree. Is it a new feature? Sure. Is it "behavior creep?" I mean no what do you even mean by that? Is there some law that input.conf must never get any new features? This feature maps very neatly onto input.conf syntax which already looks a lot like shell. It looks perfectly in scope. If hypothetically in the future someone wants to add something else, we can discuss if it is appropriate based on its own individual merits. Trying to argue something along the lines of "well someone might try to add even more things in the future" strikes me as absurd. mpv rarely reject features. As long as it makes sense and the solution is technically sound, we almost always accept a feature. I also don't understand what "non standard input.conf syntax which is already hard to use with complex inputs" is supposed to mean. Is there some standard we should be following? How is it hard to use? I think input.conf is quite easy. I don't know what "complex inputs" is referring to.

And we already have two proper languages which are well specified and documented and which can do real procedural behavior, including what the pipe feature supports (i'm not even suggesting to write a script which does pipes, but it's entirely possible).

input.conf is great because it allows users to do fairly complex things without having to write a single line of code. Sure I fully understand that there is a limit and we shouldn't be trying to turn it into some kind of 3rd pseudo language. But this is PR is nowhere near that. You can bring up this point if someone tries to implement data structures or something in input.conf. This is a very natural piping idiom that even noobs at the shell can use and understand.

I get that it's fun to write, and maybe with some real immediate value in specific use cases, but I think the cost and the technical debt in the long term is not worth it, especially when we already have lua and js to complement input.conf in a very meaningful way.

Can you actually explain in concrete terms what "cost" and "technical debt" are being incurred here?

@avih
Copy link
Member

avih commented Feb 22, 2025

Can you actually explain in concrete terms what "cost" and "technical debt" are being incurred here?

Sure.

Both of them refer to the long term.

Technical debt means that shortcuts are taken now because it's easier, but they may make it hard to extend generically or maybe require workarounds in the future which we don't envison now, because they're not the "real" correct way. This referred specifically to interpreting - at the parser, where I think the correct place to do it is at the command itself (not saying we should do that, only that this is the correct place for it).

The long term cost is both in terms of supporting this mini language, handling issues, and potentially enhancing it further as deficiencies are identified or new enhancements are identified as useful. This is not a new language which you're desiging now from scratch and you can make great decisions about how the parts fit together. It already exists and it's already complex, and any new addition - like this pipe, adds on top of that.

One way to look at it is "it's only a pipe and it's easy and useful and we can always consider each enhancement individually", and I can even agree with most of those. Another way is to take a step back and look at what it already is, what's the potential trajectory here, assess the overall value which it adds vs the altrenatives which already exist or which can be created with some effort, and try to forsee whether this is a good path to walk in.

All of these are obviously subjective and no two people would have identical points of view. But for me, it feels like not a good path, especially considering the exting complexity of input.conf syntax, and the existing lua/js support in mpv which can extend it effectively as much as someone wants to put effort into it.

@Dudemanguy
Copy link
Member Author

Dudemanguy commented Feb 22, 2025

This referred specifically to interpreting - at the parser, where I think the correct place to do it is at the command itself (not saying we should do that, only that this is the correct place for it).

I don't agree. - necessarily requires the interaction of multiple commands to be interpreted and thus is a global identifier. To implement it correctly, the parser has to have knowledge of it. Consider the very simple case of expand-path foo | show-text -. The parser has to be aware of | already and take that into account. No way around that one. Additionally the output of the expand-path must be stored in the global state (in this case, that would be the list of commands that is created by the parser) and passed some way to show-text. The show-text command alone is not capable of getting the result. So we already have the parser essentially taking care of most of the work. Now the final question is who should interpret - and the answer is of course: the parser as well. Here's why: how do you tell the difference between a string literal - and the idiom? show-text can't know this on its own. It has to get the information from the global list of commands. And that information ultimately is sourced by, once again, the parser. So sure, you could write code in show-text that does the if string == - then show-text 'previous-command-output' but the only way to know if that - is a string literal or not is to rely on the parser.

The long term cost is both in terms of supporting this mini language, handling issues, and potentially enhancing it further as deficiencies are identified or new enhancements are identified as useful. This is not a new language which you're desiging now from scratch and you can make great decisions about how the parts fit together. It already exists and it's already complex, and any new addition - like this pipe, adds on top of that.

I find this entire argument to be incredibly disingenuous. This is not a "mini language". There is no intention to make a "mini language". This does not even have 1% of the features I would expect from any language. Please stop calling it what it is not. You keep making claims about "complexity" but have not actually quantified actually is complex or so hard to support. Again, this feature is merely a simple addition to the already existing multi command execution that we have in input.conf. The functional changes are fairly small and easy to understand. You can already already execute multiple commands in succession. All this does is allow one command to pass its output to another command. It is a small addition to the chain of commands logic. Nothing more.

One way to look at it is "it's only a pipe and it's easy and useful and we can always consider each enhancement individually", and I can even agree with most of those. Another way is to take a step back and look at what it already is, what's the potential trajectory here, assess the overall value which it adds vs the altrenatives which already exist or which can be created with some effort, and try to forsee whether this is a good path to walk in.

This is just fearmongering. It's a generic, simple solution that can solve usecases previously discussed and possibly more. Vague appeals to how somehow this is going to lead to some dark trajectory doesn't make sense and honestly is just nonsense.

All of these are obviously subjective and no two people would have identical points of view. But for me, it feels like not a good path, especially considering the exting complexity of input.conf syntax, and the existing lua/js support in mpv which can extend it effectively as much as someone wants to put effort into it.

I don't think input.conf syntax is complex.

@avih
Copy link
Member

avih commented Feb 22, 2025

And just to not be completely negative, here's something which I do see as a good path to walk in: all the recent UI enhancements using scripts, mainly select.lua and the ever-extending use cases where it applies.

I think it's great, it adds value to users almost without affecting development of the core of mpv (up to new support functionalities at the core which are not simple or practical to keep in a script).

That's obviously off topic, it's not black and white either, and supporting these scripting UI enhancements is also not without cost, but it's contained in a way which I think minimizes the long term cost. This is obviously a subjective view as well.

@CogentRedTester
Copy link
Contributor

CogentRedTester commented Feb 22, 2025

input.conf is great because it allows users to do fairly complex things without having to write a single line of code. Sure I fully understand that there is a limit and we shouldn't be trying to turn it into some kind of 3rd pseudo language. But this is PR is nowhere near that. You can bring up this point if someone tries to implement data structures or something in input.conf. This is a very natural piping idiom that even noobs at the shell can use and understand.

I think what @avih is trying to say is not that people should be writing a Lua script to do this, but that a Lua script could easily be created that performs this piping operation without needed to modify the player core. I wanted to test this out so I tried writing a script that pipes the output of one command to another, and it turns out to be pretty simple:

local mp = require 'mp'
local msg = require 'mp.msg'

local err_obj = {}

local function main(...)
    local args = {...}
    if #args == 0 then return end

    local commands = {{}}

    local tail = 1
    for _, arg in ipairs(args) do
        if arg == '|' then
            tail = tail + 1
            commands[tail] = {}
        else
            table.insert(commands[tail], arg)
        end
    end

    local carry = nil
    for i, command in ipairs(commands) do
        for j, arg in ipairs(command) do
            if arg == '-' then
                command[j] = carry
            end
        end

        local res, err = mp.command_native({'osd-auto', unpack(command)}, err_obj)
        if res == err_obj then
            mp.osd_message('error: '..err)
            msg.error(err)
        end
        carry = res
    end
end

mp.register_script_message('pipe', main)

With this a simple entry in input.conf:

<key> script-message pipe normalize-path "${filename}" | show-text -

Allows return values from commands (the few that have them) to be inserted into the next command.


Obviously this is a very naive example that is likely buggy and with little to no error handling or input validation, but it shouldn't be difficult to add, along with other features. The only downside is the script-message pipe that needs to be added to the start, otherwise this approach seems to provide identical benefits.

@avih
Copy link
Member

avih commented Feb 22, 2025

The parser has to be aware of | already and take that into account. No way around that one

And I never had issues with this part. We agree this should be interpreted by the parser/"shell". I already said that explicitly before.

I don't agree. - necessarily requires the interaction of multiple commands to be interpreted and thus is a global identifier. To implement it correctly, the parser has to have knowledge of it

Is it really not enough to answer it in one word: shell?

The shell doesn't have knowledge of it, and yet pipe has magically worked and still works for about 5 decades now.

The connection which the shell identifies is the pipe syntax. Not the - syntax.

So as much as you see - as essential part of the parser, history clearly thinks otherwise.

Maybe it's harder to implement for mpv without identifying - at the parser, and this is something I can imagine is actually true. Doesn't change the fact that it's most probably not a neccessity, and it depends on how much effort you want to put into it now. I certainly won't ask you to make this effort, and I don't think anyone should make this effort, which is kinda my point.

I'm not arguing about the rest because it's subjective. I can only say how I feel about it, and I'm definitely not saying that your point of view is wrong.

@Dudemanguy
Copy link
Member Author

Dudemanguy commented Feb 22, 2025

I think what @avih is trying to say is not that people should be writing a Lua script to do this, but that a Lua script could easily be created that performs this piping operation without needed to modify the player core.

Of course and a lua script could easily be created to execute multi commands sequentially too. Why don't we delete all the core input and command code that handles multiple commands and tell people to use scripts?

Is it really not enough to answer it in one word: shell?

That entire explanation was in terms of mpv not the shell. It is not the same thing and I'd appreciate it if you would not conflate it.

Maybe it's harder to implement for mpv without identifying - at the parser, and this is something I can imagine is actually true. Doesn't change the fact that it's most probably not a neccessity, and it depends on how much effort you want to put into it now.

What? How do you tell the difference between "-" and - in input.conf if the parser isn't identifying it? And you still haven't given any actual reason why this is somehow a bad thing other than some handwavy nebulous "muh technical debt trust me bro". I need actual concrete reasons.

@avih
Copy link
Member

avih commented Feb 22, 2025

I think what @avih is trying to say is not that people should be writing a Lua script to do this, but that a Lua script could easily be created that performs this piping operation without needed to modify the player core.

Of course and a lua script could easily be created to execute multi commands sequentially too. Why don't we delete all the core input and command code that handles multiple commands and tell people to use scripts?

It's not of course. I did not say that and I did not try to say that. I even said explicitly that I'm not suggesting to implement pipe as a script.

Don't put words into my mouth, and don't jump blindly on any suggestion that this is what I wanted to say, especially when I explicitly said exactly the oposite.

Just so that you don't have to look it up:

And we already have two proper languages which are well specified and documented and which can do real procedural behavior, including what the pipe feature supports (i'm not even suggesting to write a script which does pipes, but it's entirely possible).

What I said and meant is that input.conf can already be extended in infinite ways using scripting, and therefore the enhancement of input.conf syntax is not an insurmountable limitation, and there's no real need to extend it meaningfully, be it pipes or whatever else. This doesn't include fixes or even minor refinements, which of course should be implemented if issues are identified. (please let's not start an argument about the threshold for "minor refinements")

There was also no suggestion about convenience. I certainly agree that it would be nicer to use pipes directly at input.conf (if the user can find a real use for it) rather than writing a script or using a 3rd party script which achieves a similar goal. I even called it "cute" more than once. I did mean it. It's cute and convenient.

Heads up, just in case you missed the last line, please don't try to convince me that it's more convenient at input.conf. I think it's quite obvious that it is indeed convenient.

Also, in case you forgot or missed that, because this seems to be a highly recurring theme, I'm not suggesting to replace pipes or any other core part of mpv with a script. Can I count on you to remember this? Do you need me to put a sticky note someplace so that you can come back to this message and re-check just to be sure whether or not I'm suggesting to replace pipes with a script?

The point of this part was to say that it's possible also without input.conf pipes syntax.

Is it really not enough to answer it in one word: shell?

That entire explanation was in terms of mpv not the shell. It is not the same thing and I'd appreciate it if you would not conflate it.

This reply was about the general notion that identifying - must be done by the "top level" parser, and it demonstrated that this is not some absolute truth, because the very inspiration for this pipe feature in mpv (shell) does not do it or need it. In the shell-commands ecosystems the commands themselves decide how to interpret -, or if they even need it when using a pipe, like foo | tail where there's no - interpreted by the shell or by anything, and yet the pipe works.

If all your statements which suggested that it must be interpreted by the parser were meant explicitly in the mpv context, then I misunderstood.

I'm going to assume that I misunderstood, and that indeed you meant exclusively in the context of mpv, so let's move on.

Maybe it's harder to implement for mpv without identifying - at the parser, and this is something I can imagine is actually true. Doesn't change the fact that it's most probably not a neccessity, and it depends on how much effort you want to put into it now.

What? How do you tell the difference between "-" and - in input.conf if the parser isn't identifying it?

First, as you can tell from that quote, I never suggested that you or the parser or anyone should be able to tell difference between quoted and unquoted -. On the contrary, I suggested that - should be interpreted in the same way relardless of quoting.

What I also suggested, is that the parser should not even care about -.

But whatever the exact quesiton was, the honest answer is that I don't know because I didn't look at this code recently, and even if I looked, I can't know whether I would be able to understand it enough to give you a straight and fully working alternative to identifying - at the parser. So everything below are assessments.

Back to the answer I can give.

I hope I'm not doing an injustice, but I'll answer the question "how can it work if the parser doesn't identify which argument should be replaced?".

One approach I could imagine is that the context which the command implementation takes as argument has a field which represents "output of the previous command in a pipe".

Elsewhere, "stdin" is the standard input place where applications check "input from someplace", so let's call this command context field "stdin" as a temporary name.

Do correct me if I'm wrong, but I'm assuming the mpv "shell" (parser, however you want to call it) already has to execute the commands in order, because it should be able to replace - with the output of the previous command.

Let's say that the input.conf line is

x cmd-a ... | cmd-b ...

So when it identifies the pipe syntax, and after it got the output of cmd-a, then instead of identifying - as an argument to cmd-b and replace it, it sets stdin of cmd-b to this output.

Then cmd-b does what it wants with it.

If it supports taking input from a previous command, then it checks its stdin. If it doesn't support it, then it doesn't check its stdin. If it only supports it in place of a - argument, then this is how it uses its stdin.

We can even do here things which don't work with normal pipes, like making it possible to identify at the the value of stdin whether there was no previous command in the pipe, or there was a previous command which for some reason didn't have an output - maybe like if there was some error there.

Does this answer the question of "how to do pipes without the parser identifying which argument should be replaced"?

I hope it does answer, at least in rough outline, the "it's not possible" and "how can it be possible" questions.

However, even if it is possible, this IS work. The parser part maybe not so much, probably even less work that identifying -, but now, if we actually want it to work in practice, then indivdual commands would need to be modified.

Maybe there's some way which could make most of them do that automatically. Maybe there isn't, and indeed it requires tedious modifications of commands. It's entirely possible that it's the latter, which probably makes it hard, but not impossible.

And this is what I meant in what you quoted me.

And you still haven't given any actual reason why this is somehow a bad thing other than some handwavy nebulous "muh technical debt trust me bro". I need actual concrete reasons.

The concrete reason is that it adds special cases to the syntax where the same - argument at input.conf can be interpreted in two different ways, depending on however you very nicely specified it, but which is very much not "always the same way".

This is an idiosyncrasy, just one more on top of the existing ones, which makes input.conf syntax just a little bit harder to grok than before, and this is what I call increasing technical debt, because it's another factor which you can't forget about from now on.

Mandatory reference: Monty Python's The Meaning of Life, the restaurant scene.

@Dudemanguy
Copy link
Member Author

Dudemanguy commented Feb 22, 2025

First, as you can tell from that quote, I never suggested that you or the parser or anyone should be able to tell difference between quoted and unquoted -. On the contrary, I suggested that - should be interpreted in the same way relardless of quoting.

What? So now you just randomly decided that we shouldn't attempt to identify the string literal "-"? Why? This is just after I made a few changes to ensure that it would still work like before. Unbelievable. You have to be kidding me you literally said earlier:

Will my input.conf which I wrote yesterday and has unquoted - break if this is merged?

That statement quite obviously implies that you expected the quoted "-" to still work. And yes, I would too. That is a reasonable expectation. If you decide to suddenly not care about if the syntax was quoted/escaped then sure the problem gets easier.

We can even do here things which don't work with normal pipes, like making it possible to identify at the the value of stdin whether there was no previous command in the pipe, or there was a previous command which for some reason didn't have an output - maybe like if there was some error there.

We can and already do that with my solution.

Does this answer the question of "how to do pipes without the parser identifying which argument should be replaced"?

No it doesn't answer the question because you ignored it, arbitrarily changed the terms and answered something else completely.

The concrete reason is that it adds special cases to the syntax where the same - argument at input.conf can be interpreted in two different ways, depending on however you very nicely specified it, but which is very much not "always the same way".

This is not what the term "technical debt" means and it's frankly insulting that you insist on calling an enhancement to input.conf syntax that can be implemented in an almost perfectly backwards-compatible way (literally the only thing that would break would be something like show-text |) as "technical debt".

Also it is ridiculous that you call this solution "technical debt" and then turn around and argue that individual commands should all be explicitly modified with some if stdin_arg then blah type of logic. Which is the robust, extensible solution? It sure isn't the latter.

However, even if it is possible, this IS work.

Sorry I need to address this. I can't let you get away with all these endless normative statements. Anyways, no this not "work". This is codemonkey levels of "work" where you go back and modify each command individually. It is not hard. It's just stupid and why would you do this when there are better solutions.

I am very sick of this discussion. Please come back with actual patches, point out something wrong with the code, etc. Dodging points I've made and constantly gaslighting me is not helpful.

@avih
Copy link
Member

avih commented Feb 22, 2025

Maybe it's harder to implement for mpv without identifying - at the parser, and this is something I can imagine is actually true. Doesn't change the fact that it's most probably not a neccessity, and it depends on how much effort you want to put into it now.

What? How do you tell the difference between "-" and - in input.conf if the parser isn't identifying it?

First, as you can tell from that quote, I never suggested that you or the parser or anyone should be able to tell difference between quoted and unquoted -. On the contrary, I suggested that - should be interpreted in the same way relardless of quoting.

What? So now you just randomly decided ...

I didn't randomly decide anything. Look. It's right there at the whole progression of this line of discussion.

I said something very specific, "Maybe it's harder to implement (pipes) for mpv without identifying - at the parser".

You quoted that and said "What? How do you tell the difference between "-" and - in input.conf if the parser isn't identifying it?"

And I want to answer it, but I don't know how, and I don't know why you're asking me. I never said someone should be able to tell this difference, and I don't know the answer to that question, or even why it matters to begin with.

I said the oposite, and thought, apparently wrongly, that you wanted clarification on how it's even possible. So I then then gave a suggestion of how it can work wihout telling the difference and without the parser even caring.

Now, you said so very explicitly, so I have to believe you that it doesn't answer your question. Please believe that I did my best, but apparently failed.

Reminder, my only claim and suggestion in the context of - is that preferably we don't extend the syntax and make it special depending on quotes, and that preferably it's not the parser which needs to identify where the input from the previous command should be inserted.

I hope we can agree that these are the things I said about the - (not getting into implications of not doing that).

So do you have a question about these things, or other things which maybe I can help clarify in the context of "I don't think identifying '-' belongs in the parser"?

@Dudemanguy
Copy link
Member Author

This a complete and utter waste of my time. The general problem of "identifying -" includes, quite obviously, telling the difference between the string literal variant "-" and the unquoted version. The entire point was about how that is a job for the parser. You dodged/misinterpreted/whatever and went off some completely unrelated tangent. I really don't care if it was in good faith or not (sure feels like it wasn't like most of this "discussion") because I am not going to try and bother communicating any further. I do this for completely free and for fun. It is not like it is my job to put up with painful people.

People that have actual productive things to say are always welcome.

@avih
Copy link
Member

avih commented Feb 22, 2025

I really don't care if it was in good faith or not (sure feels like it wasn't like most of this "discussion")

I could say exactly the same about you, but I won't, because this won't help the discussion in any way. So I give you the benefit of doubt that it was in good faith.

I can say about myself without any doubt that it was in good faith, and I hope you could accept it as well.

I am not going to try and bother communicating any further.

Considering how it went so far, I can't blame you, and I'll do the same. Both because it takes two to tango, but also because I don't have anything else to say which I didn't already say before.

But if at some stage you have some question which you think was not answered by what I said above, and you do want to hear my reply, then do ask.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants