diff --git a/CodeLite/clEditorConfig.cpp b/CodeLite/clEditorConfig.cpp index 15ffcca947..29f894c399 100644 --- a/CodeLite/clEditorConfig.cpp +++ b/CodeLite/clEditorConfig.cpp @@ -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()) { @@ -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 @@ -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) { diff --git a/CodeLite/clEditorConfig.h b/CodeLite/clEditorConfig.h index 9c564d5422..c1940d93a0 100644 --- a/CodeLite/clEditorConfig.h +++ b/CodeLite/clEditorConfig.h @@ -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 Vec_t; clEditorConfigSection() @@ -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; @@ -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) { @@ -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) { @@ -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; } }; @@ -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 diff --git a/EditorConfigPlugin/EditorConfigCache.cpp b/EditorConfigPlugin/EditorConfigCache.cpp new file mode 100644 index 0000000000..03d7deeff9 --- /dev/null +++ b/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(); } diff --git a/EditorConfigPlugin/EditorConfigCache.h b/EditorConfigPlugin/EditorConfigCache.h new file mode 100644 index 0000000000..f6c0d6abb9 --- /dev/null +++ b/EditorConfigPlugin/EditorConfigCache.h @@ -0,0 +1,38 @@ +#ifndef EDITORCONFIGCACHE_H +#define EDITORCONFIGCACHE_H + +#include +#include "clEditorConfig.h" +#include + +class EditorConfigCache +{ +private: + struct CachedItem { + clEditorConfigSection section; + time_t lastModified; + }; + + std::map 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 diff --git a/EditorConfigPlugin/EditorConfigPlugin.project b/EditorConfigPlugin/EditorConfigPlugin.project index d74294abb4..712eeb3039 100644 --- a/EditorConfigPlugin/EditorConfigPlugin.project +++ b/EditorConfigPlugin/EditorConfigPlugin.project @@ -2,6 +2,8 @@ + + @@ -38,12 +40,12 @@ copy "$(IntermediateDirectory)\EditorConfigPlugin-dbg.dll" ..\Runtime\plugins - - + + - - + + @@ -73,12 +75,12 @@ copy "$(IntermediateDirectory)\EditorConfigPlugin.dll" ..\Runtime\plugins - - + + - - + + diff --git a/EditorConfigPlugin/editorconfigplugin.cpp b/EditorConfigPlugin/editorconfigplugin.cpp index a16897b5b7..44ba23f3ae 100644 --- a/EditorConfigPlugin/editorconfigplugin.cpp +++ b/EditorConfigPlugin/editorconfigplugin.cpp @@ -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() {} @@ -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; } diff --git a/EditorConfigPlugin/editorconfigplugin.h b/EditorConfigPlugin/editorconfigplugin.h index 2684952a6a..dd42a0c0f7 100644 --- a/EditorConfigPlugin/editorconfigplugin.h +++ b/EditorConfigPlugin/editorconfigplugin.h @@ -3,28 +3,37 @@ #include "plugin.h" #include "cl_command_event.h" +#include "EditorConfigCache.h" +#include +#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 diff --git a/LiteEditor.workspace b/LiteEditor.workspace index 8ed0238566..0fb55e88b1 100644 --- a/LiteEditor.workspace +++ b/LiteEditor.workspace @@ -271,7 +271,7 @@ - + @@ -374,7 +374,7 @@ WXCFG=gcc_dll\mswu - + diff --git a/LiteEditor/LiteEditor.project b/LiteEditor/LiteEditor.project index ea73a3a457..2f1b881642 100644 --- a/LiteEditor/LiteEditor.project +++ b/LiteEditor/LiteEditor.project @@ -1227,133 +1227,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2087,4 +1960,134 @@ resources.cpp: resources.xrc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +