8#include "absl/strings/str_cat.h"
9#include "absl/strings/match.h"
17using util::FileDialogWrapper;
21static const char *
const kKeywords[] = {
22 "ADC",
"AND",
"ASL",
"BCC",
"BCS",
"BEQ",
"BIT",
"BMI",
"BNE",
"BPL",
23 "BRA",
"BRL",
"BVC",
"BVS",
"CLC",
"CLD",
"CLI",
"CLV",
"CMP",
"CPX",
24 "CPY",
"DEC",
"DEX",
"DEY",
"EOR",
"INC",
"INX",
"INY",
"JMP",
"JSR",
25 "JSL",
"LDA",
"LDX",
"LDY",
"LSR",
"MVN",
"NOP",
"ORA",
"PEA",
"PER",
26 "PHA",
"PHB",
"PHD",
"PHP",
"PHX",
"PHY",
"PLA",
"PLB",
"PLD",
"PLP",
27 "PLX",
"PLY",
"REP",
"ROL",
"ROR",
"RTI",
"RTL",
"RTS",
"SBC",
"SEC",
28 "SEI",
"SEP",
"STA",
"STP",
"STX",
"STY",
"STZ",
"TAX",
"TAY",
"TCD",
29 "TCS",
"TDC",
"TRB",
"TSB",
"TSC",
"TSX",
"TXA",
"TXS",
"TXY",
"TYA",
30 "TYX",
"WAI",
"WDM",
"XBA",
"XCE",
"ORG",
"LOROM",
"HIROM"};
32static const char *
const kIdentifiers[] = {
33 "abort",
"abs",
"acos",
"asin",
"atan",
"atexit",
34 "atof",
"atoi",
"atol",
"ceil",
"clock",
"cosh",
35 "ctime",
"div",
"exit",
"fabs",
"floor",
"fmod",
36 "getchar",
"getenv",
"isalnum",
"isalpha",
"isdigit",
"isgraph",
37 "ispunct",
"isspace",
"isupper",
"kbhit",
"log10",
"log2",
38 "log",
"memcmp",
"modf",
"pow",
"putchar",
"putenv",
39 "puts",
"rand",
"remove",
"rename",
"sinh",
"sqrt",
40 "srand",
"strcat",
"strcmp",
"strerror",
"time",
"tolower",
45 for (
auto &k : kKeywords) language_65816.
mKeywords.emplace(k);
47 for (
auto &k : kIdentifiers) {
50 language_65816.
mIdentifiers.insert(std::make_pair(std::string(k),
id));
54 std::make_pair<std::string, TextEditor::PaletteIndex>(
57 std::make_pair<std::string, TextEditor::PaletteIndex>(
60 std::make_pair<std::string, TextEditor::PaletteIndex>(
63 std::make_pair<std::string, TextEditor::PaletteIndex>(
64 "[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][+-]?[0-9]+)?[fF]?",
67 std::make_pair<std::string, TextEditor::PaletteIndex>(
70 std::make_pair<std::string, TextEditor::PaletteIndex>(
73 std::make_pair<std::string, TextEditor::PaletteIndex>(
74 "0[xX][0-9a-fA-F]+[uU]?[lL]?[lL]?",
77 std::make_pair<std::string, TextEditor::PaletteIndex>(
80 std::make_pair<std::string, TextEditor::PaletteIndex>(
81 "[\\[\\]\\{\\}\\!\\%\\^\\&\\*\\(\\)\\-\\+\\=\\~\\|\\<\\>\\?\\/"
92 language_65816.
mName =
"65816";
94 return language_65816;
98 const std::vector<std::string>& files,
99 const std::vector<std::string>& ignored_files) {
100 std::vector<std::string> filtered_files;
101 for (
const auto& file : files) {
103 if (absl::StrContains(file,
'/')) {
107 if (!absl::StrContains(file,
'.')) {
110 if (std::ranges::find(ignored_files, file) == ignored_files.end()) {
111 filtered_files.push_back(file);
114 return filtered_files;
119 std::ifstream gitignore(folder +
"/.gitignore");
120 std::vector<std::string> ignored_files;
121 if (gitignore.good()) {
123 while (std::getline(gitignore, line)) {
124 if (line[0] ==
'#') {
127 if (line[0] ==
'!') {
131 ignored_files.push_back(line);
136 current_folder.
name = folder;
140 for (
const auto& subfolder :
143 folder_item.
name = subfolder;
144 std::string full_folder = current_folder.
name +
"/" + subfolder;
146 for (
const auto& files : folder_files) {
148 if (absl::StrContains(files,
'/')) {
152 if (!absl::StrContains(files,
'.')) {
155 if (std::ranges::find(ignored_files, files) != ignored_files.end()) {
158 folder_item.
files.push_back(files);
161 for (
const auto& subdir :
164 subfolder_item.
name = subdir;
166 folder_item.
subfolders.push_back(subfolder_item);
168 current_folder.
subfolders.push_back(folder_item);
171 return current_folder;
182 card_registry->
RegisterCard({.card_id =
"assembly.editor", .display_name =
"Assembly Editor",
184 .shortcut_hint =
"", .priority = 10});
185 card_registry->RegisterCard({.card_id =
"assembly.file_browser", .display_name =
"File Browser",
187 .shortcut_hint =
"", .priority = 20});
198 return absl::OkStatus();
206 ImGui::Begin(
"Assembly Editor", &is_loaded);
207 if (ImGui::BeginMenuBar()) {
214 ImGui::Text(
"%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
227 ImGui::Text(
"%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
243 bool file_browser_open =
true;
244 if (file_browser_card.
Begin(&file_browser_open)) {
248 if (ImGui::Button(
"Open Folder")) {
253 file_browser_card.
End();
264 if (file_id >=
files_.size()) {
273 if (file_card.
Begin()) {
274 if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)) {
277 open_files_[file_id].Render(absl::StrCat(
"##", card_name).c_str());
292 return absl::OkStatus();
294 return absl::FailedPreconditionError(
"No active file to save.");
312 if (ImGui::BeginChild(
"##current_folder", ImVec2(0, 0),
true,
313 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
314 if (ImGui::BeginTable(
"##file_table", 2,
315 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
316 ImGuiTableFlags_Resizable |
317 ImGuiTableFlags_Sortable)) {
318 ImGui::TableSetupColumn(
"Name", ImGuiTableColumnFlags_WidthFixed, 256.0f);
319 ImGui::TableSetupColumn(
"Type", ImGuiTableColumnFlags_WidthStretch);
321 ImGui::TableHeadersRow();
324 ImGui::TableNextRow();
325 ImGui::TableNextColumn();
326 if (ImGui::Selectable(file.c_str())) {
329 ImGui::TableNextColumn();
334 ImGui::TableNextRow();
335 ImGui::TableNextColumn();
336 if (ImGui::TreeNode(subfolder.name.c_str())) {
337 for (
const auto& file : subfolder.files) {
338 ImGui::TableNextRow();
339 ImGui::TableNextColumn();
340 if (ImGui::Selectable(file.c_str())) {
342 subfolder.name,
"/", file));
344 ImGui::TableNextColumn();
349 ImGui::TableNextColumn();
350 ImGui::Text(
"Folder");
363 if (ImGui::BeginMenu(
"File")) {
364 if (ImGui::MenuItem(
"Open",
"Ctrl+O")) {
368 if (ImGui::MenuItem(
"Save",
"Ctrl+S")) {
376 if (ImGui::BeginMenu(
"Edit")) {
377 if (ImGui::MenuItem(
"Undo",
"Ctrl+Z")) {
380 if (ImGui::MenuItem(
"Redo",
"Ctrl+Y")) {
384 if (ImGui::MenuItem(
"Cut",
"Ctrl+X")) {
387 if (ImGui::MenuItem(
"Copy",
"Ctrl+C")) {
390 if (ImGui::MenuItem(
"Paste",
"Ctrl+V")) {
394 if (ImGui::MenuItem(
"Find",
"Ctrl+F")) {
405 if (
files_[file_id] == filename) {
412 int new_file_id =
files_.size();
413 files_.push_back(std::string(filename));
423 if (!content.empty()) {
428 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error opening file: %s\n",
429 std::string(filename).c_str());
435 return absl::OkStatus();
440 return absl::OkStatus();
445 return absl::OkStatus();
450 return absl::OkStatus();
455 return absl::OkStatus();
static const Palette & GetDarkPalette()
Coordinates GetCursorPosition() const
int GetTotalLines() const
void Render(const char *aTitle, const ImVec2 &aSize=ImVec2(), bool aBorder=false)
const LanguageDefinition & GetLanguageDefinition() const
void SetLanguageDefinition(const LanguageDefinition &aLanguageDef)
std::string current_file_
absl::Status Save() override
std::vector< TextEditor > open_files_
absl::Status Load() override
void Initialize() override
void ChangeActiveFile(const std::string_view &filename)
absl::Status Copy() override
void OpenFolder(const std::string &folder_path)
absl::Status Paste() override
FolderItem current_folder_
absl::Status Update() override
std::vector< std::string > files_
absl::Status Redo() override
ImVector< int > active_files_
absl::Status Undo() override
absl::Status Cut() override
void RegisterCard(size_t session_id, const CardInfo &base_info)
Register a card for a specific session.
EditorDependencies dependencies_
std::string MakeCardTitle(const std::string &base_title) const
Draggable, dockable card for editor sub-windows.
bool Begin(bool *p_open=nullptr)
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
static std::string ShowOpenFolderDialog()
ShowOpenFolderDialog opens a file dialog and returns the selected folder path. Uses global feature fl...
static std::vector< std::string > GetFilesInFolder(const std::string &folder_path)
static std::vector< std::string > GetSubdirectoriesInFolder(const std::string &folder_path)
#define ICON_MD_FOLDER_OPEN
#define ICON_MD_DESCRIPTION
FolderItem LoadFolder(const std::string &folder)
std::vector< std::string > RemoveIgnoredFiles(const std::vector< std::string > &files, const std::vector< std::string > &ignored_files)
Editors are the view controllers for the application.
void VerticalSpacing(float pixels)
TextEditor::LanguageDefinition GetAssemblyLanguageDef()
void SaveFile(const std::string &filename, const std::string &contents)
std::string LoadFile(const std::string &filename)
Loads the entire contents of a file into a string.
TokenRegexStrings mTokenRegexStrings
std::string mSingleLineComment
std::string mCommentStart
EditorCardRegistry * card_registry
std::vector< FolderItem > subfolders
std::vector< std::string > files