Skip to content

Commit

Permalink
EditorConfig plugin: cache the .editorconfig parsed for future use
Browse files Browse the repository at this point in the history
EditorConfig plugin: changes are applied once the .editorconfig is saved, there is no need to reload the file being edited for the changes
 to take place
  • Loading branch information
eranif committed Dec 2, 2016
1 parent 34308fd commit 4a23109
Show file tree
Hide file tree
Showing 9 changed files with 298 additions and 160 deletions.
10 changes: 6 additions & 4 deletions CodeLite/clEditorConfig.cpp
Expand Up @@ -11,9 +11,9 @@ clEditorConfig::clEditorConfig()

clEditorConfig::~clEditorConfig() {}

bool clEditorConfig::LoadForFile(const wxFileName& filename)
bool clEditorConfig::LoadForFile(const wxFileName& filename, wxFileName& editorConfigFile)
{
wxFileName editorConfigFile(filename.GetPath(), ".editorconfig");
editorConfigFile= wxFileName(filename.GetPath(), ".editorconfig");

bool foundFile = false;
while(editorConfigFile.GetDirCount()) {
Expand All @@ -35,7 +35,7 @@ bool clEditorConfig::LoadForFile(const wxFileName& filename)
clEditorConfigSection section;
m_sections.push_back(section);
clEditorConfigSection* cursection = &(m_sections.back());

wxUnusedVar(cursection); // for debug purposes
wxArrayString lines = ::wxStringTokenize(content, "\n", wxTOKEN_STRTOK);
for(size_t i = 0; i < lines.size(); ++i) {
// Remove comments
Expand Down Expand Up @@ -296,8 +296,10 @@ bool clEditorConfig::ReadUntil(wxChar delim, wxString& strLine, wxString& output

bool clEditorConfig::GetSectionForFile(const wxFileName& filename, clEditorConfigSection& section)
{
if(!LoadForFile(filename)) return false;
wxFileName editorConfigFile;
if(!LoadForFile(filename, editorConfigFile)) return false;
section = clEditorConfigSection();
section.filename = editorConfigFile;
bool match_found = false;
std::for_each(m_sections.begin(), m_sections.end(), [&](const clEditorConfigSection& sec) {
for(size_t i = 0; i < sec.patterns.size(); ++i) {
Expand Down
22 changes: 16 additions & 6 deletions CodeLite/clEditorConfig.h
Expand Up @@ -30,7 +30,7 @@ class WXDLLIMPEXP_CL clEditorConfigSection
bool trim_trailing_whitespace;
bool insert_final_newline;
wxString end_of_line;

wxFileName filename; // the path to the .editorconfig file
typedef std::vector<clEditorConfigSection> Vec_t;

clEditorConfigSection()
Expand All @@ -43,6 +43,9 @@ class WXDLLIMPEXP_CL clEditorConfigSection
, insert_final_newline(false)
{
}
void SetFilename(const wxFileName& filename) {this->filename = filename;}
const wxFileName& GetFilename() const {return filename;}

void SetCharset(const wxString& charset)
{
this->charset = charset;
Expand All @@ -55,7 +58,7 @@ class WXDLLIMPEXP_CL clEditorConfigSection
this->indent_size = indent_size;
this->flags |= kIndentSizeSet;
}
bool IsIndentSizeSet() const { return this->flags & kIndentSizeSet; }
bool IsIndentSizeSet() const { return (this->flags & kTabWidthSet) || (this->flags & kIndentSizeSet); }

void SetIndentStyle(const wxString& indent_style)
{
Expand All @@ -76,7 +79,7 @@ class WXDLLIMPEXP_CL clEditorConfigSection
this->tab_width = tab_width;
this->flags |= kTabWidthSet;
}
bool IsTabWidthSet() const { return this->flags & kTabWidthSet; }
bool IsTabWidthSet() const { return (this->flags & kTabWidthSet) || (this->flags & kIndentSizeSet); }

void SetTrimTrailingWhitespace(bool trim_trailing_whitespace)
{
Expand All @@ -93,10 +96,17 @@ class WXDLLIMPEXP_CL clEditorConfigSection
bool IsSetEndOfLineSet() const { return this->flags & kEOLStyleSet; }

const wxString& GetCharset() const { return charset; }
size_t GetIndentSize() const { return indent_size; }
// According to the docs:
// When set to tab, the value of tab_width (if specified) will be used
size_t GetIndentSize() const
{
return (GetIndentStyle() == "tab" && (this->flags & kTabWidthSet)) ? tab_width : indent_size;
}

// If user set the tab_width, return its value, otherwise return the size of the indent size
size_t GetTabWidth() const { return (this->flags & kTabWidthSet) ? tab_width : indent_size; }
const wxString& GetIndentStyle() const { return indent_style; }
bool IsInsertFinalNewline() const { return insert_final_newline; }
size_t GetTabWidth() const { return tab_width; }
bool IsTrimTrailingWhitespace() const { return trim_trailing_whitespace; }
const wxString& GetEndOfLine() const { return end_of_line; }
};
Expand All @@ -119,7 +129,7 @@ class WXDLLIMPEXP_CL clEditorConfig
* @brief try and load a .editorconfig settings for 'filename'. We start looking from the current file location
* and going up until we hit the root folder
*/
bool LoadForFile(const wxFileName& filename);
bool LoadForFile(const wxFileName& filename, wxFileName& editorConfigFile);

/**
* @brief find the best section for a file
Expand Down
38 changes: 38 additions & 0 deletions EditorConfigPlugin/EditorConfigCache.cpp
@@ -0,0 +1,38 @@
#include "EditorConfigCache.h"
#include "fileutils.h"

EditorConfigCache::EditorConfigCache() {}

EditorConfigCache::~EditorConfigCache() {}

bool EditorConfigCache::Get(const wxFileName& filename, clEditorConfigSection& section)
{
wxString key = filename.GetFullPath();
if(m_map.count(key) == 0) return false;

CachedItem& entry = m_map[key];
time_t lastModTimeOnDisk = FileUtils::GetFileModificationTime(entry.section.GetFilename());
if(lastModTimeOnDisk != entry.lastModified) {
// remove this entry and return false
m_map.erase(key);
return false;
}

section = entry.section;
return true;
}

void EditorConfigCache::Add(const wxFileName& filename, const clEditorConfigSection& section)
{
wxString key = filename.GetFullPath();
if(m_map.count(key)) {
m_map.erase(key);
}

CachedItem entry;
entry.lastModified = FileUtils::GetFileModificationTime(section.GetFilename());
entry.section = section;
m_map.insert(std::make_pair(key, entry));
}

void EditorConfigCache::Clear() { m_map.clear(); }
38 changes: 38 additions & 0 deletions EditorConfigPlugin/EditorConfigCache.h
@@ -0,0 +1,38 @@
#ifndef EDITORCONFIGCACHE_H
#define EDITORCONFIGCACHE_H

#include <wx/filename.h>
#include "clEditorConfig.h"
#include <map>

class EditorConfigCache
{
private:
struct CachedItem {
clEditorConfigSection section;
time_t lastModified;
};

std::map<wxString, CachedItem> m_map;

public:
EditorConfigCache();
virtual ~EditorConfigCache();

/**
* @brief find cached item for given filename
*/
bool Get(const wxFileName& filename, clEditorConfigSection& section);

/**
* @brief add entry to the cache
*/
void Add(const wxFileName& filename, const clEditorConfigSection& section);

/**
* @brief clear the cache
*/
void Clear();
};

#endif // EDITORCONFIGCACHE_H
18 changes: 10 additions & 8 deletions EditorConfigPlugin/EditorConfigPlugin.project
Expand Up @@ -2,6 +2,8 @@
<CodeLite_Project Name="EditorConfigPlugin">
<VirtualDirectory Name="src">
<File Name="editorconfigplugin.cpp"/>
<File Name="EditorConfigCache.h"/>
<File Name="EditorConfigCache.cpp"/>
</VirtualDirectory>
<VirtualDirectory Name="include">
<File Name="editorconfigplugin.h"/>
Expand Down Expand Up @@ -38,12 +40,12 @@
<Command Enabled="yes">copy "$(IntermediateDirectory)\EditorConfigPlugin-dbg.dll" ..\Runtime\plugins</Command>
</PostBuild>
<CustomBuild Enabled="no">
<CleanCommand></CleanCommand>
<BuildCommand></BuildCommand>
<CleanCommand/>
<BuildCommand/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild></CustomPostBuild>
<CustomPreBuild></CustomPreBuild>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
</Configuration>
<Configuration Name="Win_x64_Release" CompilerType="g++-64" DebuggerType="GNU gdb debugger">
Expand Down Expand Up @@ -73,12 +75,12 @@
<Command Enabled="yes">copy "$(IntermediateDirectory)\EditorConfigPlugin.dll" ..\Runtime\plugins</Command>
</PostBuild>
<CustomBuild Enabled="no">
<CleanCommand></CleanCommand>
<BuildCommand></BuildCommand>
<CleanCommand/>
<BuildCommand/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild></CustomPostBuild>
<CustomPreBuild></CustomPreBuild>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
</Configuration>
</Settings>
Expand Down
48 changes: 42 additions & 6 deletions EditorConfigPlugin/editorconfigplugin.cpp
Expand Up @@ -35,6 +35,7 @@ EditorConfigPlugin::EditorConfigPlugin(IManager* manager)

// Bind events
EventNotifier::Get()->Bind(wxEVT_EDITOR_CONFIG_LOADING, &EditorConfigPlugin::OnEditorConfigLoading, this);
EventNotifier::Get()->Bind(wxEVT_ACTIVE_EDITOR_CHANGED, &EditorConfigPlugin::OnActiveEditorChanged, this);
}

EditorConfigPlugin::~EditorConfigPlugin() {}
Expand All @@ -51,18 +52,53 @@ void EditorConfigPlugin::CreatePluginMenu(wxMenu* pluginsMenu) {}
void EditorConfigPlugin::UnPlug()
{
EventNotifier::Get()->Unbind(wxEVT_EDITOR_CONFIG_LOADING, &EditorConfigPlugin::OnEditorConfigLoading, this);
EventNotifier::Get()->Unbind(wxEVT_ACTIVE_EDITOR_CHANGED, &EditorConfigPlugin::OnActiveEditorChanged, this);
}

void EditorConfigPlugin::OnEditorConfigLoading(clEditorConfigEvent& event)
{
// TODO: cache the results
event.Skip();
clEditorConfig conf;
clEditorConfigSection section;
wxFileName fn(event.GetFileName());
if(!fn.IsOk() || !fn.FileExists()) return;
if(conf.GetSectionForFile(event.GetFileName(), section)) {
event.Skip(false);
event.SetEditorConfig(section);
if(!DoGetEditorConfigForFile(fn, section)) {
return;
}

event.Skip(false);
event.SetEditorConfig(section);
}

void EditorConfigPlugin::OnActiveEditorChanged(wxCommandEvent& event)
{
event.Skip();
IEditor* editor = m_mgr->GetActiveEditor();
CHECK_PTR_RET(editor);

OptionsConfigPtr conf = editor->GetOptions();
CHECK_PTR_RET(conf);

clEditorConfigSection section;
if(!DoGetEditorConfigForFile(editor->GetFileName(), section)) return;
conf->UpdateFromEditorConfig(section);
editor->ApplyEditorConfig();
}

bool EditorConfigPlugin::DoGetEditorConfigForFile(const wxFileName& filename, clEditorConfigSection& section)
{
// Try the cache first
if(m_cache.Get(filename, section)) {
return true;
}

// Sanity
if(!filename.IsOk() || !filename.FileExists()) return false;

clEditorConfig conf;
if(!conf.GetSectionForFile(filename, section)) {
// Update the cache
return false;
}

m_cache.Add(filename, section);
return true;
}
23 changes: 16 additions & 7 deletions EditorConfigPlugin/editorconfigplugin.h
Expand Up @@ -3,28 +3,37 @@

#include "plugin.h"
#include "cl_command_event.h"
#include "EditorConfigCache.h"
#include <wx/filename.h>
#include "clEditorConfig.h"

class EditorConfigPlugin : public IPlugin
{
EditorConfigCache m_cache;

protected:
bool DoGetEditorConfigForFile(const wxFileName& filename, clEditorConfigSection& section);

public:
EditorConfigPlugin(IManager *manager);
EditorConfigPlugin(IManager* manager);
~EditorConfigPlugin();

//--------------------------------------------
//Abstract methods
// Abstract methods
//--------------------------------------------
virtual clToolBar *CreateToolBar(wxWindow *parent);
virtual clToolBar* CreateToolBar(wxWindow* parent);
/**
* @brief Add plugin menu to the "Plugins" menu item in the menu bar
*/
virtual void CreatePluginMenu(wxMenu *pluginsMenu);
virtual void CreatePluginMenu(wxMenu* pluginsMenu);

/**
* @brief Unplug the plugin. Perform here any cleanup needed (e.g. unbind events, destroy allocated windows)
*/
virtual void UnPlug();

void OnEditorConfigLoading(clEditorConfigEvent& event);
void OnActiveEditorChanged(wxCommandEvent& event);
};

#endif //EditorConfigPlugin
#endif // EditorConfigPlugin
4 changes: 2 additions & 2 deletions LiteEditor.workspace
Expand Up @@ -271,7 +271,7 @@
<Project Name="Tail" ConfigName="Win_x64_Debug"/>
<Project Name="EditorConfigPlugin" ConfigName="Win_x64_Debug"/>
</WorkspaceConfiguration>
<WorkspaceConfiguration Name="OSX_Release" Selected="yes">
<WorkspaceConfiguration Name="OSX_Release" Selected="no">
<Environment/>
<Project Name="ZoomNavigator" ConfigName="DebugUnicode"/>
<Project Name="wxsqlite3" ConfigName="Win_x86_Release"/>
Expand Down Expand Up @@ -374,7 +374,7 @@ WXCFG=gcc_dll\mswu</Environment>
<Project Name="ZoomNavigator" ConfigName="Win_x64_Release"/>
<Project Name="EditorConfigPlugin" ConfigName="Win_x64_Release"/>
</WorkspaceConfiguration>
<WorkspaceConfiguration Name="Win_x64_Debug" Selected="yes">
<WorkspaceConfiguration Name="Win_x64_Debug" Selected="no">
<Environment/>
<Project Name="abbreviation" ConfigName="Win_x64_Debug"/>
<Project Name="AutoSave" ConfigName="Win_x64_Debug"/>
Expand Down

0 comments on commit 4a23109

Please sign in to comment.