7#include "absl/strings/str_cat.h"
8#include "absl/strings/match.h"
16using util::FileDialogWrapper;
20static const char *
const kKeywords[] = {
21 "ADC",
"AND",
"ASL",
"BCC",
"BCS",
"BEQ",
"BIT",
"BMI",
"BNE",
"BPL",
22 "BRA",
"BRL",
"BVC",
"BVS",
"CLC",
"CLD",
"CLI",
"CLV",
"CMP",
"CPX",
23 "CPY",
"DEC",
"DEX",
"DEY",
"EOR",
"INC",
"INX",
"INY",
"JMP",
"JSR",
24 "JSL",
"LDA",
"LDX",
"LDY",
"LSR",
"MVN",
"NOP",
"ORA",
"PEA",
"PER",
25 "PHA",
"PHB",
"PHD",
"PHP",
"PHX",
"PHY",
"PLA",
"PLB",
"PLD",
"PLP",
26 "PLX",
"PLY",
"REP",
"ROL",
"ROR",
"RTI",
"RTL",
"RTS",
"SBC",
"SEC",
27 "SEI",
"SEP",
"STA",
"STP",
"STX",
"STY",
"STZ",
"TAX",
"TAY",
"TCD",
28 "TCS",
"TDC",
"TRB",
"TSB",
"TSC",
"TSX",
"TXA",
"TXS",
"TXY",
"TYA",
29 "TYX",
"WAI",
"WDM",
"XBA",
"XCE",
"ORG",
"LOROM",
"HIROM"};
31static const char *
const kIdentifiers[] = {
32 "abort",
"abs",
"acos",
"asin",
"atan",
"atexit",
33 "atof",
"atoi",
"atol",
"ceil",
"clock",
"cosh",
34 "ctime",
"div",
"exit",
"fabs",
"floor",
"fmod",
35 "getchar",
"getenv",
"isalnum",
"isalpha",
"isdigit",
"isgraph",
36 "ispunct",
"isspace",
"isupper",
"kbhit",
"log10",
"log2",
37 "log",
"memcmp",
"modf",
"pow",
"putchar",
"putenv",
38 "puts",
"rand",
"remove",
"rename",
"sinh",
"sqrt",
39 "srand",
"strcat",
"strcmp",
"strerror",
"time",
"tolower",
44 for (
auto &k : kKeywords) language_65816.
mKeywords.emplace(k);
46 for (
auto &k : kIdentifiers) {
49 language_65816.
mIdentifiers.insert(std::make_pair(std::string(k),
id));
53 std::make_pair<std::string, TextEditor::PaletteIndex>(
56 std::make_pair<std::string, TextEditor::PaletteIndex>(
59 std::make_pair<std::string, TextEditor::PaletteIndex>(
62 std::make_pair<std::string, TextEditor::PaletteIndex>(
63 "[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][+-]?[0-9]+)?[fF]?",
66 std::make_pair<std::string, TextEditor::PaletteIndex>(
69 std::make_pair<std::string, TextEditor::PaletteIndex>(
72 std::make_pair<std::string, TextEditor::PaletteIndex>(
73 "0[xX][0-9a-fA-F]+[uU]?[lL]?[lL]?",
76 std::make_pair<std::string, TextEditor::PaletteIndex>(
79 std::make_pair<std::string, TextEditor::PaletteIndex>(
80 "[\\[\\]\\{\\}\\!\\%\\^\\&\\*\\(\\)\\-\\+\\=\\~\\|\\<\\>\\?\\/"
91 language_65816.
mName =
"65816";
93 return language_65816;
97 const std::vector<std::string>& files,
98 const std::vector<std::string>& ignored_files) {
99 std::vector<std::string> filtered_files;
100 for (
const auto& file : files) {
102 if (absl::StrContains(file,
'/')) {
106 if (!absl::StrContains(file,
'.')) {
109 if (std::ranges::find(ignored_files, file) == ignored_files.end()) {
110 filtered_files.push_back(file);
113 return filtered_files;
118 std::ifstream gitignore(folder +
"/.gitignore");
119 std::vector<std::string> ignored_files;
120 if (gitignore.good()) {
122 while (std::getline(gitignore, line)) {
123 if (line[0] ==
'#') {
126 if (line[0] ==
'!') {
130 ignored_files.push_back(line);
135 current_folder.
name = folder;
139 for (
const auto& subfolder :
142 folder_item.
name = subfolder;
143 std::string full_folder = current_folder.
name +
"/" + subfolder;
145 for (
const auto& files : folder_files) {
147 if (absl::StrContains(files,
'/')) {
151 if (!absl::StrContains(files,
'.')) {
154 if (std::ranges::find(ignored_files, files) != ignored_files.end()) {
157 folder_item.
files.push_back(files);
160 for (
const auto& subdir :
163 subfolder_item.
name = subdir;
165 folder_item.
subfolders.push_back(subfolder_item);
167 current_folder.
subfolders.push_back(folder_item);
170 return current_folder;
184 return absl::OkStatus();
192 ImGui::Begin(
"Assembly Editor", &is_loaded);
193 if (ImGui::BeginMenuBar()) {
200 ImGui::Text(
"%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
213 ImGui::Text(
"%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
229 bool file_browser_open =
true;
230 if (file_browser_card.
Begin(&file_browser_open)) {
234 if (ImGui::Button(
"Open Folder")) {
239 file_browser_card.
End();
250 if (file_id >=
files_.size()) {
259 if (file_card.
Begin()) {
260 if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)) {
263 open_files_[file_id].Render(absl::StrCat(
"##", card_name).c_str());
278 return absl::OkStatus();
280 return absl::FailedPreconditionError(
"No active file to save.");
298 if (ImGui::BeginChild(
"##current_folder", ImVec2(0, 0),
true,
299 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
300 if (ImGui::BeginTable(
"##file_table", 2,
301 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
302 ImGuiTableFlags_Resizable |
303 ImGuiTableFlags_Sortable)) {
304 ImGui::TableSetupColumn(
"Name", ImGuiTableColumnFlags_WidthFixed, 256.0f);
305 ImGui::TableSetupColumn(
"Type", ImGuiTableColumnFlags_WidthStretch);
307 ImGui::TableHeadersRow();
310 ImGui::TableNextRow();
311 ImGui::TableNextColumn();
312 if (ImGui::Selectable(file.c_str())) {
315 ImGui::TableNextColumn();
320 ImGui::TableNextRow();
321 ImGui::TableNextColumn();
322 if (ImGui::TreeNode(subfolder.name.c_str())) {
323 for (
const auto& file : subfolder.files) {
324 ImGui::TableNextRow();
325 ImGui::TableNextColumn();
326 if (ImGui::Selectable(file.c_str())) {
328 subfolder.name,
"/", file));
330 ImGui::TableNextColumn();
335 ImGui::TableNextColumn();
336 ImGui::Text(
"Folder");
349 if (ImGui::BeginMenu(
"File")) {
350 if (ImGui::MenuItem(
"Open",
"Ctrl+O")) {
354 if (ImGui::MenuItem(
"Save",
"Ctrl+S")) {
362 if (ImGui::BeginMenu(
"Edit")) {
363 if (ImGui::MenuItem(
"Undo",
"Ctrl+Z")) {
366 if (ImGui::MenuItem(
"Redo",
"Ctrl+Y")) {
370 if (ImGui::MenuItem(
"Cut",
"Ctrl+X")) {
373 if (ImGui::MenuItem(
"Copy",
"Ctrl+C")) {
376 if (ImGui::MenuItem(
"Paste",
"Ctrl+V")) {
380 if (ImGui::MenuItem(
"Find",
"Ctrl+F")) {
391 if (
files_[file_id] == filename) {
398 int new_file_id =
files_.size();
399 files_.push_back(std::string(filename));
409 if (!content.empty()) {
411 open_files_[new_file_id].SetLanguageDefinition(GetAssemblyLanguageDef());
414 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error opening file: %s\n",
415 std::string(filename).c_str());
421 return absl::OkStatus();
426 return absl::OkStatus();
431 return absl::OkStatus();
436 return absl::OkStatus();
441 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
std::string MakeCardTitle(const std::string &base_title) const
static EditorCardManager & Get()
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
TextEditor::LanguageDefinition GetAssemblyLanguageDef()
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)
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
std::vector< FolderItem > subfolders
std::vector< std::string > files