Skip to content

Commit 384b855

Browse files
committed
Improve Heavy console with ANSI colour, font weight and command logging
1 parent 6f38358 commit 384b855

17 files changed

Lines changed: 903 additions & 415 deletions

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ file(GLOB plugdata_resources
176176
${CMAKE_CURRENT_SOURCE_DIR}/Resources/Fonts/InterVariable.ttf
177177
${CMAKE_CURRENT_SOURCE_DIR}/Resources/Fonts/InterRegular.ttf
178178
${CMAKE_CURRENT_SOURCE_DIR}/Resources/Fonts/RobotoMono-Regular.ttf
179+
${CMAKE_CURRENT_SOURCE_DIR}/Resources/Fonts/RobotoMono-Bold.ttf
179180
${CMAKE_CURRENT_SOURCE_DIR}/Resources/Icons/plugdata_large_logo.png
180181
${CMAKE_CURRENT_SOURCE_DIR}/Resources/Icons/plugdata_logo.png
181182
# Generated resources
85.6 KB
Binary file not shown.

Resources/Scripts/package_resources.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ def generate_binary_data(output_dir, file_list):
342342
project_root + "/Resources/Fonts/InterVariable.ttf",
343343
project_root + "/Resources/Fonts/InterRegular.ttf",
344344
project_root + "/Resources/Fonts/RobotoMono-Regular.ttf",
345+
project_root + "/Resources/Fonts/RobotoMono-Bold.ttf",
345346
project_root + "/Resources/Icons/plugdata_large_logo.png",
346347
project_root + "/Resources/Icons/plugdata_logo.png",
347348
"Documentation.bin",

Source/Constants.h

Lines changed: 243 additions & 243 deletions
Large diffs are not rendered by default.

Source/Heavy/CppExporter.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ class CppExporter final : public ExporterBase {
5555
return true;
5656

5757
auto const command = args.joinIntoString(" ");
58-
exportingView->logToConsole("Command: " + command + "\n");
59-
Toolchain::startShellScript(command, this);
58+
startShellScript(command);
6059

6160
waitForProcessToFinish(-1);
6261
exportingView->flushConsole();

Source/Heavy/DPFExporter.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,7 @@ class DPFExporter final : public ExporterBase {
220220
return true;
221221

222222
auto const command = args.joinIntoString(" ");
223-
exportingView->logToConsole("Command: " + command + "\n");
224-
Toolchain::startShellScript(command, this);
223+
startShellScript(command);
225224

226225
waitForProcessToFinish(-1);
227226
exportingView->flushConsole();
@@ -234,11 +233,11 @@ class DPFExporter final : public ExporterBase {
234233
outputFile.getChildFile("hv").deleteRecursively();
235234
outputFile.getChildFile("c").deleteRecursively();
236235

237-
auto const DPF = Toolchain::dir.getChildFile("lib").getChildFile("dpf");
236+
auto const DPF = toolchainDir.getChildFile("lib").getChildFile("dpf");
238237
DPF.copyDirectoryTo(outputFile.getChildFile("dpf"));
239238

240239
if (exportType == 2 || exportType == 4) {
241-
auto const DPFGui = Toolchain::dir.getChildFile("lib").getChildFile("dpf-widgets");
240+
auto const DPFGui = toolchainDir.getChildFile("lib").getChildFile("dpf-widgets");
242241
DPFGui.copyDirectoryTo(outputFile.getChildFile("dpf-widgets"));
243242
}
244243

@@ -256,29 +255,29 @@ class DPFExporter final : public ExporterBase {
256255

257256
outputFile.setAsCurrentWorkingDirectory();
258257

259-
auto const bin = Toolchain::dir.getChildFile("bin");
258+
auto const bin = toolchainDir.getChildFile("bin");
260259
auto make = bin.getChildFile("make" + exeSuffix);
261260
auto makefile = outputFile.getChildFile("Makefile");
262-
261+
263262
#if JUCE_MAC
264-
Toolchain::startShellScript("make -j4 -f " + makefile.getFullPathName(), this);
263+
startShellScript("make -j4 -f " + makefile.getFullPathName());
265264
#elif JUCE_WINDOWS
266-
auto path = "export PATH=\"$PATH:" + pathToString(Toolchain::dir.getChildFile("bin")) + "\"\n";
267-
auto cc = "CC=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("gcc.exe")) + " ";
268-
auto cxx = "CXX=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("g++.exe")) + " ";
269-
auto shell = " SHELL=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("bash.exe")).quoted();
270-
Toolchain::startShellScript(path + cc + cxx + pathToString(make) + " -j4 -f " + pathToString(makefile) + shell, this);
265+
auto path = "export PATH=\"$PATH:" + pathToString(toolchainDir.getChildFile("bin")) + "\"\n";
266+
auto cc = "CC=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("gcc.exe")) + " ";
267+
auto cxx = "CXX=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("g++.exe")) + " ";
268+
auto shell = " SHELL=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("bash.exe")).quoted();
269+
startShellScript(path + cc + cxx + pathToString(make) + " -j4 -f " + pathToString(makefile) + shell);
271270
#else // Linux or BSD
272-
auto prepareEnvironmentScript = pathToString(Toolchain::dir.getChildFile("scripts").getChildFile("anywhere-setup.sh")) + "\n";
271+
auto prepareEnvironmentScript = pathToString(toolchainDir.getChildFile("scripts").getChildFile("anywhere-setup.sh")) + "\n";
273272
auto buildScript = prepareEnvironmentScript
274273
+ pathToString(make)
275274
+ " -j4 -f " + pathToString(makefile);
276275

277276
// For some reason we need to do this again
278277
outputFile.getChildFile("dpf").getChildFile("utils").getChildFile("generate-ttl.sh").setExecutePermission(true);
279-
Toolchain::dir.getChildFile("scripts").getChildFile("anywhere-setup.sh").getChildFile("generate-ttl.sh").setExecutePermission(true);
278+
toolchainDir.getChildFile("scripts").getChildFile("anywhere-setup.sh").getChildFile("generate-ttl.sh").setExecutePermission(true);
280279

281-
Toolchain::startShellScript(buildScript, this);
280+
startShellScript(buildScript);
282281
#endif
283282

284283
waitForProcessToFinish(-1);

Source/Heavy/DaisyExporter.h

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class DaisyExporter final : public ExporterBase {
7373

7474
flashButton.onClick = [this] {
7575
auto const tempFolder = File::getSpecialLocation(File::tempDirectory).getChildFile("Heavy-" + Uuid().toString().substring(10));
76-
Toolchain::deleteTempFileLater(tempFolder);
76+
deleteTempFileLater(tempFolder);
7777
startExport(tempFolder);
7878
};
7979

@@ -82,10 +82,10 @@ class DaisyExporter final : public ExporterBase {
8282
exportingView->monitorProcessOutput(this);
8383
exportingView->showState(ExportingProgressView::Flashing);
8484

85-
auto const bin = Toolchain::dir.getChildFile("bin");
85+
auto const bin = toolchainDir.getChildFile("bin");
8686
auto const make = bin.getChildFile("make" + exeSuffix);
8787
auto const& gccPath = bin.getFullPathName();
88-
auto const sourceDir = Toolchain::dir.getChildFile("lib").getChildFile("libdaisy").getChildFile("core");
88+
auto const sourceDir = toolchainDir.getChildFile("lib").getChildFile("libdaisy").getChildFile("core");
8989

9090
int const result = flashBootloader(bin, sourceDir, make, gccPath);
9191

@@ -218,7 +218,7 @@ class DaisyExporter final : public ExporterBase {
218218
+ pathToString(make) + " program-boot"
219219
+ " GCC_PATH=" + gccPath;
220220

221-
Toolchain::startShellScript(bootloaderScript, this);
221+
startShellScript(bootloaderScript);
222222

223223
waitForProcessToFinish(-1);
224224
exportingView->flushConsole();
@@ -262,7 +262,7 @@ class DaisyExporter final : public ExporterBase {
262262
if (board == "custom") {
263263
metaDaisy.getDynamicObject()->setProperty("board_file", customBoardDefinition.getFullPathName());
264264
} else if (extra_boards.contains(board)) {
265-
metaDaisy.getDynamicObject()->setProperty("board_file", Toolchain::dir.getChildFile("etc").getChildFile(board + ".json").getFullPathName());
265+
metaDaisy.getDynamicObject()->setProperty("board_file", toolchainDir.getChildFile("etc").getChildFile(board + ".json").getFullPathName());
266266
} else {
267267
metaDaisy.getDynamicObject()->setProperty("board", board);
268268
}
@@ -301,15 +301,15 @@ class DaisyExporter final : public ExporterBase {
301301
} else if (size == 3) {
302302
metaDaisy.getDynamicObject()->setProperty(
303303
"linker_script",
304-
Toolchain::dir.getChildFile("etc").getChildFile("linkers").getChildFile("sram_linker_sdram.lds").getFullPathName());
304+
toolchainDir.getChildFile("etc").getChildFile("linkers").getChildFile("sram_linker_sdram.lds").getFullPathName());
305305
metaDaisy.getDynamicObject()->setProperty("bootloader", "BOOT_SRAM");
306306
} else if (size == 4) {
307307
metaDaisy.getDynamicObject()->setProperty("linker_script", "../../libdaisy/core/STM32H750IB_qspi.lds");
308308
metaDaisy.getDynamicObject()->setProperty("bootloader", "BOOT_QSPI");
309309
} else if (size == 5) {
310310
metaDaisy.getDynamicObject()->setProperty(
311311
"linker_script",
312-
Toolchain::dir.getChildFile("etc").getChildFile("linkers").getChildFile("qspi_linker_sdram.lds").getFullPathName());
312+
toolchainDir.getChildFile("etc").getChildFile("linkers").getChildFile("qspi_linker_sdram.lds").getFullPathName());
313313
metaDaisy.getDynamicObject()->setProperty("bootloader", "BOOT_QSPI");
314314
} else if (size == 6) {
315315
metaDaisy.getDynamicObject()->setProperty("linker_script", customLinker.getFullPathName());
@@ -333,8 +333,8 @@ class DaisyExporter final : public ExporterBase {
333333
}
334334

335335
auto const command = args.joinIntoString(" ");
336-
exportingView->logToConsole("Command: " + command + "\n");
337-
Toolchain::startShellScript(command, this);
336+
startShellScript(command);
337+
338338
waitForProcessToFinish(-1);
339339
exportingView->flushConsole();
340340

@@ -353,8 +353,8 @@ class DaisyExporter final : public ExporterBase {
353353
metaJsonFile.copyFileTo(outputFile.getChildFile("meta.json"));
354354

355355
if (compile) {
356-
auto bin = Toolchain::dir.getChildFile("bin");
357-
auto libDaisy = Toolchain::dir.getChildFile("lib").getChildFile("libdaisy");
356+
auto bin = toolchainDir.getChildFile("bin");
357+
auto libDaisy = toolchainDir.getChildFile("lib").getChildFile("libdaisy");
358358
auto make = bin.getChildFile("make" + exeSuffix);
359359
auto compiler = bin.getChildFile("arm-none-eabi-gcc" + exeSuffix);
360360

@@ -371,17 +371,22 @@ class DaisyExporter final : public ExporterBase {
371371
sourceDir.getChildFile("build").createDirectory();
372372
auto const& gccPath = pathToString(bin);
373373

374+
// Bit hacky, but the only way to get colour coding on daisy builds for Windows
375+
#if JUCE_WINDOWS
376+
sourceDir.getChildFile("Makefile").appendText("\nCFLAGS += -fdiagnostics-color=always");
377+
#endif
378+
374379
auto buildScript = pathToString(make)
375380
+ " -j4 -f "
376381
+ pathToString(sourceDir.getChildFile("Makefile")).quoted()
377382
#if JUCE_WINDOWS
378-
+ " SHELL=" + pathToString(Toolchain::dir.getChildFile("bin").getChildFile("bash.exe")).quoted()
383+
+ " SHELL=" + pathToString(toolchainDir.getChildFile("bin").getChildFile("bash.exe")).quoted()
379384
#endif
380385
+ " GCC_PATH="
381386
+ gccPath
382387
+ " PROJECT_NAME=" + name;
383388

384-
Toolchain::startShellScript(buildScript, this);
389+
startShellScript(buildScript);
385390

386391
waitForProcessToFinish(-1);
387392
exportingView->flushConsole();
@@ -416,8 +421,7 @@ class DaisyExporter final : public ExporterBase {
416421
String testBootloaderScript = "export PATH=\"" + bin.getFullPathName() + ":$PATH\"\n"
417422
+ dfuUtil.getFullPathName() + " -l ";
418423

419-
Toolchain runTest;
420-
auto output = runTest.startShellScriptWithOutput(testBootloaderScript);
424+
auto output = startShellScriptWithOutput(testBootloaderScript);
421425
if (output.contains("alt=1")) {
422426
exportingView->logToConsole("Bootloader not found...\n");
423427
bootloaderExitCode = flashBootloader(bin, sourceDir, make, gccPath);
@@ -434,7 +438,7 @@ class DaisyExporter final : public ExporterBase {
434438
+ " GCC_PATH=" + gccPath
435439
+ " PROJECT_NAME=" + name;
436440

437-
Toolchain::startShellScript(flashScript, this);
441+
startShellScript(flashScript);
438442

439443
waitForProcessToFinish(-1);
440444
exportingView->flushConsole();
@@ -456,7 +460,7 @@ class DaisyExporter final : public ExporterBase {
456460
} else {
457461
auto outputFile = File(outdir);
458462

459-
auto libDaisy = Toolchain::dir.getChildFile("lib").getChildFile("libdaisy");
463+
auto libDaisy = toolchainDir.getChildFile("lib").getChildFile("libdaisy");
460464
libDaisy.copyDirectoryTo(outputFile.getChildFile("libdaisy"));
461465

462466
outputFile.getChildFile("ir").deleteRecursively();

Source/Heavy/ExporterBase.h

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ struct ExporterBase : public Component
2222
bool blockDialog = false;
2323

2424
#if JUCE_WINDOWS
25-
inline static String const exeSuffix = ".exe";
25+
static inline File const toolchainDir = ProjectInfo::appDataDir.getChildFile("Toolchain").getChildFile("usr");
26+
static inline String const exeSuffix = ".exe";
2627
#else
27-
inline static String const exeSuffix = "";
28+
static inline File const toolchainDir = ProjectInfo::appDataDir.getChildFile("Toolchain");
29+
static inline String const exeSuffix = "";
2830
#endif
2931

30-
inline static File heavyExecutable = Toolchain::dir.getChildFile("bin").getChildFile("Heavy").getChildFile("Heavy" + exeSuffix);
31-
32+
static inline File heavyExecutable = toolchainDir.getChildFile("bin").getChildFile("Heavy").getChildFile("Heavy" + exeSuffix);
33+
static inline SmallArray<File> tempFilesToDelete;
34+
3235
bool validPatchSelected = false;
3336
bool canvasDirty = false;
3437
bool isTempFile = false;
@@ -45,6 +48,8 @@ struct ExporterBase : public Component
4548

4649
Label unsavedLabel = Label("", "Warning: patch has unsaved changes");
4750
PluginEditor* editor;
51+
52+
4853

4954
ExporterBase(PluginEditor* pluginEditor, ExportingProgressView* exportView)
5055
: ThreadPool(1, Thread::osDefaultStackSize, Thread::Priority::highest)
@@ -86,7 +91,7 @@ struct ExporterBase : public Component
8691

8792
if (auto const* cnv = editor->getCurrentCanvas()) {
8893
openedPatchFile = File::createTempFile(".pd");
89-
Toolchain::deleteTempFileLater(openedPatchFile);
94+
deleteTempFileLater(openedPatchFile);
9095
patchFile = cnv->patch.getCurrentFile();
9196
if (!patchFile.existsAsFile()) {
9297
openedPatchFile.replaceWithText(cnv->patch.getCanvasContent(), false, false, "\n");
@@ -150,6 +155,67 @@ struct ExporterBase : public Component
150155
return file.getFullPathName();
151156
#endif
152157
}
158+
159+
static void deleteTempFileLater(File const& script)
160+
{
161+
tempFilesToDelete.add(script);
162+
}
163+
164+
static void deleteTempFiles()
165+
{
166+
for (auto& file : tempFilesToDelete) {
167+
if (file.existsAsFile())
168+
file.deleteFile();
169+
if (file.isDirectory())
170+
file.deleteRecursively();
171+
}
172+
}
173+
174+
String startShellScriptWithOutput(String const& scriptText)
175+
{
176+
exportingView->logToConsole("\n\x1b[1;92m> " + scriptText + " \x1b[0m \n\n");
177+
178+
File scriptFile = File::createTempFile(".sh");
179+
deleteTempFileLater(scriptFile);
180+
181+
auto const bash = String("#!/bin/bash\n");
182+
scriptFile.replaceWithText(bash + scriptText, false, false, "\n");
183+
184+
ChildProcess process;
185+
#if JUCE_WINDOWS
186+
auto sh = toolchainDir.getChildFile("bin").getChildFile("sh.exe");
187+
auto arguments = StringArray { sh.getFullPathName(), "--login", scriptFile.getFullPathName().replaceCharacter('\\', '/') };
188+
#else
189+
scriptFile.setExecutePermission(true);
190+
auto arguments = scriptFile.getFullPathName();
191+
#endif
192+
process.start(arguments, ChildProcess::wantStdOut | ChildProcess::wantStdErr);
193+
return process.readAllProcessOutput();
194+
}
195+
196+
void startShellScript(String const& scriptText)
197+
{
198+
exportingView->logToConsole("\n\x1b[1;92m> " + scriptText + " \x1b[0m \n\n");
199+
200+
File scriptFile = File::createTempFile(".sh");
201+
deleteTempFileLater(scriptFile);
202+
203+
#if JUCE_WINDOWS
204+
auto const gccColourFlags = String("export CFLAGS=\"-fdiagnostics-color=always\"\nexport CXXFLAGS=\"-fdiagnostics-color=always\"\n ");
205+
#else
206+
auto const gccColourFlags = String("export TERM=xterm-256color\nexport GCC_URLS=no\n");
207+
#endif
208+
auto const bash = String("#!/bin/bash\n");
209+
scriptFile.replaceWithText(bash + gccColourFlags + scriptText, false, false, "\n");
210+
211+
#if JUCE_WINDOWS
212+
auto sh = toolchainDir.getChildFile("bin").getChildFile("sh.exe");
213+
start(StringArray { sh.getFullPathName(), "--login", scriptFile.getFullPathName().replaceCharacter('\\', '/') });
214+
#else
215+
scriptFile.setExecutePermission(true);
216+
start(scriptFile.getFullPathName(), ChildProcess::wantStdOut | ChildProcess::wantStdErr | ChildProcess::wantTtyOut);
217+
#endif
218+
}
153219

154220
void startExport(File const& outDir)
155221
{
@@ -245,7 +311,7 @@ struct ExporterBase : public Component
245311
static File createMetaJson(DynamicObject::Ptr const& metaJson)
246312
{
247313
auto const metadata = File::createTempFile(".json");
248-
Toolchain::deleteTempFileLater(metadata);
314+
deleteTempFileLater(metadata);
249315
String const metaString = JSON::toString(var(metaJson.get()));
250316
metadata.replaceWithText(metaString, false, false, "\n");
251317
return metadata;

0 commit comments

Comments
 (0)