Repository: pallets/click

Problem statement:
Option for click.prompt to write to standard error
click.echo can write to standard error nicely, however I have a usecase where I want to redirect output to a file with shell builtin `>>`, but don't want to write the conversation between the user and the script.
Example:

```
$ command getinfo Walkma  >> outputfile.txt                                                                                                                
Got multiple users with similar names!
1. walkman
2. Walkman Invader
3. WalkmanX
4. Walkman_
Which would you like to see [1-4] (CTRL-C to abort): 4

$ cat outputfile.txt
Got multiple users with similar names!
1. walkman
2. Walkman Invader
3. WalkmanX
4. Walkman_
Which would you like to see [1-4] (CTRL-C to abort):

Info about the user:
Username: Walkman_
profile_picture: ...

$
```

Now, the conversation part got into `outputfile.txt`, which I don't want. I can write out the list to standard error with `click.echo('Got multiple users...', err=True)`, but `click.prompt` cannot do that.

Do you think it makes sense, or are there other more POSIX compliant ways to handle this case?
I can implement this and send a pull request if you find it useful.



Hints:
I played with it a bit more and tried:

``` python
click.echo('Message', err=True)
click.prompt('', prompt_suffix='')
```

In this case, the message don't get written to the redirected file, but the question will not be repeated (just an empty prompt).

Echoing the message to stdout is not good at all, because it will not appear, because it will be redirected to the file also:

``` python
click.echo('Message')
# nothing will appear, the user doesn't know what to do
click.prompt('', prompt_suffix='')
```


Patch:
diff --git a/click/termui.py b/click/termui.py
--- a/click/termui.py
+++ b/click/termui.py
@@ -33,7 +33,8 @@ def _build_prompt(text, suffix, show_default=False, default=None):
 
 def prompt(text, default=None, hide_input=False,
            confirmation_prompt=False, type=None,
-           value_proc=None, prompt_suffix=': ', show_default=True):
+           value_proc=None, prompt_suffix=': ',
+           show_default=True, err=False):
     """Prompts a user for input.  This is a convenience function that can
     be used to prompt a user for input later.
 
@@ -52,6 +53,8 @@ def prompt(text, default=None, hide_input=False,
                        convert a value.
     :param prompt_suffix: a suffix that should be added to the prompt.
     :param show_default: shows or hides the default value in the prompt.
+    :param err: if set to true the file defaults to ``stderr`` instead of
+                ``stdout``, the same as with echo.
     """
     result = None
 
@@ -60,7 +63,7 @@ def prompt_func(text):
         try:
             # Write the prompt separately so that we get nice
             # coloring through colorama on Windows
-            echo(text, nl=False)
+            echo(text, nl=False, err=err)
             return f('')
         except (KeyboardInterrupt, EOFError):
             raise Abort()
@@ -83,7 +86,7 @@ def prompt_func(text):
         try:
             result = value_proc(value)
         except UsageError as e:
-            echo('Error: %s' % e.message)
+            echo('Error: %s' % e.message, err=err)
             continue
         if not confirmation_prompt:
             return result
@@ -93,11 +96,11 @@ def prompt_func(text):
                 break
         if value == value2:
             return result
-        echo('Error: the two entered values do not match')
+        echo('Error: the two entered values do not match', err=err)
 
 
 def confirm(text, default=False, abort=False, prompt_suffix=': ',
-            show_default=True):
+            show_default=True, err=False):
     """Prompts for confirmation (yes/no question).
 
     If the user aborts the input by sending a interrupt signal this
@@ -109,6 +112,8 @@ def confirm(text, default=False, abort=False, prompt_suffix=': ',
                   exception by raising :exc:`Abort`.
     :param prompt_suffix: a suffix that should be added to the prompt.
     :param show_default: shows or hides the default value in the prompt.
+    :param err: if set to true the file defaults to ``stderr`` instead of
+                ``stdout``, the same as with echo.
     """
     prompt = _build_prompt(text, prompt_suffix, show_default,
                            default and 'Y/n' or 'y/N')
@@ -116,7 +121,7 @@ def confirm(text, default=False, abort=False, prompt_suffix=': ',
         try:
             # Write the prompt separately so that we get nice
             # coloring through colorama on Windows
-            echo(prompt, nl=False)
+            echo(prompt, nl=False, err=err)
             value = visible_prompt_func('').lower().strip()
         except (KeyboardInterrupt, EOFError):
             raise Abort()
@@ -127,7 +132,7 @@ def confirm(text, default=False, abort=False, prompt_suffix=': ',
         elif value == '':
             rv = default
         else:
-            echo('Error: invalid input')
+            echo('Error: invalid input', err=err)
             continue
         break
     if abort and not rv:
@@ -478,7 +483,7 @@ def getchar(echo=False):
     return f(echo)
 
 
-def pause(info='Press any key to continue ...'):
+def pause(info='Press any key to continue ...', err=False):
     """This command stops execution and waits for the user to press any
     key to continue.  This is similar to the Windows batch "pause"
     command.  If the program is not run through a terminal, this command
@@ -492,11 +497,11 @@ def pause(info='Press any key to continue ...'):
         return
     try:
         if info:
-            echo(info, nl=False)
+            echo(info, nl=False, err=err)
         try:
             getchar()
         except (KeyboardInterrupt, EOFError):
             pass
     finally:
         if info:
-            echo()
+            echo(err=err)


Test patch:
diff --git a/tests/test_utils.py b/tests/test_utils.py
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -151,6 +151,64 @@ def test_echo_color_flag(monkeypatch, capfd):
     assert out == text + '\n'
 
 
+def test_echo_writing_to_standard_error(capfd, monkeypatch):
+    def emulate_input(text):
+        """Emulate keyboard input."""
+        if sys.version_info[0] == 2:
+            from StringIO import StringIO
+        else:
+            from io import StringIO
+        monkeypatch.setattr(sys, 'stdin', StringIO(text))
+
+    click.echo('Echo to standard output')
+    out, err = capfd.readouterr()
+    assert out == 'Echo to standard output\n'
+    assert err == ''
+
+    click.echo('Echo to standard error', err=True)
+    out, err = capfd.readouterr()
+    assert out == ''
+    assert err == 'Echo to standard error\n'
+
+    emulate_input('asdlkj\n')
+    click.prompt('Prompt to stdin')
+    out, err = capfd.readouterr()
+    assert out == 'Prompt to stdin: '
+    assert err == ''
+
+    emulate_input('asdlkj\n')
+    click.prompt('Prompt to stderr', err=True)
+    out, err = capfd.readouterr()
+    assert out == ''
+    assert err == 'Prompt to stderr: '
+
+    emulate_input('y\n')
+    click.confirm('Prompt to stdin')
+    out, err = capfd.readouterr()
+    assert out == 'Prompt to stdin [y/N]: '
+    assert err == ''
+
+    emulate_input('y\n')
+    click.confirm('Prompt to stderr', err=True)
+    out, err = capfd.readouterr()
+    assert out == ''
+    assert err == 'Prompt to stderr [y/N]: '
+
+    monkeypatch.setattr(click._compat, 'isatty', lambda x: True)
+
+    emulate_input(' ')
+    click.pause('Pause to stdin')
+    out, err = capfd.readouterr()
+    assert out == 'Pause to stdin'
+    assert err == ''
+
+    emulate_input(' ')
+    click.pause('Pause to stderr', err=True)
+    out, err = capfd.readouterr()
+    assert out == ''
+    assert err == 'Pause to stderr'
+
+
 def test_open_file(runner):
     with runner.isolated_filesystem():
         with open('hello.txt', 'w') as f: