summaryrefslogtreecommitdiff
path: root/DevTools
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-10-21 20:17:32 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-10-21 20:17:32 +0200
commit43ccb2885210eca8caebae3c0f4ba82d61a4a148 (patch)
treec30f2f0104d3944945adab0842834bfd1abf2507 /DevTools
parent5b30aa8b0212575701e46cf70fc762deae0daa65 (diff)
downloadserenity-43ccb2885210eca8caebae3c0f4ba82d61a4a148.zip
HackStudio: Embed a Terminal widget below the text editor
This will be very useful for running (and interacting with) programs after we build them. :^)
Diffstat (limited to 'DevTools')
-rw-r--r--DevTools/HackStudio/Makefile3
-rw-r--r--DevTools/HackStudio/TerminalWrapper.cpp95
-rw-r--r--DevTools/HackStudio/TerminalWrapper.h16
-rw-r--r--DevTools/HackStudio/main.cpp10
4 files changed, 120 insertions, 4 deletions
diff --git a/DevTools/HackStudio/Makefile b/DevTools/HackStudio/Makefile
index d23b1d60a6..23bcd506eb 100644
--- a/DevTools/HackStudio/Makefile
+++ b/DevTools/HackStudio/Makefile
@@ -2,6 +2,7 @@ include ../../Makefile.common
OBJS = \
Project.o \
+ TerminalWrapper.o \
main.o
APP = HackStudio
@@ -11,7 +12,7 @@ DEFINES += -DUSERLAND
all: $(APP)
$(APP): $(OBJS)
- $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lgui -ldraw -lcore -lc
+ $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lvt -lgui -ldraw -lcore -lc
.cpp.o:
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
diff --git a/DevTools/HackStudio/TerminalWrapper.cpp b/DevTools/HackStudio/TerminalWrapper.cpp
new file mode 100644
index 0000000000..d1f20bf8bb
--- /dev/null
+++ b/DevTools/HackStudio/TerminalWrapper.cpp
@@ -0,0 +1,95 @@
+#include "TerminalWrapper.h"
+#include <AK/String.h>
+#include <LibCore/CConfigFile.h>
+#include <LibGUI/GBoxLayout.h>
+#include <LibVT/TerminalWidget.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+static void run_command(int ptm_fd, const String& command)
+{
+ pid_t pid = fork();
+ if (pid == 0) {
+ const char* tty_name = ptsname(ptm_fd);
+ if (!tty_name) {
+ perror("ptsname");
+ exit(1);
+ }
+ close(ptm_fd);
+ int pts_fd = open(tty_name, O_RDWR);
+ if (pts_fd < 0) {
+ perror("open");
+ exit(1);
+ }
+
+ // NOTE: It's okay if this fails.
+ (void)ioctl(0, TIOCNOTTY);
+
+ close(0);
+ close(1);
+ close(2);
+
+ int rc = dup2(pts_fd, 0);
+ if (rc < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ rc = dup2(pts_fd, 1);
+ if (rc < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ rc = dup2(pts_fd, 2);
+ if (rc < 0) {
+ perror("dup2");
+ exit(1);
+ }
+ rc = close(pts_fd);
+ if (rc < 0) {
+ perror("close");
+ exit(1);
+ }
+ rc = ioctl(0, TIOCSCTTY);
+ if (rc < 0) {
+ perror("ioctl(TIOCSCTTY)");
+ exit(1);
+ }
+ const char* args[4] = { "/bin/Shell", nullptr, nullptr, nullptr };
+ if (!command.is_empty()) {
+ args[1] = "-c";
+ args[2] = command.characters();
+ }
+ const char* envs[] = { "TERM=xterm", "PATH=/bin:/usr/bin:/usr/local/bin", nullptr };
+ rc = execve("/bin/Shell", const_cast<char**>(args), const_cast<char**>(envs));
+ if (rc < 0) {
+ perror("execve");
+ exit(1);
+ }
+ ASSERT_NOT_REACHED();
+ }
+}
+
+TerminalWrapper::TerminalWrapper(GWidget* parent)
+ : GWidget(parent)
+{
+ set_layout(make<GBoxLayout>(Orientation::Vertical));
+
+ int ptm_fd = open("/dev/ptmx", O_RDWR);
+ if (ptm_fd < 0) {
+ perror("open(ptmx)");
+ ASSERT_NOT_REACHED();
+ }
+
+ run_command(ptm_fd, "/bin/Shell");
+
+ RefPtr<CConfigFile> config = CConfigFile::get_for_app("Terminal");
+ m_terminal_widget = TerminalWidget::construct(ptm_fd, config);
+ add_child(*m_terminal_widget);
+}
+
+TerminalWrapper::~TerminalWrapper()
+{
+}
diff --git a/DevTools/HackStudio/TerminalWrapper.h b/DevTools/HackStudio/TerminalWrapper.h
new file mode 100644
index 0000000000..c36e421a1f
--- /dev/null
+++ b/DevTools/HackStudio/TerminalWrapper.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <LibGUI/GWidget.h>
+
+class TerminalWidget;
+
+class TerminalWrapper final : public GWidget {
+ C_OBJECT(TerminalWrapper)
+public:
+ virtual ~TerminalWrapper() override;
+
+private:
+ explicit TerminalWrapper(GWidget* parent);
+
+ RefPtr<TerminalWidget> m_terminal_widget;
+};
diff --git a/DevTools/HackStudio/main.cpp b/DevTools/HackStudio/main.cpp
index 8f14f07a4f..9142021493 100644
--- a/DevTools/HackStudio/main.cpp
+++ b/DevTools/HackStudio/main.cpp
@@ -1,4 +1,5 @@
#include "Project.h"
+#include "TerminalWrapper.h"
#include <LibCore/CFile.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GApplication.h>
@@ -39,13 +40,14 @@ int main(int argc, char** argv)
auto toolbar = GToolBar::construct(widget);
- auto splitter = GSplitter::construct(Orientation::Horizontal, widget);
- auto project_list_view = GListView::construct(splitter);
+ auto outer_splitter = GSplitter::construct(Orientation::Horizontal, widget);
+ auto project_list_view = GListView::construct(outer_splitter);
project_list_view->set_model(project->model());
project_list_view->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill);
project_list_view->set_preferred_size(200, 0);
- auto text_editor = GTextEditor::construct(GTextEditor::MultiLine, splitter);
+ auto inner_splitter = GSplitter::construct(Orientation::Vertical, outer_splitter);
+ auto text_editor = GTextEditor::construct(GTextEditor::MultiLine, inner_splitter);
text_editor->set_ruler_visible(true);
project_list_view->on_activation = [&](auto& index) {
@@ -58,6 +60,8 @@ int main(int argc, char** argv)
text_editor->set_text(file->read_all());
};
+ auto terminal_wrapper = TerminalWrapper::construct(inner_splitter);
+
auto statusbar = GStatusBar::construct(widget);
text_editor->on_cursor_change = [&] {