Skip to content

Commit

Permalink
Merge pull request #356 from Genio-The-Haiku-IDE/feature/editorconfig
Browse files Browse the repository at this point in the history
Add support for .editorconfig
  • Loading branch information
nexus6-haiku authored Apr 23, 2024
2 parents e766544 + ae583ba commit 8dba593
Show file tree
Hide file tree
Showing 12 changed files with 240 additions and 35 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
#end_of_line = lf
#insert_final_newline = true
indent_style = tab
indent_size = 4
5 changes: 5 additions & 0 deletions Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
v3.x
- Improved support for OmniSharp with multiple Code Actions
- Rename symbols across multiple files
- Class Outline
---
v2.1
- Added user documentation (courtesy of Humdinger).
- UI: Improved the tab close button position and size.
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ LIBS += columnlistview tracker
LIBS += git2
LIBS += src/scintilla/bin/libscintilla.a
LIBS += yaml-cpp
LIBS += editorconfig

SYSTEM_INCLUDE_PATHS = $(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/interface)
SYSTEM_INCLUDE_PATHS += $(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/shared)
Expand Down
14 changes: 8 additions & 6 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Some of the features of the Genio IDE are:
* Integrated source control with GIT (including opening a remote project)
* Find in files
* Links to file and build errors in Build Log and Console I/O
* Symbols outline view
* Symbols outline view
* "Problems" tab
* Build on save / Save on build
* User templates for quickly creating new files and projects
Expand Down Expand Up @@ -64,10 +64,12 @@ For more advanced IDE features, Genio implements the LSP protocol. (<https://mic
### Prerequirements

Genio requires Scintilla and Lexilla to implement various functionalities.
It also requires libgit2 to implement Git features and libyaml_cpp to read yaml files.
The needed development files are available in `libgit2_devel`, `lexilla_devel` and
`yaml_cpp_devel`, respectively.
Execute `pkgman install libgit2_devel lexilla_devel yaml_cpp_devel` from Terminal.
It also requires libgit2 to implement Git features, libyaml_cpp to read yaml files and
editorconfig_core_c to provide support for project wide .editorconfig settings.
The needed development files are available in `libgit2_devel`, `lexilla_devel`, `yaml_cpp_devel`,
and `editorconfig_core_c_devel` respectively.
Execute `pkgman install libgit2_devel lexilla_devel yaml_cpp_devel editorconfig_core_c_devel`
from Terminal.

If you would like to try a clang++ build:

Expand All @@ -94,5 +96,5 @@ We (try to) stick to the Haiku style for code, although with a few differences.
## License

Genio is available under the MIT license. See [License.md](License.md).
Outline LSP icons are taken from Visual Studio Code and released under Creative Commons license.
Outline LSP icons are taken from Visual Studio Code and released under Creative Commons license.
See [Visual Studio Code - Icons](https://github.com/microsoft/vscode-icons)
3 changes: 3 additions & 0 deletions src/GenioApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,13 @@ GenioApp::_PrepareConfig(ConfigManager& cfg)
cfg.AddConfig(editor.String(), "syntax_highlight", B_TRANSLATE("Enable syntax highlighting"), true);
cfg.AddConfig(editor.String(), "brace_match", B_TRANSLATE("Enable brace matching"), true);
cfg.AddConfig(editor.String(), "save_caret", B_TRANSLATE("Save caret position"), true);
cfg.AddConfig(editor.String(), "ignore_editorconfig", B_TRANSLATE("Ignore .editorconfig"), false);
cfg.AddConfig(editor.String(), "trim_trailing_whitespace", B_TRANSLATE("Trim trailing whitespace on save"), false);
// TODO: change to "indent_style" to be coherent with editorconfig
cfg.AddConfig(editor.String(), "tab_to_space", B_TRANSLATE("Convert tabs to spaces"), false);

GMessage tabs = { {"min",1},{"max",8} };
// TODO: change to "indent_size" to be coherent with editorconfig
cfg.AddConfig(editor.String(), "tab_width", B_TRANSLATE("Tab width:"), 4, &tabs);

GMessage zooms = { {"min", -9}, {"max", 19} };
Expand Down
130 changes: 111 additions & 19 deletions src/ui/Editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <Catalog.h>
#include <Control.h>
#include <ControlLook.h>
#include <editorconfig/editorconfig.h>
#include <ILexer.h>
#include <Lexilla.h>
#include <NodeMonitor.h>
Expand All @@ -24,6 +25,7 @@
#include <Url.h>
#include <Volume.h>

#include "ActionManager.h"
#include "ConfigManager.h"
#include "EditorContextMenu.h"
#include "EditorMessages.h"
Expand Down Expand Up @@ -77,6 +79,8 @@ Editor::Editor(entry_ref* ref, const BMessenger& target)

fLSPEditorWrapper = new LSPEditorWrapper(BPath(&fFileRef), this);

LoadEditorConfig();

// MARGINS
SendMessage(SCI_SETMARGINS, 4, UNSET);

Expand Down Expand Up @@ -358,9 +362,14 @@ Editor::ApplySettings()
ShowWhiteSpaces(gCFG["show_white_space"]);
ShowLineEndings(gCFG["show_line_endings"]);

SendMessage(SCI_SETTABWIDTH, (int) gCFG["tab_width"], 0);
SendMessage(SCI_SETUSETABS, !(bool)gCFG["tab_to_space"], 0);
// FIXME: understand fEditor->SendMessage(SCI_SETINDENT, 0, 0);
// editorconfig
SendMessage(SCI_SETUSETABS, fEditorConfig.IndentStyle==IndentStyle::Tab, 0);
SendMessage(SCI_SETTABWIDTH, fEditorConfig.IndentSize, 0);
SendMessage(SCI_SETINDENT, 0, 0);
if (fEditorConfig.TrimTrailingWhitespace)
TrimTrailingWhitespace();
EndOfLineConvert(fEditorConfig.EndOfLine);

SendMessage(SCI_SETCARETLINEVISIBLE, bool(gCFG["mark_caretline"]), 0);
SendMessage(SCI_SETCARETLINEVISIBLEALWAYS, true, 0);
// TODO add settings: SendMessage(SCI_SETCARETLINEFRAME, fPreferences->fLineHighlightingMode ? 2
Expand Down Expand Up @@ -401,6 +410,8 @@ Editor::ApplySettings()

// custom ContextMenu!
SendMessage(SCI_USEPOPUP, SC_POPUP_NEVER, 0);

UpdateStatusBar();
}

void
Expand Down Expand Up @@ -459,22 +470,25 @@ Editor::BookmarkToggle(int position)
void
Editor::TrimTrailingWhitespace()
{
Sci::Guard<SearchTarget, SearchFlags> guard(this);

Sci_Position length = SendMessage(SCI_GETLENGTH, 0, 0);
Set<SearchTarget>({0, length});
Set<SearchFlags>(SCFIND_REGEXP | SCFIND_CXX11REGEX);

Sci::UndoAction action(this);
const std::string whitespace = "\\s+$";
int result;
do {
result = SendMessage(SCI_SEARCHINTARGET, whitespace.size(), (sptr_t)whitespace.c_str());
if (result != -1) {
SendMessage(SCI_REPLACETARGET, -1, (sptr_t)"");
Set<SearchTarget>({Get<SearchTargetEnd>(), length});
}
} while(result != -1);
if ((gCFG["ignore_editorconfig"] && gCFG["trim_trailing_whitespace"])
|| fEditorConfig.TrimTrailingWhitespace) {
Sci::Guard<SearchTarget, SearchFlags> guard(this);

Sci_Position length = SendMessage(SCI_GETLENGTH, 0, 0);
Set<SearchTarget>({0, length});
Set<SearchFlags>(SCFIND_REGEXP | SCFIND_CXX11REGEX);

Sci::UndoAction action(this);
const std::string whitespace = "\\s+$";
int result;
do {
result = SendMessage(SCI_SEARCHINTARGET, whitespace.size(), (sptr_t)whitespace.c_str());
if (result != -1) {
SendMessage(SCI_REPLACETARGET, -1, (sptr_t)"");
Set<SearchTarget>({Get<SearchTargetEnd>(), length});
}
} while(result != -1);
}
}


Expand Down Expand Up @@ -795,6 +809,80 @@ Editor::IsTextSelected()
}


