1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
12 #include "cmsys/Encoding.hxx"
14 #include "cmCursesColor.h"
15 #include "cmCursesForm.h"
16 #include "cmCursesMainForm.h"
17 #include "cmCursesStandardIncludes.h"
18 #include "cmDocumentation.h"
19 #include "cmDocumentationEntry.h"
20 #include "cmMessageMetadata.h"
22 #include "cmStringAlgorithms.h"
23 #include "cmSystemTools.h"
27 const cmDocumentationEntry cmDocumentationName
= {
29 " ccmake - Curses Interface for CMake."
32 const cmDocumentationEntry cmDocumentationUsage
[2] = {
34 " ccmake <path-to-source>\n"
35 " ccmake <path-to-existing-build>" },
37 "Specify a source directory to (re-)generate a build system for "
38 "it in the current working directory. Specify an existing build "
39 "directory to re-generate its build system." },
42 const cmDocumentationEntry cmDocumentationUsageNote
= {
44 "Run 'ccmake --help' for more information."
50 void onsig(int /*unused*/)
52 if (cmCursesForm::CurrentForm
) {
53 cmCursesForm::CurrentForm
->HandleResize();
55 signal(SIGWINCH
, onsig
);
59 } // anonymous namespace
61 cmCursesForm
* cmCursesForm::CurrentForm
= nullptr;
63 int main(int argc
, char const* const* argv
)
65 cmSystemTools::EnsureStdPipes();
66 cmsys::Encoding::CommandLineArguments encoding_args
=
67 cmsys::Encoding::CommandLineArguments::Main(argc
, argv
);
68 argc
= encoding_args
.argc();
69 argv
= encoding_args
.argv();
71 cmSystemTools::InitializeLibUV();
72 cmSystemTools::FindCMakeResources(argv
[0]);
74 doc
.addCMakeStandardDocSections();
75 if (doc
.CheckOptions(argc
, argv
)) {
76 cmake
hcm(cmake::RoleInternal
, cmState::Help
);
77 hcm
.SetHomeDirectory("");
78 hcm
.SetHomeOutputDirectory("");
80 auto generators
= hcm
.GetGeneratorsDocumentation();
81 doc
.SetName("ccmake");
82 doc
.SetSection("Name", cmDocumentationName
);
83 doc
.SetSection("Usage", cmDocumentationUsage
);
85 doc
.AppendSection("Usage", cmDocumentationUsageNote
);
87 doc
.AppendSection("Generators", generators
);
88 doc
.PrependSection("Options", cmake::CMAKE_STANDARD_OPTIONS_TABLE
);
89 return !doc
.PrintRequestedDocumentation(std::cout
);
95 std::vector
<std::string
> args
;
96 for (j
= 0; j
< argc
; ++j
) {
97 if (strcmp(argv
[j
], "-debug") == 0) {
100 args
.emplace_back(argv
[j
]);
104 std::string cacheDir
= cmSystemTools::GetCurrentWorkingDirectory();
105 for (i
= 1; i
< args
.size(); ++i
) {
106 std::string
const& arg
= args
[i
];
107 if (cmHasPrefix(arg
, "-B")) {
108 cacheDir
= arg
.substr(2);
112 cmSystemTools::DisableRunCommandOutput();
115 cmCursesForm::DebugStart();
118 if (initscr() == nullptr) {
119 fprintf(stderr
, "Error: ncurses initialization failed\n");
122 noecho(); /* Echo off */
123 cbreak(); /* nl- or cr not needed */
124 keypad(stdscr
, true); /* Use key symbols as KEY_DOWN */
125 cmCursesColor::InitColors();
128 signal(SIGWINCH
, onsig
);
133 getmaxyx(stdscr
, y
, x
);
134 if (x
< cmCursesMainForm::MIN_WIDTH
|| y
< cmCursesMainForm::MIN_HEIGHT
) {
136 std::cerr
<< "Window is too small. A size of at least "
137 << cmCursesMainForm::MIN_WIDTH
<< " x "
138 << cmCursesMainForm::MIN_HEIGHT
<< " is required to run ccmake."
143 cmCursesMainForm
* myform
;
145 myform
= new cmCursesMainForm(args
, x
);
146 if (myform
->LoadCache(cacheDir
.c_str())) {
151 std::cerr
<< "Error running cmake::LoadCache(). Aborting.\n";
156 * The message is stored in a list by the form which will be
157 * joined by '\n' before display.
158 * Removing any trailing '\n' avoid extra empty lines in the final results
160 auto cleanMessage
= [](const std::string
& message
) -> std::string
{
162 if (!msg
.empty() && msg
.back() == '\n') {
167 cmSystemTools::SetMessageCallback(
168 [&](const std::string
& message
, const cmMessageMetadata
& md
) {
169 myform
->AddError(cleanMessage(message
), md
.title
);
171 cmSystemTools::SetStderrCallback([&](const std::string
& message
) {
172 myform
->AddError(cleanMessage(message
), "");
174 cmSystemTools::SetStdoutCallback([&](const std::string
& message
) {
175 myform
->UpdateProgress(cleanMessage(message
), -1);
178 cmCursesForm::CurrentForm
= myform
;
180 myform
->InitializeUI();
181 if (myform
->Configure(1) == 0) {
182 myform
->Render(1, 1, x
, y
);
183 myform
->HandleInput();
186 // Need to clean-up better
190 delete cmCursesForm::CurrentForm
;
191 cmCursesForm::CurrentForm
= nullptr;
193 std::cout
<< std::endl
<< std::endl
;