aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-07-07 12:34:08 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-07-07 12:34:08 +0200
commit726f4573a5d183a685e0a1032a3e247e3b47482e (patch)
treea92ee55bdea255789df662c77063ee89ccca6eff
parentfb9b318a77ad9364aa2303679c0b84d2d1bdb055 (diff)
Move prompt facility from bpkg to libbutl
-rw-r--r--libbutl/prompt.cxx74
-rw-r--r--libbutl/prompt.mxx36
2 files changed, 110 insertions, 0 deletions
diff --git a/libbutl/prompt.cxx b/libbutl/prompt.cxx
new file mode 100644
index 0000000..52442b2
--- /dev/null
+++ b/libbutl/prompt.cxx
@@ -0,0 +1,74 @@
+// file : libbutl/prompt.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef __cpp_modules
+#include <libbutl/prompt.mxx>
+#endif
+
+#ifndef __cpp_lib_modules
+#include <string>
+
+#include <iostream>
+#endif
+
+// Other includes.
+
+#ifdef __cpp_modules
+module butl.prompt;
+
+// Only imports additional to interface.
+#ifdef __clang__
+#ifdef __cpp_lib_modules
+import std.core;
+import std.io;
+#endif
+#endif
+
+import butl.diagnostics;
+#else
+#include <libbutl/diagnostics.mxx> // diag_stream
+#endif
+
+using namespace std;
+
+namespace butl
+{
+ bool
+ yn_prompt (const string& prompt, char def)
+ {
+ // Writing a robust Y/N prompt is more difficult than one would expect.
+ //
+ string a;
+ do
+ {
+ *diag_stream << prompt << ' ';
+
+ // getline() will set the failbit if it failed to extract anything,
+ // not even the delimiter and eofbit if it reached eof before seeing
+ // the delimiter.
+ //
+ getline (cin, a);
+
+ bool f (cin.fail ());
+ bool e (cin.eof ());
+
+ if (f || e)
+ *diag_stream << endl; // Assume no delimiter (newline).
+
+ if (f)
+ throw ios_base::failure ("unable to read y/n answer from stdout");
+
+ if (a.empty () && def != '\0')
+ {
+ // Don't treat eof as the default answer. We need to see the actual
+ // newline.
+ //
+ if (!e)
+ a = def;
+ }
+ } while (a != "y" && a != "n");
+
+ return a == "y";
+ }
+}
diff --git a/libbutl/prompt.mxx b/libbutl/prompt.mxx
new file mode 100644
index 0000000..5d431a6
--- /dev/null
+++ b/libbutl/prompt.mxx
@@ -0,0 +1,36 @@
+// file : libbutl/prompt.mxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef __cpp_modules
+#pragma once
+#endif
+
+// C includes.
+
+#ifndef __cpp_lib_modules
+#include <string>
+#endif
+
+// Other includes.
+
+#ifdef __cpp_modules
+export module butl.prompt;
+#ifdef __cpp_lib_modules
+import std.core;
+#endif
+#endif
+
+#include <libbutl/export.hxx>
+
+LIBBUTL_MODEXPORT namespace butl
+{
+ // The Y/N prompt. The def argument, if specified, should be either 'y' or
+ // 'n'. It is used as the default answer, in case the user just hits enter.
+ //
+ // Write the prompt to diag_stream. Throw ios_base::failure if no answer
+ // could be extracted from stdin (for example, because it was closed).
+ //
+ LIBBUTL_SYMEXPORT bool
+ yn_prompt (const std::string&, char def = '\0');
+}