void
Editor::LoadEditorConfig()
{
fEditorConfig.EndOfLine = EndOfLine();
fEditorConfig.IndentStyle = (bool)gCFG["tab_to_space"] ? IndentStyle::Space : IndentStyle::Tab;
fEditorConfig.IndentSize = (int)gCFG["tab_width"];
fEditorConfig.TrimTrailingWhitespace = (bool)gCFG["trim_trailing_whitespace"];
fHasEditorConfig = false;

if (!(bool)gCFG["ignore_editorconfig"]) {
// start parsing
// Ignore full path error, whose error code is EDITORCONFIG_PARSE_NOT_FULL_PATH
editorconfig_handle handle = editorconfig_handle_init();
int errNum;
if ((errNum = editorconfig_parse(FilePath().String(), handle)) != 0 &&
errNum != EDITORCONFIG_PARSE_NOT_FULL_PATH) {
editorconfig_handle_destroy(handle);
LogError("Can't load .editorconfig with error %d", editorconfig_get_error_msg(errNum));
fHasEditorConfig = false;
} else {

fHasEditorConfig = true;

int32 i;
int32 nameValueCount;

nameValueCount = editorconfig_handle_get_name_value_count(handle);

/* get settings */
int32 tabWidth;
for (i = 0; i < nameValueCount; ++i) {
const char* name;
const char* value;

editorconfig_handle_get_name_value(handle, i, &name, &value);

if (!strcmp(name, "indent_style")) {
fEditorConfig.IndentStyle = !strcmp(value, "space") ? IndentStyle::Space : IndentStyle::Tab;
} else if (!strcmp(name, "tab_width")) {
if (strcmp(value, "undefine")) {
tabWidth = atoi(value);
}
} else if (!strcmp(name, "indent_size")) {
if (strcmp(value, "undefine")) {
int value_i = atoi(value);
if (!strcmp(value, "tab"))
fEditorConfig.IndentSize = tabWidth;
else if (value_i > 0)
fEditorConfig.IndentSize = value_i;
}
} else if (!strcmp(name, "end_of_line")) {
if (strcmp(value, "undefine")) {
if (!strcmp(value, "lf"))
fEditorConfig.EndOfLine = SC_EOL_LF;
else if (!strcmp(value, "cr"))
fEditorConfig.EndOfLine = SC_EOL_CR;
else if (!strcmp(value, "crlf"))
fEditorConfig.EndOfLine = SC_EOL_CRLF;
}
} else if (!strcmp(name, "trim_trailing_whitespace")) {
if (strcmp(value, "undefine")) {
fEditorConfig.TrimTrailingWhitespace = !strcmp(value, "true") ? true : false;
}
}
else if (!strcmp(name, "insert_final_newline"))
fEditorConfig.InsertFinalNewline = !strcmp(value, "true") ? true : false;
}

editorconfig_handle_destroy(handle);
}
}
}


