Skip to content

Commit

Permalink
IPC between texedit and tecomp with piped+async subprocesses
Browse files Browse the repository at this point in the history
IO redirection from tecomp for texedit to recieve its output while
it's run in the background
  • Loading branch information
kosude committed Apr 21, 2024
1 parent 036d421 commit 8ba556f
Show file tree
Hide file tree
Showing 14 changed files with 421 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .tokeignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
vendor/
tests/
examples/
deps/
docs/
build/
Expand Down
4 changes: 4 additions & 0 deletions texedit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ set(SRCS
"gui/main_frame.cpp"
"gui/preview_panel.cpp"
"gui/prog_info.cpp"
"process/compiler/tecomp_proc.cpp"
"process/process_mgr.cpp"
"process/process.cpp"
"util/log.cpp"
"util/resources.cpp"
"main.cpp"
)

Expand Down
14 changes: 13 additions & 1 deletion texedit/gui/main_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

#include "main_frame.hpp"

#include "process/process.hpp"
#include "util/log.hpp"
#include "util/except.hpp"
#include "util/resources.hpp"
#include "command_ids.hpp"
#include "editor_panel.hpp"
#include "preview_panel.hpp"
Expand All @@ -18,7 +20,9 @@
#include <wx/splitter.h>

namespace te {
MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "TexEdit", wxDefaultPosition, wxSize{1024, 640}) {
MainFrame::MainFrame() : wxFrame{nullptr, wxID_ANY, "TexEdit", wxDefaultPosition, wxSize{1024, 640}}, _proc_mgr{this}, _tecomp{_proc_mgr} {
_tecomp.Start();

BuildMenuBar();
BuildSplitLayout();
}
Expand Down Expand Up @@ -64,6 +68,13 @@ namespace te {
SetMenuBar(menuBar);
}

void MainFrame::OnIdle(wxIdleEvent &ev) {
wxString s = _proc_mgr.PollPipedOutput();
if (!s.IsEmpty()) {
std::cout << s;
}
}

void MainFrame::ShowURL(const std::string &url) {
if (!wxLaunchDefaultBrowser(url)) {
util::log::Error("Failed to open URL \"" + url + "\"");
Expand Down Expand Up @@ -96,6 +107,7 @@ namespace te {
}

wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
EVT_IDLE(MainFrame::OnIdle)
EVT_MENU(wxID_EXIT, MainFrame::OnMenuQuit)
EVT_MENU(wxID_ABOUT, MainFrame::OnMenuAbout)
EVT_MENU(cmds::Menu_URLSourcePage, MainFrame::OnMenuURLSourcePage)
Expand Down
8 changes: 8 additions & 0 deletions texedit/gui/main_frame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,23 @@

#include <wx/wx.h>

#include "process/process_mgr.hpp"
#include "process/compiler/tecomp_proc.hpp"

namespace te {
class MainFrame : public wxFrame {
public:
MainFrame();

private:
ProcessManager _proc_mgr;
TECompProcess _tecomp;

void BuildSplitLayout();
void BuildMenuBar();

void OnIdle(wxIdleEvent &ev);

void ShowURL(const std::string &url);

void OnMenuAbout(wxCommandEvent &event);
Expand Down
41 changes: 29 additions & 12 deletions texedit/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,44 @@ wxIMPLEMENT_APP(te::Application);

namespace te {
bool Application::OnExceptionInMainLoop() {
wxString what;
try {
throw;
} catch (const std::exception &e) {
util::log::Fatal(e.what());

if (wxMessageBox("An unexpected exception has occurred:\n"
"\"" + std::string{e.what()} + "\"\n\n"
"TexEdit can attempt to keep running so you can save your data. Do you want to try?",
"Fatal Error", wxYES | wxNO | wxICON_ERROR)
== wxYES) {
util::log::Warn("Attempting to continue execution following a potentially fatal exception");
return true;
}
what = e.what();
} catch (...) {
what = "Unknown runtime error";
}

util::log::Fatal(what.ToStdString());

if (wxMessageBox("An unexpected exception has occurred:\n"
"\"" + what + "\"\n\n"
"TexEdit can attempt to keep running so you can save your data. Do you want to try?",
"Fatal Error", wxYES | wxNO | wxICON_ERROR)
== wxYES) {
util::log::Warn("Attempting to continue execution following a potentially fatal exception");
return true;
}

return false;
}

void Application::OnUnhandledException() {
wxMessageBox("An unhandled exception has occurred and TexEdit cannot recover.\n"
"The program will now terminate.",
wxString what;
try {
throw;
} catch (const std::exception &e) {
what = e.what();
} catch (...) {
what = "Unknown runtime error";
}

util::log::Fatal("(unhandled) " + what.ToStdString());

wxMessageBox("An unexpected exception has occurred:\n"
"\"" + what + "\"\n\n"
"This was unhandled and TexEdit cannot recover. The program will now terminate.",
"Unhandled Exception", wxOK | wxICON_ERROR);
}

Expand Down
30 changes: 30 additions & 0 deletions texedit/process/compiler/tecomp_proc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2024 Jack Bennett.
* All Rights Reserved.
*
* See the LICENCE file for more information.
*/

#include "tecomp_proc.hpp"

#include "util/except.hpp"
#include "util/resources.hpp"

namespace te {
TECompProcess::TECompProcess(ProcessManager &mgr) : _mgr{mgr}, _id{1} {
_cmd = util::res::RelToExec("tecomp");
if (!util::res::ValidateExecutable(_cmd.ToStdString())) {
throw util::except::MissingComponentException("tecomp");
}
}

void TECompProcess::Start() {
const char *const argv[] = {
_cmd.ToUTF8(),
"watch", "examples", "examples/HelloWorld.tex",
0
};

_mgr.ExecutePipedAsync(_id, argv);
}
}
33 changes: 33 additions & 0 deletions texedit/process/compiler/tecomp_proc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2024 Jack Bennett.
* All Rights Reserved.
*
* See the LICENCE file for more information.
*/

#pragma once
#ifndef __texedit__tecomp_proc_hpp__
#define __texedit__tecomp_proc_hpp__

#include <wx/wx.h>

#include "process/process_mgr.hpp"

namespace te {
class TECompProcess {
public:
TECompProcess(ProcessManager &mgr);

void Start();

inline int GetID() { return _id; }

private:
ProcessManager &_mgr;
wxString _cmd;

int _id;
};
}

#endif
45 changes: 45 additions & 0 deletions texedit/process/process.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 Jack Bennett.
* All Rights Reserved.
*
* See the LICENCE file for more information.
*/

#include "process.hpp"

#include "process_mgr.hpp"

#include <wx/txtstrm.h>
#include <iostream>

namespace te {
Process::Process(wxEvtHandler *parent, ProcessManager *mgr) : wxProcess(parent), _mgr{mgr} {
}

void Process::OnTerminate(int pid, int status) {
_mgr->HandleProcessTerminated(this, pid, status);
}

PipedProcess::PipedProcess(wxEvtHandler *parent, ProcessManager *mgr) : Process(parent, mgr) {
Redirect();
}

wxString PipedProcess::ReadLineStdout() {
wxString r{""};

if (IsInputAvailable()) {
wxTextInputStream tis(*GetInputStream());
r << _cmd << " (stdout): " << tis.ReadLine() << "\n";
}
if (IsErrorAvailable()) {
wxTextInputStream tis(*GetErrorStream());
r << _cmd << " (stderr): " << tis.ReadLine() << "\n";
}

return r;
}

void PipedProcess::OnTerminate(int pid, int status) {
_mgr->HandlePipedProcessTerminated(this, pid, status);
}
}
43 changes: 43 additions & 0 deletions texedit/process/process.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2024 Jack Bennett.
* All Rights Reserved.
*
* See the LICENCE file for more information.
*/

#pragma once
#ifndef __texedit__process_mgr_hpp__
#define __texedit__process_mgr_hpp__

#include <wx/process.h>

#include <vector>

namespace te {
class ProcessManager;

class Process : public wxProcess {
public:
Process(wxEvtHandler *parent, ProcessManager *mgr);

virtual void OnTerminate(int pid, int status) override;

inline void SetCmd(const wxString &cmd) { _cmd = cmd; }
inline wxString GetCmd() { return _cmd; }

protected:
ProcessManager *_mgr;
wxString _cmd{};
};

class PipedProcess : public Process {
public:
PipedProcess(wxEvtHandler *parent, ProcessManager *mgr);

wxString ReadLineStdout();

virtual void OnTerminate(int pid, int status) override;
};
}

#endif
Loading

0 comments on commit 8ba556f

Please sign in to comment.