what to call an option to dump to stdout?


I’m working on our “view” command where you can view older versions of files as you want – as an example “h view foo.cs;C123” would view the version of foo.cs at changeset 123 “h view $/bar/ack.cs;Lfoo” would view that server item with the version pointed to by the “foo” label.  One of the things we’ve decided about view (and hence its name) is that we’re going to fire off the registered viewer for the filetype.  This makes a lot of sense to us – if you’re doing an “h view x.y” on some 16MB texture file, surely it’s more useful that it get brought up in your registered viewer of texture files instead of dumped out to stdout.  On the subject though – do you have a preference for whether the default for the command (whatever the command is called) is “send to stdout” vs “invoke registered viewer”?  Our thoughts are the registered viewer is the right default with an option for stdout, but maybe there are very-common scenarios we’re missing.


However, for a default of “invoke registered viewer“ (going with that as how we behave) there are certainly scenarios where people will want to have the file dumped to standard out as well (redirect to a file, pipe through grep/findstr/whatever, etc.) so we want an option to dump the contents to standard out (aka file descriptor 1, /dev/stdout, etc. – where stuff goes when you “echo foo“).  The thing is, none of the options we’ve thought of seem most intuitively obvious if that’s the goal.  What would you want it to be called?


         /stdout is good on the obvious-behavior front, but it’s a bit of a unix-y term for a windows-centric product.  That doesn’t make it bad, but it’s potentially less discoverable and for developers that don’t have stdin/stdout/stderr knowledge, can be downright confusing.


         /dump is too overloaded in other contexts, mainly debugging scenarios (core dumps) and the like.  Also, it’s not very elegant of a term to put it nicely.


         /out isn’t obvious enough – out to what?  I would see an option with that name as needing a parameter to tell it where it should go.  /output fails on approximately the same reason.


         /console isn’t bad, but it’s another overloaded term.  In the terminal services world, the console session is the one specifically on the machine’s console (IOW, for the typical case, the one with the graphics in the machine’s primary video card’s memory J).  An option like /console may give the false impression that we’re interacting with the console session somehow.  Other teams in Microsoft have attempted to avoid “console” meaning “stdout” as well for basically the same reasons.


         /print was rejected because there’s an existing “Print” verb in Windows already that means (wait for it…) “send to the printer”.  Our internal source control (source depot, as mentioned in other blogs) uses “sd print” for sending the file to stdout (it has no ability to invoke a registered viewer)


         /type was rejected because it’s already used in Hatteras– we have the ability for the user to override what file type a particular file is, which is nice for saying things like “treat this as utf-8 even if you detect it as windows-1252”


         /display sounds too much like “invoke registered viewer” behavior and doesn’t imply “send to stdout”


         /text is rejected since there are binary files that you may want to send to stdout (say, to a perl script that does record-based parsing or something)


         /format was kind of considered – so we have an existing standard option /format that takes possible parameters brief and detailed, and we typically default to detailed.  Hence, you can “h workspaces” just to see you workspaces but “h workspaces /format:detailed” to show the workspaces with additional things like the workspace mappings ($/proj1/ -> c:\proj1, $/proj2/ -> c:\docs\foo, etc.) – the idea was /format:brief would do “stdout” behavior and /format:detailed would do “invoke viewer” behavior (or, heck, maybe even vice versa).  Yeah, discoverability near zero, we know. J


         /mode was a potential “make it obvious” brute-force approach.  /mode:stdout would send to stdout, /mode:viewer would invoke the viewer.  Of course, then the /mode: parameter that sends to stdout gets the same kind of argument – stdout? console? Something else?  Also, an option of /mode isn’t very discoverable on what its parameters should be.


We had also considered having a /file: option that would dictate where we would save the file to, and then stdout would become some special case of that. I liked “-“ since it’s pervasive in unix commands as “this means stdout/stdin as appropriate” but that doesn’t really help the windows developer and still fails the discoverability test because of that.  Another option was using the Win32 device con so people could /file:con to get stdout behavior, but that’s taking a dependency on that Win32 device is pretty silly, especially since we’re not sure if it’ll be around for Longhorn et al.  Also, a “file option with special case for stdout” is less discoverable than “stdout option than can be easily redirected to a file” – if you just saw there was a /file option, it’s not obvious that the parameter can be a special case that’ll make it switch to stdout.  However, if you have a stdout option, there’s an established habit that you can redirect/pipe/whatever the contents however you want.