/*
* Code (editable) taken from stylededit
*/
Expand Down Expand Up @@ -1331,6 +1419,10 @@ Editor::UpdateStatusBar()
update.AddString("overwrite", IsOverwriteString());//EndOfLineString());
update.AddString("readOnly", ModeString());
update.AddString("eol", _EndOfLineString());
update.AddString("editorconfig", fHasEditorConfig ? "\xF0\x9F\x97\x8E" : "\xF0\x9F\x8C\x90");
update.AddString("trim_trialing_whitespace", fEditorConfig.TrimTrailingWhitespace ? "TRIM" : "NOTRIM");
update.AddString("indent_style", fEditorConfig.IndentStyle == IndentStyle::Tab ? "TAB" : "SPACE");
update.AddInt32("indent_size", fEditorConfig.IndentSize);

fStatusView->SetStatus(&update);
}
Expand Down
22 changes: 19 additions & 3 deletions src/ui/Editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ enum {
EDITOR_UPDATE_SYMBOLS = 'symb'
};

enum IndentStyle {
Tab,
Space
};

/*
* Not very smart: NONE,SKIP,DONE are Status
* while the others are Function placeholders
Expand All @@ -60,6 +65,13 @@ constexpr auto sci_COMMENT_MARGIN = 3;

constexpr auto sci_BOOKMARK = 0; //Marker

struct EditorConfig {
enum IndentStyle IndentStyle;
int32 IndentSize;
int32 EndOfLine;
bool TrimTrailingWhitespace;
bool InsertFinalNewline; // Not implemented
};

class Editor : public BScintillaView {
public:
Expand All @@ -71,6 +83,7 @@ class Editor : public BScintillaView {
Editor(entry_ref* ref, const BMessenger& target);
~Editor();
virtual void MessageReceived(BMessage* message);
void LoadEditorConfig();
void ApplySettings();
void ApplyEdit(std::string info);
void TrimTrailingWhitespace();
Expand Down Expand Up @@ -106,8 +119,6 @@ class Editor : public BScintillaView {
node_ref *const NodeRef() { return &fNodeRef; }
bool IsOverwrite();



ssize_t SaveToFile();
status_t SetFileRef(entry_ref* ref);
void SetReadOnly(bool readOnly = true);
Expand All @@ -120,7 +131,6 @@ class Editor : public BScintillaView {
ProjectFolder* GetProjectFolder() const { return fProjectFolder; }
void Undo();


void SetProblems();

void SetDocumentSymbols(const BMessage* symbols);
Expand Down Expand Up @@ -175,6 +185,7 @@ class Editor : public BScintillaView {
void ShowWhiteSpaces(bool show);
bool LineEndingsVisible();
bool WhiteSpacesVisible();

void ScrollCaret();
void SelectAll();
const BString Selection();
Expand Down Expand Up @@ -248,6 +259,11 @@ class Editor : public BScintillaView {
BMessage fDocumentSymbols;
symbols_status fSymbolsStatus;
std::set<std::pair<std::string, int32> > fCollapsedSymbols;

// editorconfig
bool fHasEditorConfig;
EditorConfig fEditorConfig;

BMessageRunner* fIdleHandler;
};

Expand Down
47 changes: 44 additions & 3 deletions src/ui/EditorStatusView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,40 @@ StatusView::Draw(BRect updateRect)
}


void
StatusView::MouseMoved(BPoint where, uint32 transit, const BMessage* message)
{
if ((transit == B_ENTERED_VIEW) || (transit == B_INSIDE_VIEW)) {
BRect cellRect = _GetCellRect(kEditorConfig);
if (where.x < cellRect.right && where.x > cellRect.left) {
if (fCellText[kEditorConfig] == "\xF0\x9F\x97\x8E")
SetToolTip(B_TRANSLATE("Settings in .editorconfig applied"));
else
SetToolTip(B_TRANSLATE("Global settings applied"));
} else {
SetToolTip("");
}
}
}


BRect
StatusView::_GetCellRect(int32 cell)
{
BRect rect;
rect.bottom = Frame().bottom;
rect.top = Frame().top;

for (int32 i = 0; i < cell; i++) {
rect.left += fCellWidth[i];
}
rect.left += fNavigationButtonWidth;
rect.right = rect.left + fCellWidth[cell];

return rect;
}


void
StatusView::MouseDown(BPoint where)
{
Expand Down Expand Up @@ -191,9 +225,16 @@ StatusView::SetStatus(BMessage* message)
fCellText[kPositionCell].SetToFormat("%" B_PRIi32 ":%" B_PRIi32, line, column);
}

fCellText[kOverwriteMode] = message->GetString("overwrite", "");
fCellText[kLineFeed] = message->GetString("eol", "");
fCellText[kFileStateCell] = message->GetString("readOnly", "");
fCellText[kOverwriteMode] = message->GetString("overwrite", "");
fCellText[kLineFeed] = message->GetString("eol", "");
fCellText[kFileStateCell] = message->GetString("readOnly", "");
fCellText[kEditorConfig] = message->GetString("editorconfig", "");
fCellText[kTrimWhitespace] = message->GetString("trim_trialing_whitespace", "");

BString style = message->GetString("indent_style", "");
int32 size = message->GetInt32("indent_size", -1);

fCellText[kIndent].SetToFormat("%s:%" B_PRIi32, style.String(), size);

Invalidate();
}
Expand Down
Loading

0 comments on commit 8dba593

Please sign in to comment.