add hard editor
Some checks failed
build_test / build (push) Failing after 2m49s

This commit is contained in:
PoliEcho 2025-06-02 20:26:58 +02:00
parent 2a374dbf4b
commit dded22125c
3 changed files with 238 additions and 5 deletions

189
src/editor_hard.cpp Normal file
View File

@ -0,0 +1,189 @@
#include <ncurses.h>
#include <cstddef>
#include <cstdint>
#include <nlohmann/json.hpp>
#include <nlohmann/json_fwd.hpp>
#include <sstream>
#include <string>
#include <vector>
#include "strings.h"
using nlohmann::json;
void save_document(std::string& text, std::vector<std::string>& lines) {
text = "";
for (const std::string& line : lines) {
text.append(line);
text.append("\n");
}
}
void editor_hard(std::string& text) {
uint16_t cursor_x = 0;
uint16_t cursor_y = 0;
std::vector<std::string> lines;
char mode = 'n';
uint16_t window_height, window_width;
mode = 'n';
noecho();
curs_set(1);
cbreak();
keypad(stdscr, TRUE);
getmaxyx(stdscr, window_height, window_width);
// Parse the multi-line string into individual lines
lines.clear();
std::stringstream ss(text);
std::string line;
while (std::getline(ss, line)) {
lines.push_back(line);
}
// Ensure at least one empty line exists
if (lines.empty()) {
lines.push_back("");
}
while (true) {
clear();
// Draw text lines
for (size_t i = 0; i < window_height - 1 && i < lines.size(); i++) {
mvprintw(i, 0, "%s", lines[i].c_str());
}
// Draw status line
std::string status = "Mode: " + std::string(1, mode);
mvprintw(window_height - 1, 0, "%s", status.c_str());
move(cursor_y, cursor_x);
refresh();
{
int ch = getch();
switch (mode) {
case 'n': // Normal mode
switch (ch) {
case 'h':
if (cursor_x > 0) {
cursor_x--;
}
break;
case 'j':
if (cursor_y < lines.size() - 1) {
cursor_y++;
if (cursor_x > lines[cursor_y].length()) {
cursor_x = lines[cursor_y].length();
}
}
break;
case 'k':
if (cursor_y > 0) {
cursor_y--;
if (cursor_x > lines[cursor_y].length()) {
cursor_x = lines[cursor_y].length();
}
}
break;
case 'l':
if (cursor_x < lines[cursor_y].length()) {
cursor_x++;
}
break;
case 'i':
case 'a':
mode = 'i';
break;
case 'x':
if (cursor_x < lines[cursor_y].length()) {
lines[cursor_y].erase(cursor_x, 1);
}
break;
case ':': {
// Enter command mode
std::string command = "";
int cmd_ch;
// Show command prompt
mvprintw(window_height - 1, 0, ":%s", command.c_str());
clrtoeol();
refresh();
while ((cmd_ch = getch()) != '\n' && cmd_ch != '\r') {
if (cmd_ch == 27) { // ESC - cancel command
break;
} else if (cmd_ch == KEY_BACKSPACE || cmd_ch == 127) {
if (!command.empty()) {
command.pop_back();
}
} else if (cmd_ch >= 32 && cmd_ch <= 126) {
command += static_cast<char>(cmd_ch);
}
mvprintw(window_height - 1, 0, ":%s", command.c_str());
clrtoeol();
refresh();
}
// Execute command
if (cmd_ch != 27) { // If not cancelled
switch (hash_djb2a(command)) {
case "q"_sh:
return;
break;
case "w"_sh:
save_document(text, lines);
break;
case "wq"_sh:
case "x"_sh:
save_document(text, lines);
return;
break;
case "q!"_sh:
return;
break;
}
}
} break;
}
break;
case 'i': // Insert mode
switch (ch) {
case 27: // ESC
mode = 'n';
if (cursor_x > 0)
cursor_x--;
break;
case KEY_BACKSPACE:
case 127:
if (mode == 'i' && cursor_x > 0) {
lines[cursor_y].erase(cursor_x - 1, 1);
cursor_x--;
}
break;
case '\n':
case '\r': {
// Insert new line
std::string new_line = lines[cursor_y].substr(cursor_x);
lines[cursor_y] = lines[cursor_y].substr(0, cursor_x);
lines.insert(lines.begin() + cursor_y + 1, new_line);
cursor_y++;
cursor_x = 0;
break;
}
default:
if (ch >= 32 && ch <= 126) {
if (mode == 'i') {
lines[cursor_y].insert(cursor_x, 1, ch);
cursor_x++;
}
}
break;
}
break;
}
}
}
}

5
src/editor_hard.h Normal file
View File

@ -0,0 +1,5 @@
#ifndef PARADOCS_EDEH_H_
#define PARADOCS_EDEH_H_
#include <string>
void editor_hard(std::string& text);
#endif

View File

@ -17,15 +17,26 @@
#include "const.h"
#include "cups.h"
#include "editor_easy.h"
#include "editor_hard.h"
#include "gameske_funkce.h"
#include "memory.h"
#include "signal.h"
#include "strings.h"
#include "types.h"
using nlohmann::json;
std::vector<allocation> main_menu_allocated;
#define COMPLAINTS_DIR "complaints"
std::array<std::string, 2> get_name_date_from_item(ITEM* item) {
std::stringstream ss(item_description(item));
std::array<std::string, 2> name_date;
name_date[0] = item_name(item);
std::getline(ss, name_date[1], ' ');
return name_date;
}
void menu() {
current_allocated = &main_menu_allocated;
/* Initialize curses */
@ -165,6 +176,37 @@ void menu() {
break;
}
case "eh"_sh: {
std::array<std::string, 2> name_date =
get_name_date_from_item(current_item(main_menu.menu));
std::ifstream selected_file(COMPLAINTS_DIR "/" + name_date[0] +
'_' + name_date[1]);
if (!selected_file.is_open()) {
std::clog << selected_file.rdstate() << "\n";
std::cerr << RED "[ERROR] " RESET << loc_strings->invalid_input
<< "\n"
<< "File: "
<< COMPLAINTS_DIR "/" + name_date[0] + '_' +
name_date[1]
<< "\n";
exit(EINVAL);
}
json selected_file_json = json::parse(selected_file);
selected_file.close();
std::string complaint_text =
selected_file_json["complaint_text"].get<std::string>();
editor_hard(complaint_text);
curs_set(0);
clear();
selected_file_json["complaint_text"] = complaint_text;
std::ofstream selected_file_out(COMPLAINTS_DIR "/" + name_date[0] +
'_' + name_date[1]);
selected_file_out << selected_file_json;
selected_file_out.close();
break;
}
default:
print_in_middle(main_menu.win, 10, 0, 40,
loc_strings->unknown_command, COLOR_PAIR(1));
@ -172,11 +214,8 @@ void menu() {
}
break;
case 'm': {
std::stringstream item_desc_ss(
item_description(current_item(main_menu.menu)));
std::string name_date[2];
name_date[0] = item_name(current_item(main_menu.menu));
std::getline(item_desc_ss, name_date[1], ' ');
std::array<std::string, 2> name_date =
get_name_date_from_item(current_item(main_menu.menu));
{
uint8_t n = 0;