diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2018-07-07 12:34:08 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2018-07-07 12:34:08 +0200 |
commit | 726f4573a5d183a685e0a1032a3e247e3b47482e (patch) | |
tree | a92ee55bdea255789df662c77063ee89ccca6eff | |
parent | fb9b318a77ad9364aa2303679c0b84d2d1bdb055 (diff) |
Move prompt facility from bpkg to libbutl
-rw-r--r-- | libbutl/prompt.cxx | 74 | ||||
-rw-r--r-- | libbutl/prompt.mxx | 36 |
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'); +} |