aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorseivarya <[email protected]>2026-06-20 18:25:02 +0530
committerseivarya <[email protected]>2026-06-20 18:25:02 +0530
commit8798eafd4cc4b32c590a40c276c09b830c5d62da (patch)
treee39a1ca656c893fc0280456a26947e7fdaf7aa59 /src
parent02a1bdae9780c1f08818d1a5039bdfb055372723 (diff)
[refactor]: restructured the project
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp71
-rw-r--r--src/reader.cpp142
2 files changed, 213 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..a0c60cb
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,71 @@
+#include "reader.h"
+
+int main(int argc, char *argv[]) {
+ try {
+ editor_cfg *cfg = (editor_cfg *)malloc(sizeof(editor_cfg));
+ if (cfg == nullptr) {
+ die("[err]: malloc failed\n");
+ }
+
+ enable_raw(cfg);
+ init_editor(cfg);
+
+ int speed { 250000 };
+
+ if (argc < 2)
+ die("[err]: no file provided!\n");
+
+ if (argc > 3)
+ die("[err]: too many arguments!\n");
+
+ if (argc == 3) {
+ if (!is_number(argv[2]))
+ die("[err]: invalid speed interval provided!\n");
+ speed = std::stoi(argv[2]);
+ }
+
+ FILE *fp = fopen(argv[1], "r");
+
+ if (fp == nullptr)
+ die("[err]: fopen failed\n");
+
+ fseek(fp, 0, SEEK_END);
+ long size = ftell(fp);
+ rewind(fp);
+
+ std::string content(size, '\0');
+ fread(content.data(), 1, size, fp);
+
+ fclose(fp);
+
+ std::vector<std::string> data;
+ split(content, data, ' ');
+
+ while(1) {
+ for (std::string &k: data) {
+ if (k.empty()) continue;
+ editor_refresh_scrn(cfg);
+ int mid = k.size() / 2;
+
+ write(STDOUT_FILENO, k.substr(0, mid).c_str(), mid);
+ write(STDOUT_FILENO, "\x1b[31m", 5);
+ write(STDOUT_FILENO, k.substr(mid, 1).c_str(), 1);
+ write(STDOUT_FILENO, "\x1b[m", 3);
+
+ int remaining = k.size() - mid - 1;
+
+ write(STDOUT_FILENO, k.substr(mid + 1, remaining).c_str(), remaining);
+ usleep(speed);
+ }
+ }
+
+ free(cfg);
+
+ } catch (const std::exception &e) {
+ die(e.what());
+ } catch (...) {
+ die("[err]: Unknown exception occurred\n");
+ }
+
+ return 0;
+} /* main.cpp */
diff --git a/src/reader.cpp b/src/reader.cpp
new file mode 100644
index 0000000..dd293db
--- /dev/null
+++ b/src/reader.cpp
@@ -0,0 +1,142 @@
+#include "reader.h"
+#include <csignal>
+
+void die(const char *s) {
+ write(STDOUT_FILENO, "\x1b[2J", 4);
+ write(STDOUT_FILENO, "\x1b[H", 3);
+
+ perror(s);
+ fprintf(stderr, "[exit]: die(s) invoked, exiting..\n");
+ exit(1);
+}
+
+static editor_cfg *g_cfg = nullptr;
+
+void disable_raw_atexit() {
+ if (g_cfg) {
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &(g_cfg->termios_inst));
+ }
+}
+
+void handle_signal(int sig) {
+ disable_raw_atexit();
+ _exit(128 + sig);
+}
+
+void disable_raw(editor_cfg *cfg) {
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &(cfg->termios_inst)))
+ die("tcsetattr");
+}
+
+void enable_raw(editor_cfg *cfg) {
+ if (tcgetattr(STDIN_FILENO, &(cfg->termios_inst)) == -1)
+ die("tcgetattr");
+
+ g_cfg = cfg;
+
+ std::atexit(disable_raw_atexit);
+
+ std::signal(SIGINT, handle_signal);
+ std::signal(SIGTERM, handle_signal);
+ std::signal(SIGQUIT, handle_signal);
+
+ struct termios raw = cfg->termios_inst;
+ raw.c_iflag &= ~(IXON | ICRNL | BRKINT | INPCK | ISTRIP);
+ raw.c_oflag &= ~(OPOST);
+ raw.c_lflag &=
+ ~(ECHO | ICANON | IEXTEN); // disables several keybinds in terminal
+
+ raw.c_cc[VMIN] = 0;
+ raw.c_cc[VTIME] = 1;
+
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1)
+ die("tcsetattr");
+}
+
+char editor_readkey() {
+ int nread;
+ char c;
+
+ while ((nread = read(STDIN_FILENO, &c, 1)) != 1) {
+ if (nread == -1 && errno != EAGAIN)
+ die("read");
+ }
+ return c;
+}
+
+int get_cursor_pos(int *rows, int *cols) {
+ char buff[32];
+ unsigned int i = 0;
+
+ if (write(STDOUT_FILENO, "\x1b[6n", 4) != 4) {
+ return -1;
+ }
+ while (i < sizeof(buff) - 1) {
+ if (read(STDIN_FILENO, &buff[i], 1) != 1)
+ break;
+ if (buff[i] == 'R')
+ break;
+ i++;
+ }
+ buff[i] = '\0';
+
+ if (buff[0] != '\x1b' || buff[1] != '[')
+ return -1;
+ if (sscanf(&buff[2], "%d;%d", rows, cols) != 2)
+ return -1;
+ return 0;
+}
+
+int get_window_size(int *rows, int *cols) {
+ struct winsize w_size;
+
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w_size) == -1 ||
+ w_size.ws_col == 0) {
+ if (write(STDOUT_FILENO, "\x1b[999C\x1b[999B", 12) != 12)
+ return -1;
+ return get_cursor_pos(rows, cols);
+ }
+
+ *rows = w_size.ws_row;
+ *cols = w_size.ws_col;
+
+ return 0;
+}
+
+void editor_refresh_scrn(editor_cfg *cfg) {
+ append_buffer::instance().append("\x1b[2J", 4);
+ char buff[32];
+ memset(buff, 0, sizeof(buff));
+
+ snprintf(buff, sizeof(buff), "\x1b[%d;%dH", cfg->screenrows / 2, cfg->screencols / 2);
+
+ append_buffer::instance().append(buff, strlen(buff));
+ append_buffer::instance().write_output();
+ append_buffer::instance().remove();
+}
+
+size_t split(const std::string &txt, std::vector<std::string> &strings, char ch) {
+ size_t pos = txt.find(ch);
+ size_t initial_pos = 0;
+
+ while (pos != std::string::npos) {
+ strings.push_back(txt.substr(initial_pos, pos - initial_pos));
+ initial_pos = pos + 1;
+ pos = txt.find(ch, initial_pos);
+ }
+
+ strings.push_back(txt.substr(initial_pos));
+ return strings.size();
+}
+
+void init_editor(editor_cfg *cfg) {
+ if (get_window_size(&(cfg->screenrows), &(cfg->screencols)) == -1)
+ die("get_window_size");
+}
+
+int is_number(char *strnum) {
+ std::string str = strnum;
+ std::string::const_iterator it = str.begin();
+ while (it != str.end() && std::isdigit(*it)) ++it;
+ return !str.empty() && it == str.end();
+}