Browse Source

cmake -E cat: Add ability to print standard input

Kyle Edwards 2 years ago
parent
commit
ab72846794

+ 4 - 0
Help/manual/cmake.1.rst

@@ -891,6 +891,10 @@ Available commands are:
     ``-`` will result in an error. Use ``--`` to indicate the end of options, in
     case a file starts with ``-``.
 
+  .. versionadded:: 3.29
+
+    ``cat`` can now print the standard input by passing the ``-`` argument.
+
 .. program:: cmake-E
 
 .. option:: chdir <dir> <cmd> [<arg>...]

+ 5 - 0
Help/release/dev/cmake-E-cat-stdin.rst

@@ -0,0 +1,5 @@
+cmake-E-cat-stdin
+-----------------
+
+* :manual:`cmake(1)` :option:`-E cat <cmake-E cat>` can now print the standard
+  input by passing the ``-`` argument.

+ 14 - 4
Source/cmcmd.cxx

@@ -203,11 +203,16 @@ bool cmTarFilesFrom(std::string const& file, std::vector<std::string>& files)
 void cmCatFile(const std::string& fileToAppend)
 {
 #ifdef _WIN32
+  _setmode(fileno(stdin), _O_BINARY);
   _setmode(fileno(stdout), _O_BINARY);
 #endif
-  cmsys::ifstream source(fileToAppend.c_str(),
-                         (std::ios::binary | std::ios::in));
-  std::cout << source.rdbuf();
+  std::streambuf* buf = std::cin.rdbuf();
+  cmsys::ifstream source;
+  if (fileToAppend != "-") {
+    source.open(fileToAppend.c_str(), (std::ios::binary | std::ios::in));
+    buf = source.rdbuf();
+  }
+  std::cout << buf;
 }
 
 bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
@@ -1147,7 +1152,12 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
       int return_value = 0;
       bool doing_options = true;
       for (auto const& arg : cmMakeRange(args).advance(2)) {
-        if (doing_options && cmHasLiteralPrefix(arg, "-")) {
+        if (arg == "-") {
+          doing_options = false;
+          // Destroy console buffers to drop cout/cerr encoding transform.
+          consoleBuf.reset();
+          cmCatFile(arg);
+        } else if (doing_options && cmHasLiteralPrefix(arg, "-")) {
           if (arg == "--") {
             doing_options = false;
           } else {

+ 1 - 0
Tests/RunCMake/CommandLine/E_cat-stdin-stdout.txt

@@ -0,0 +1 @@
+^Hello world$

+ 10 - 0
Tests/RunCMake/CommandLine/E_cat-stdin.cmake

@@ -0,0 +1,10 @@
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ell.txt" "ell")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/rld.txt" "rld")
+execute_process(
+  COMMAND ${CMAKE_COMMAND} -E echo_append "H"
+  COMMAND ${CMAKE_COMMAND} -E cat -
+  )
+execute_process(
+  COMMAND ${CMAKE_COMMAND} -E echo_append "o wo"
+  COMMAND ${CMAKE_COMMAND} -E cat "${CMAKE_CURRENT_BINARY_DIR}/ell.txt" - "${CMAKE_CURRENT_BINARY_DIR}/rld.txt"
+  )

+ 2 - 0
Tests/RunCMake/CommandLine/RunCMakeTest.cmake

@@ -782,6 +782,8 @@ run_cmake_command(E_cat-without-double-dash ${CMAKE_COMMAND} -E cat "-file-start
 unset(RunCMake_TEST_COMMAND_WORKING_DIRECTORY)
 unset(out)
 
+run_cmake_command(E_cat-stdin ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_cat-stdin.cmake)
+
 # Unset environment variables that are used for testing cmake -E
 unset(ENV{TEST_ENV})
 unset(ENV{TEST_ENV_EXPECTED})