That’s where we stand now – we’re very fortunate that there are a lot of excellent Windows developers among the group of people reading http://blogs.msdn.com/ so I’m hoping we can get some comments/feedback on this and make for a very-discoverable option that will make sense across the board.  What would you like an option to send a file’s contents to stdout to be called?


Comments (30)

  1. Kiliman says:

    The fact that you’re asking at all is really cool. But I’d have to go with /stdout. It’s amazing how many developers I’ve met that don’t know their way around a command line.

    I’d bet that anyone that would use the command line version would know (or at least be willing to learn) what stdout was.

    Those that aren’t would probably stick with the GUI anyway.

    Kiliman

  2. "It’s amazing how many developers I’ve met that don’t know their way around a command line."

    That’s exactly one of the reasons why /stdout is such a painful choice. If a developer is using the command-line for one of the first times, we don’t want to force a learning curve on them – we’re hoping to make things easier on them, not harder. I’ve come across multiple Windows users that know about redirecting output to a file but had never heard of stdout at all.

    For those that know about stdout, /stdout is definitely the most obvious option, but I’m afraid it’s setting the bar higher than necessary, and hence hoping we can find something that is just as discoverable, but doesn’t rely on the user having pre-existing knowledge of stdout 🙂

    Thanks for the comment, though! One vote in, many to go 🙂

  3. ToddM says:

    In the spirit of discoverability, I think I’d make stdout be the default, with /viewer or something similar to use the registered viewer.

    I believe it could go like this:

    h view foo.cs

    [Printing foo.cs to console. Use /viewer to view foo.cs with the registered file view for .cs files. Use /help:none to suppress this message. Use /paging:no to turn off paging.]

    namespace fooNS

    {

    public class foo {}

    }

    The output is preceeded by some help text, which aids in the discovery of the /viewer option. It also explains how to turn off the help message, so that it never displays. Having /paging:yes (think: ‘dir /p’) be a default is also important, to ensure that the help text doesn’t scroll away and is therefore missed.

    Although I don’t like help messages such as this one being the default, or even paging being the default, you seem very concerned about discovery. Naturally, I’d want to see the equivalent of dir’s DIRCMD environment variable for h.exe, so, as a power user, I can make /help:none and /paging:no be the defaults.

  4. Max Battcher says:

    With my command line tools I’ve gotten into the habit of using "start" to pop up the registered viewer. What about something like "h view" (stdout) and "h start" (registered viewer)?

  5. Suggestions:

    /show

    I intended to see if I could come up with more, but a few rounds with the thesaurus didn’t /reveal anything else.

  6. Rich says:

    I have to agree with the other fellow–a default for a CLI invocation should send output to stdout. The registered viewer should be the one with the switch. IMO.

    If this were less of a development tool, I’d expect something different. And, if this was context menu initiated behavior, obviously the viewer should be launched.

  7. Brant – it’s hard to understand the "broke the stdout/stdin/stderr convention" comment. You’ll notice System.Console has exactly what you’d expect on that front – the properties are called In, Out, and Error with corresponding SetXxx methods and OpenStandardXxx methods. How much more explicit could that be in following stdin/stdout/stderr? 🙂

    http://longhorn.msdn.microsoft.com/lhsdk/ref/ns/system/c/console/console.aspx

  8. Max: I think "start" would be nice except that we really want to invoke a viewer for this command, not an invoker – IOW what should "h start $/bar/foo.pl" do? To me, that should run the perl script, which isn’t what we want to do – we want to view it 🙂

    Rich: I can agree about a command-line convention existing – the stronger question is which one is actually going to be called more often? If 90% of the time (as a random number) people are going to want the file sent to the registered viewer (which is pretty common, I want my source files in my favorite (and registered) IDE, not stdout nor a file on disk I have to open manually) then we should default to that behavior and have the option be the more rare case of stdout. We’re having a hard time believing that (despite whatever convention exists) people would actually want to deal with the file as a stream of bytes instead of using the appropriate editor. Imagine "h view $/docs/spec.pdf" – does stdout make sense as a default for that command? It doesn’t feel that way, but that’s a particular example of course.

  9. ToddM: I think people understand "more" well enough that forcing them to add "| more" if they want a pager shouldn’t be a big deal. Also, printing help out makes it more painful if they want to direct to something else. Like if I want all the lines from a server file with "console" in them, I’d like to just "h view $/bar/foo.cs;C10 | findstr console" but with the help going out to the user like that, we’ll get a bad hit – effectively, we’re corrupting the file with the help message, at least for later programs that would like to operate on the file. It’s worth considering, though, but it has some drawbacks.

    Thanks for the feedback!

  10. Anderson: Thanks! I’d be worried that "show" is just repetitive with "view" – IOW, there’s nothing about "show" that implies "put this on stdout instead of displaying in a graphical way". Good idea, though – it’s in the running 🙂

  11. ToddM: in terms of my examples to your suggestion, I wanted to point out that I understand we could /help:none and /paging:no – it’s more about trying to figure out what people want to do most often and making that as easy as possible. Great ideas, though.

    I tend to just run things with no params to get help or a param of /? (so "h view" or "h view /?") myself, and the paging on/off is adding "|more" or not, but again it’s more about trying to make the common case easiest, and it’s hard to get a feel for exactly what’s most common for everyone out there 🙂

  12. Raymond Chen says:

    I say just pick some arbitrary switch like /E (which the C compiler uses). That way it has no semantic meaning and therefore cannot be misunderstood.

    Alternatively don’t overload the "view" command with this. View is for viewing with a viewer. That’s why it’s called view. If you want to print to stdout, call it something else entirely, like "h cat …".

  13. Mike Dimmick says:

    Well, since we’re dealing with DOS-style commands here, not UNIX ones, it should really be "h type" but that repeats the problem – it helps the users with a degree of familiarity with one system, but confuses the heck out of people with no familiarity. "h list" has similar problems: produce a list of files?

    How about /here? Works well for the console, but less well for piping and redirecting to a file (but would you want to redirect anyway? It’s a little pointless when you could just "h get").

    Anyway, some of the C++ compiler options are arbitrary, but others are a little mnemonic, e.g. /c to compile only, /O for optimisation options. Microsoft have generally been moving away from single-letter options, e.g. /showIncludes on CL.EXE 13.x and later, and the mnemonic /RTC for Run-Time Checks.

  14. drebin says:

    don’t be afraid to be wordy..

    /streamtothisconsole

    /streamtofile:[filename]

    etc

    it’s clear and to the point

  15. Ian Mariano says:

    I think "sendto:" is good.

    sendto:printer, sendto:"ftp://user:pass@domain.com/dir/result.text", sendto:nothing, sendto:"user@domain.com,subject=build results,attach=result.txt", sendto:"\sharedirresult.txt", et al.

    Of course, the CLI (Command Line Interpreter) for your favorite shell would have to be able to parse the various destination devices / UNCs…

  16. ToddM says:

    James, I appreciated your responses to my comments. To be clear, I did NOT like MY OWN IDEAS, but I was trying to solve YOUR problem of ‘discovery’. You seem to contridict yourself in this thread — either you want the discovery to be easy (apparently, the default), or you do not. I agree that "h.exe /?" should supply help, but I do not think you can argue that people will know to use the /? option but not understand the meaning of stdout. I find /? to be just as Unix-like as stdout.

    Also, I agree that when piped, having help output appear by default is bad. Of course, it is very easy to detect if its output has been redirected, so, in those cases, you wouldn’t do the help by default.

    In the end, I wonder just how important you notion of discovery is. I think anyone who uses a command-line is well versed in /?, and that should be all they need to know.

    I do think it is awesome that you guys are putting this level of thought into, though, as command-line support from Microsoft tools has historically been a pain point for me and countless others. I welcome the efforts.

  17. Carlos says:

    Your application can tell whether the user has redirected stdout, so anything like:

    h view x.y > f.y

    h view x.y | more

    should not launch a viewer and should redirect the output as expected.

    In the default case where output is not redirected:

    h view x.y

    launch the viewer, but also write a help message to stderr explaining that /stdout (or whatever) is required to output to the console.

    This is what I’d do anyway 🙂

  18. Dan says:

    Why not "h view x.y" or "h start x.y" and "h type x.y" or "h cat x.y"?

    Then again, why not just integrate h into the filesystem, extend the naming convention and then "start x.y" and "type x.y" would just work and make versioning available to the user in any application.

  19. Peter Coleman says:

    It’s two separate verbs:

    1. "show a version of a file in the user’s registered viewer";

    2. "get a version of a file and hand off to command shell to do the right thing according to the user’s overall command line".

    The structure of the command line seems to be "h.exe {verb} {switches} {objects…}"

    So for 1, the verb ‘view’ fits well:

    h.exe view {versioned_file}

    For 2, go with a verb like ‘get’, and give the ‘get’ verb "obvious" syntax to direct either to a new file in the filesystem or to stdout. Assuming you’re not already using ‘get’ for something else (sorry, I haven’t seen the rest of your command syntax) just go with:

    h.exe get {versioned_file}

    for sending it to stdout, and:

    h.exe get {versioned_file} {filesystem_file_to_create}

  20. Steve Dunn says:

    It would be also nice to be able to send to a custom .NET type that implements some predefined interface, like sendto:"MyNamespace.MyClass, MyAssembly" where MyClass implements the interface "ITeamSystemFileViewer" or something similar.

    Cheers,

    Steve

    steve at dunnhq.com

  21. Steve Dunn says:

    I think Dan’s comments are great. Is there anything shared between Team System and WinFS?

  22. Chris says:

    I posted a partial followup to this on Korby’s blog, but let me follow up again here as well.

    We have two goals – hopefully they’re not mutually exclusive.

    1) It’s a console command. Keeping console commands scriptable is (and should be) a goal.

    2) Not all TFS users are Unix gee^H^Hurus, as the first half of this sentence is designed to demonstrate. I imagine the set of users who would want to use the command line interface, and yet are unfamiliar with common CLI semantics, is fairly small. But, we still strive for discoverability (weighing feasibility against need, etc.).

    Hence this thread. The names of the various arguments shouldn’t affect scripting, even ignoring the fact that we intend to have one-letter (somewhat arbitrary) aliases for each such argument (recursive is /r, noprompt is /i, /repository is /s, etc.). But, their names DO affect discoverability – so when you type h help view, the names of the major arguments should imply their function, if at all possible.

    It’s easy to forget that not every VSTS user will know what terms like "Standard Error" and "output redirection" mean – even assuming they know the particular shadings of the word "console" may be a stretch. It’s reasonable to assume that most such users will stick to the graphical interfaces, but we shouldn’t be content with CLIs being any more … daunting … than absolutely necessary.

    Carlos: Yes, you can detection redirection – but as James will tell you, I’m not sure that approach is A Good Idea. Typically, you wouldn’t expect a console app to care where stdin is coming from, or where stdout/stderr are going, and as soon as that’s no longer true, I think we’re risking weird/unexpected behavior in the future. Maybe I’m just paranoid that way, though.

    Peter: Get is the verb to sync your workspace with the repository, so using it to print to a file and/or stdout won’t work. There are merits to putting the view command as one verb and the stdout/file output as a second verb, though.

    Steve (et al): Hooking into the shell and/or Explorer and/or Monad would be nice. It can’t be the only solution, of course, but it’d be nice to support.

    I’m not sure you need the custom interface though – we’re driving it through the standard extension-based filetype, using whatever is registered as the default action for "View". You can just register your assembly as the default viewer for .foo files, and then h view on abc.foo will hit your assembly.

  23. Ian says:

    To be honest I think you’re tying yourself in knots here.

    If you’re expecting people to use a command line version of a tool, then you have to assume they know how to use the command line. That should imply knowledge of command line tools, which typically use /? or /help to give help.

    It’s also expected that most command line tools output, by default to stdout (be that right there at the command line, or somewhere you might have redirected stdout to). If you don’t know what stdout is, what have you been developing in? At least on the windows platform I’m trying to think of a development tool that doesn’t have some sense of stdout/stderr and the like.

    I think you’re trying to pander to people who don’t know sqat about the command line, and yet expecting them to be using a command line tool.

    I’d suggest making stdout the default, which allows all the pipe/redirect folks to do their thang, and use a command line switch like /launch or /viewer to indicate you want the registered viwer to be used.

    The icon in the start menu for the tool should, of course, launch the registered viewe.

  24. MADuran says:

    Command Line junkee’s like my self expect STDOUT to be the default of a command line. If any thing should be added is a switch that does a UNIX style TEE ( Output goes both to stdout and to a file that is defined after the switch ).

    I agree with the fact that a command line user should be expected to use the /? or /help switch in a product.

    My greatist hope is that this product will have well docuement API for plugins, reporting and automation.

  25. MADuran: Visual Studio has their own plugins, of course, but our source control component only really plugs in 3rd party diff and merge tools. However, we are making an object model API so that people can do source control interaction programmatically instead of having to script with our command-line. We’re trying to think of a lot of usage scenarios to make sure our API is friendly and easy to work with, but if you have specific scenarios you’d like to let us know about, please do – more input will help us make a better API 🙂