Browse Source

Added source.auto_reload_changed_files preference item, and support for prettier. Also made some various minor fixes

merge-requests/382/head
eidheim 8 years ago
parent
commit
bf798073c0
  1. 2
      CMakeLists.txt
  2. 1
      src/config.cc
  3. 1
      src/config.h
  4. 2
      src/directories.cc
  5. 1
      src/files.h
  6. 3
      src/git.cc
  7. 97
      src/source.cc
  8. 2
      src/source.h
  9. 129
      src/source_base.cc
  10. 11
      src/source_base.h
  11. 4
      src/source_clang.cc
  12. 1
      src/source_clang.h
  13. 18
      src/source_diff.cc
  14. 6
      src/source_diff.h
  15. 8
      src/source_language_protocol.cc
  16. 1
      src/source_language_protocol.h
  17. 7
      src/terminal.cc
  18. 2
      src/terminal.h
  19. 6
      src/window.cc

2
CMakeLists.txt

@ -1,7 +1,7 @@
cmake_minimum_required (VERSION 2.8.8) cmake_minimum_required (VERSION 2.8.8)
project(juci) project(juci)
set(JUCI_VERSION "1.4.1.2") set(JUCI_VERSION "1.4.1.3")
set(CPACK_PACKAGE_NAME "jucipp") set(CPACK_PACKAGE_NAME "jucipp")
set(CPACK_PACKAGE_CONTACT "Ole Christian Eidheim <eidheim@gmail.com>") set(CPACK_PACKAGE_CONTACT "Ole Christian Eidheim <eidheim@gmail.com>")

1
src/config.cc

@ -172,6 +172,7 @@ void Config::read(const boost::property_tree::ptree &cfg) {
source.highlight_current_line = source_json.get<bool>("highlight_current_line"); source.highlight_current_line = source_json.get<bool>("highlight_current_line");
source.show_line_numbers = source_json.get<bool>("show_line_numbers"); source.show_line_numbers = source_json.get<bool>("show_line_numbers");
source.enable_multiple_cursors = source_json.get<bool>("enable_multiple_cursors"); source.enable_multiple_cursors = source_json.get<bool>("enable_multiple_cursors");
source.auto_reload_changed_files = source_json.get<bool>("auto_reload_changed_files");
source.clang_format_style = source_json.get<std::string>("clang_format_style"); source.clang_format_style = source_json.get<std::string>("clang_format_style");
source.clang_usages_threads = static_cast<unsigned>(source_json.get<int>("clang_usages_threads")); source.clang_usages_threads = static_cast<unsigned>(source_json.get<int>("clang_usages_threads"));
auto pt_doc_search=cfg.get_child("documentation_searches"); auto pt_doc_search=cfg.get_child("documentation_searches");

1
src/config.h

@ -86,6 +86,7 @@ public:
bool highlight_current_line; bool highlight_current_line;
bool show_line_numbers; bool show_line_numbers;
bool enable_multiple_cursors; bool enable_multiple_cursors;
bool auto_reload_changed_files;
std::string clang_format_style; std::string clang_format_style;
unsigned clang_usages_threads; unsigned clang_usages_threads;

2
src/directories.cc

@ -507,7 +507,7 @@ void Directories::add_or_update_path(const boost::filesystem::path &dir_path, co
} }
if(path_it==directories.end()) { if(path_it==directories.end()) {
auto g_file=Glib::wrap(g_file_new_for_path(dir_path.string().c_str())); //TODO: report missing constructor in giomm auto g_file=Gio::File::create_for_path(dir_path.string());
auto monitor=g_file->monitor_directory(Gio::FileMonitorFlags::FILE_MONITOR_WATCH_MOVES); auto monitor=g_file->monitor_directory(Gio::FileMonitorFlags::FILE_MONITOR_WATCH_MOVES);
auto path_and_row=std::make_shared<std::pair<boost::filesystem::path, Gtk::TreeModel::Row> >(dir_path, row); auto path_and_row=std::make_shared<std::pair<boost::filesystem::path, Gtk::TreeModel::Row> >(dir_path, row);
auto connection=std::make_shared<sigc::connection>(); auto connection=std::make_shared<sigc::connection>();

1
src/files.h

@ -59,6 +59,7 @@ R"RAW(
"highlight_current_line": true, "highlight_current_line": true,
"show_line_numbers": true, "show_line_numbers": true,
"enable_multiple_cursors": false, "enable_multiple_cursors": false,
"auto_reload_changed_files": false,
"clang_format_style_comment": "IndentWidth, AccessModifierOffset and UseTab are set automatically. See http://clang.llvm.org/docs/ClangFormatStyleOptions.html", "clang_format_style_comment": "IndentWidth, AccessModifierOffset and UseTab are set automatically. See http://clang.llvm.org/docs/ClangFormatStyleOptions.html",
"clang_format_style": "ColumnLimit: 0, MaxEmptyLinesToKeep: 2, SpaceBeforeParens: Never, NamespaceIndentation: All, BreakBeforeBraces: Custom, BraceWrapping: {BeforeElse: true, BeforeCatch: true}", "clang_format_style": "ColumnLimit: 0, MaxEmptyLinesToKeep: 2, SpaceBeforeParens: Never, NamespaceIndentation: All, BreakBeforeBraces: Custom, BraceWrapping: {BeforeElse: true, BeforeCatch: true}",
"clang_usages_threads_comment": "The number of threads used in finding usages in unparsed files. -1 corresponds to the number of cores available, and 0 disables the search", "clang_usages_threads_comment": "The number of threads used in finding usages in unparsed files. -1 corresponds to the number of cores available, and 0 disables the search",

3
src/git.cc

@ -111,8 +111,7 @@ Git::Repository::Repository(const boost::filesystem::path &path) {
if(work_path.empty()) if(work_path.empty())
throw std::runtime_error("Could not find work path"); throw std::runtime_error("Could not find work path");
auto git_path_str=get_path().string(); auto git_directory=Gio::File::create_for_path(get_path().string());
auto git_directory=Glib::wrap(g_file_new_for_path(git_path_str.c_str())); //TODO: report missing constructor in giomm
monitor=git_directory->monitor_directory(Gio::FileMonitorFlags::FILE_MONITOR_WATCH_MOVES); monitor=git_directory->monitor_directory(Gio::FileMonitorFlags::FILE_MONITOR_WATCH_MOVES);
monitor_changed_connection=monitor->signal_changed().connect([this](const Glib::RefPtr<Gio::File> &file, monitor_changed_connection=monitor->signal_changed().connect([this](const Glib::RefPtr<Gio::File> &file,
const Glib::RefPtr<Gio::File>&, const Glib::RefPtr<Gio::File>&,

97
src/source.cc

@ -55,7 +55,7 @@ Glib::RefPtr<Gsv::Language> Source::guess_language(const boost::filesystem::path
language=language_manager->get_language("makefile"); language=language_manager->get_language("makefile");
else if(file_path.extension()==".tcc") else if(file_path.extension()==".tcc")
language=language_manager->get_language("cpphdr"); language=language_manager->get_language("cpphdr");
else if(file_path.extension()==".ts") else if(file_path.extension()==".ts" || file_path.extension()==".jsx")
language=language_manager->get_language("js"); language=language_manager->get_language("js");
else if(!file_path.has_extension()) { else if(!file_path.has_extension()) {
for(auto &part: file_path) { for(auto &part: file_path) {
@ -125,10 +125,6 @@ Source::View::View(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::L
non_deleted_views.emplace(this); non_deleted_views.emplace(this);
views.emplace(this); views.emplace(this);
load();
get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0));
search_settings = gtk_source_search_settings_new(); search_settings = gtk_source_search_settings_new();
gtk_source_search_settings_set_wrap_around(search_settings, true); gtk_source_search_settings_set_wrap_around(search_settings, true);
search_context = gtk_source_search_context_new(get_source_buffer()->gobj(), search_settings); search_context = gtk_source_search_context_new(get_source_buffer()->gobj(), search_settings);
@ -190,7 +186,96 @@ Source::View::View(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::L
set_tooltip_and_dialog_events(); set_tooltip_and_dialog_events();
if(language && (language->get_id()=="chdr" || language->get_id()=="cpphdr" || language->get_id()=="c" || static auto prettier = filesystem::find_executable("prettier");
if(!prettier.empty() && language &&
(language->get_id()=="js" || language->get_id()=="json" || language->get_id()=="css")) {
format_style=[this](bool continue_without_style_file) {
auto command=prettier.string()+" --cursor-offset "+std::to_string(get_buffer()->get_insert()->get_iter().get_offset());
command+=" --stdin-filepath "+this->file_path.string();
if(get_buffer()->get_has_selection()) {
Gtk::TextIter start, end;
get_buffer()->get_selection_bounds(start, end);
command+=" --range-start "+std::to_string(start.get_offset());
command+=" --range-end "+std::to_string(end.get_offset());
}
if(!continue_without_style_file) {
bool has_style_file=false;
auto style_file_search_path=this->file_path.parent_path();
while(true) {
if(boost::filesystem::exists(style_file_search_path/".prettierrc") ||
boost::filesystem::exists(style_file_search_path/"prettier.config")) {
has_style_file=true;
break;
}
if(style_file_search_path==style_file_search_path.root_directory())
break;
style_file_search_path=style_file_search_path.parent_path();
}
if(!has_style_file && !continue_without_style_file)
return;
}
std::stringstream stdin_stream(get_buffer()->get_text()), stdout_stream, stderr_stream;
auto exit_status=Terminal::get().process(stdin_stream, stdout_stream, command, this->file_path.parent_path(), &stderr_stream);
if(exit_status==0) {
replace_text(stdout_stream.str());
std::string line;
std::getline(stderr_stream, line);
if(line!="NaN") {
try {
auto offset=atoi(line.c_str());
if(offset<get_buffer()->size()) {
get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(offset));
hide_tooltips();
}
}
catch(...) {}
}
}
else {
// static std::regex regex("^\\[error\\] stdin: (.*) \\(([0-9]*):([0-9]*)\\)$");
// std::string line;
// std::getline(stderr_stream, line);
// std::smatch sm;
// if(std::regex_match(line, sm, regex)) {
// auto line=std::min(atoi(sm[1].str().c_str()), get_buffer()->get_line_count()-1); // TODO: add try
// if(line<0)
// line=0;
// auto iter=get_iter_at_line_end(line);
// auto pos=std::min(atoi(sm[2].str().c_str()), iter.get_line_offset()); // TODO: add try
// if(pos<0)
// pos=0;
// auto start=get_buffer()->get_iter_at_line_offset(line, pos);
// auto end=start;
// end.forward_char();
// if(start==end)
// start.forward_char();
// std::string diagnostic_tag_name="def:error";
// std::string severity_spelling="Error";
// auto spelling=sm[1].str();
// auto create_tooltip_buffer=[this, spelling, severity_spelling, diagnostic_tag_name]() {
// auto tooltip_buffer=Gtk::TextBuffer::create(get_buffer()->get_tag_table());
// tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), severity_spelling, diagnostic_tag_name);
// tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), ":\n"+spelling, "def:note");
// return tooltip_buffer;
// };
// diagnostic_tooltips.emplace_back(create_tooltip_buffer, this, get_buffer()->create_mark(start), get_buffer()->create_mark(end));
// get_buffer()->apply_tag_by_name(diagnostic_tag_name+"_underline", start, end);
// }
Terminal::get().print("Prettier:\n"+stderr_stream.str()+'\n', true); // TODO: consider using the above WiP code instead
}
};
}
else if(language && (language->get_id()=="chdr" || language->get_id()=="cpphdr" || language->get_id()=="c" ||
language->get_id()=="cpp" || language->get_id()=="objc" || language->get_id()=="java" || language->get_id()=="cpp" || language->get_id()=="objc" || language->get_id()=="java" ||
language->get_id()=="js" || language->get_id()=="ts" || language->get_id()=="proto" || language->get_id()=="js" || language->get_id()=="ts" || language->get_id()=="proto" ||
language->get_id()=="c-sharp" || language->get_id()=="html" || language->get_id()=="cuda" || language->get_id()=="c-sharp" || language->get_id()=="html" || language->get_id()=="cuda" ||

2
src/source.h

@ -94,7 +94,7 @@ namespace Source {
Tooltips diagnostic_tooltips; Tooltips diagnostic_tooltips;
Tooltips type_tooltips; Tooltips type_tooltips;
sigc::connection delayed_tooltips_connection; sigc::connection delayed_tooltips_connection;
virtual void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) {} virtual void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) { diagnostic_tooltips.show(rectangle); }
virtual void show_type_tooltips(const Gdk::Rectangle &rectangle) {} virtual void show_type_tooltips(const Gdk::Rectangle &rectangle) {}
gdouble on_motion_last_x=0.0; gdouble on_motion_last_x=0.0;
gdouble on_motion_last_y=0.0; gdouble on_motion_last_y=0.0;

129
src/source_base.cc

@ -2,28 +2,78 @@
#include "info.h" #include "info.h"
#include "terminal.h" #include "terminal.h"
#include "git.h" #include "git.h"
#include "config.h"
#include <fstream> #include <fstream>
Source::BaseView::BaseView(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language): file_path(file_path), language(language), status_diagnostics(0, 0, 0) { Source::BaseView::BaseView(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language): Gsv::View(), file_path(file_path), language(language), status_diagnostics(0, 0, 0) {
boost::system::error_code ec; load();
canonical_file_path=boost::filesystem::canonical(file_path, ec); get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0));
if(ec)
canonical_file_path=file_path;
last_write_time=boost::filesystem::last_write_time(file_path, ec);
if(ec)
last_write_time=static_cast<std::time_t>(-1);
signal_focus_in_event().connect([this](GdkEventFocus *event) { signal_focus_in_event().connect([this](GdkEventFocus *event) {
if(this->last_write_time!=static_cast<std::time_t>(-1))
check_last_write_time();
return false;
});
#ifdef __APPLE__ // TODO: Gio file monitor is bugged on MacOS
class Recursive {
public:
static void f(BaseView *view, std::time_t last_write_time_) {
view->delayed_monitor_changed_connection.disconnect();
view->delayed_monitor_changed_connection=Glib::signal_timeout().connect([view, last_write_time_]() {
boost::system::error_code ec;
auto last_write_time=boost::filesystem::last_write_time(view->file_path, ec);
if(last_write_time!=last_write_time_)
view->check_last_write_time(last_write_time);
Recursive::f(view, last_write_time);
return false;
}, 1000);
}
};
if(this->last_write_time!=static_cast<std::time_t>(-1))
Recursive::f(this, last_write_time);
#else
if(this->last_write_time!=static_cast<std::time_t>(-1)) {
monitor=Gio::File::create_for_path(file_path.string())->monitor_file(Gio::FileMonitorFlags::FILE_MONITOR_NONE);
monitor_changed_connection=monitor->signal_changed().connect([this](const Glib::RefPtr<Gio::File> &file,
const Glib::RefPtr<Gio::File>&,
Gio::FileMonitorEvent monitor_event) {
if(monitor_event!=Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) {
delayed_monitor_changed_connection.disconnect();
delayed_monitor_changed_connection=Glib::signal_timeout().connect([this]() {
check_last_write_time(); check_last_write_time();
return false; return false;
}, 500);
}
}); });
}
#endif
}
Source::BaseView::~BaseView() {
monitor_changed_connection.disconnect();
delayed_monitor_changed_connection.disconnect();
} }
bool Source::BaseView::load() { bool Source::BaseView::load() {
boost::system::error_code ec;
last_write_time=boost::filesystem::last_write_time(file_path, ec);
if(ec)
last_write_time=static_cast<std::time_t>(-1);
disable_spellcheck=true; disable_spellcheck=true;
get_source_buffer()->begin_not_undoable_action(); get_source_buffer()->begin_not_undoable_action();
bool status=true;
class Guard {
public:
Source::BaseView *view;
~Guard() {
view->get_source_buffer()->end_not_undoable_action();
view->disable_spellcheck=false;
}
};
Guard guard{this};
if(language) { if(language) {
std::ifstream input(file_path.string(), std::ofstream::binary); std::ifstream input(file_path.string(), std::ofstream::binary);
if(input) { if(input) {
@ -39,13 +89,17 @@ bool Source::BaseView::load() {
ustr.replace(iter, next_char_iter, "?"); ustr.replace(iter, next_char_iter, "?");
valid=false; valid=false;
} }
if(!valid)
Terminal::get().print("Warning: "+file_path.string()+" is not a valid UTF-8 file. Saving might corrupt the file.\n");
if(get_buffer()->size()==0) if(get_buffer()->size()==0)
get_buffer()->insert_at_cursor(ustr); get_buffer()->insert_at_cursor(ustr);
else else
replace_text(ustr.raw()); replace_text(ustr.raw());
}
if(!valid) else {
Terminal::get().print("Warning: "+file_path.string()+" is not a valid UTF-8 file. Saving might corrupt the file.\n"); return false;
} }
} }
else { else {
@ -55,30 +109,23 @@ bool Source::BaseView::load() {
ss << input.rdbuf(); ss << input.rdbuf();
Glib::ustring ustr=ss.str(); Glib::ustring ustr=ss.str();
bool valid=true;
if(ustr.validate()) { if(ustr.validate()) {
if(get_buffer()->size()==0) if(get_buffer()->size()==0)
get_buffer()->insert_at_cursor(ustr); get_buffer()->insert_at_cursor(ustr);
else else
replace_text(ustr.raw()); replace_text(ustr.raw());
} }
else else {
valid=false;
if(!valid)
Terminal::get().print("Error: "+file_path.string()+" is not a valid UTF-8 file.\n", true); Terminal::get().print("Error: "+file_path.string()+" is not a valid UTF-8 file.\n", true);
status=false; return false;
}
}
else {
return false;
} }
} }
get_source_buffer()->end_not_undoable_action();
disable_spellcheck=false;
boost::system::error_code ec;
last_write_time=boost::filesystem::last_write_time(file_path, ec);
if(ec)
last_write_time=static_cast<std::time_t>(-1);
return status; return true;
} }
void Source::BaseView::replace_text(const std::string &new_text) { void Source::BaseView::replace_text(const std::string &new_text) {
@ -149,15 +196,8 @@ void Source::BaseView::replace_text(const std::string &new_text) {
} }
void Source::BaseView::rename(const boost::filesystem::path &path) { void Source::BaseView::rename(const boost::filesystem::path &path) {
{
std::unique_lock<std::mutex> lock(file_path_mutex);
file_path=path; file_path=path;
boost::system::error_code ec;
canonical_file_path=boost::filesystem::canonical(file_path, ec);
if(ec)
canonical_file_path=file_path;
}
if(update_status_file_path) if(update_status_file_path)
update_status_file_path(this); update_status_file_path(this);
if(update_tab_label) if(update_tab_label)
@ -284,11 +324,24 @@ Gtk::TextIter Source::BaseView::get_tabs_end_iter() {
return get_tabs_end_iter(get_buffer()->get_insert()); return get_tabs_end_iter(get_buffer()->get_insert());
} }
void Source::BaseView::check_last_write_time() { void Source::BaseView::check_last_write_time(std::time_t last_write_time_) {
if(has_focus()) { if(this->last_write_time==static_cast<std::time_t>(-1))
return;
if(Config::get().source.auto_reload_changed_files && !get_buffer()->get_modified()) {
boost::system::error_code ec;
auto last_write_time=last_write_time_!=static_cast<std::time_t>(-1) ? last_write_time_ : boost::filesystem::last_write_time(file_path, ec);
if(!ec && last_write_time!=this->last_write_time) {
if(load()) {
get_buffer()->set_modified(false);
return;
}
}
}
else if(has_focus()) {
boost::system::error_code ec; boost::system::error_code ec;
auto last_write_time=boost::filesystem::last_write_time(file_path, ec); auto last_write_time=last_write_time_!=static_cast<std::time_t>(-1) ? last_write_time_ : boost::filesystem::last_write_time(file_path, ec);
if(!ec && this->last_write_time!=static_cast<std::time_t>(-1) && last_write_time!=this->last_write_time) if(!ec && last_write_time!=this->last_write_time)
Info::get().print("Caution: " + file_path.filename().string() + " was changed outside of juCi++"); Info::get().print("Caution: " + file_path.filename().string() + " was changed outside of juCi++");
} }
} }

11
src/source_base.h

@ -8,17 +8,21 @@ namespace Source {
class BaseView : public Gsv::View { class BaseView : public Gsv::View {
public: public:
BaseView(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language); BaseView(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language);
~BaseView();
boost::filesystem::path file_path; boost::filesystem::path file_path;
boost::filesystem::path canonical_file_path;
Glib::RefPtr<Gsv::Language> language; Glib::RefPtr<Gsv::Language> language;
bool load(); bool load();
/// Set new text more optimally and without unnecessary scrolling /// Set new text more optimally and without unnecessary scrolling
void replace_text(const std::string &new_text); void replace_text(const std::string &new_text);
void rename(const boost::filesystem::path &path); virtual void rename(const boost::filesystem::path &path);
virtual bool save() = 0; virtual bool save() = 0;
Glib::RefPtr<Gio::FileMonitor> monitor;
sigc::connection monitor_changed_connection;
sigc::connection delayed_monitor_changed_connection;
virtual void configure() = 0; virtual void configure() = 0;
virtual void hide_tooltips() = 0; virtual void hide_tooltips() = 0;
virtual void hide_dialogs() = 0; virtual void hide_dialogs() = 0;
@ -69,8 +73,7 @@ namespace Source {
bool disable_spellcheck=false; bool disable_spellcheck=false;
protected: protected:
std::mutex file_path_mutex;
std::time_t last_write_time; std::time_t last_write_time;
void check_last_write_time(); void check_last_write_time(std::time_t last_write_time_=static_cast<std::time_t>(-1));
}; };
} }

4
src/source_clang.cc

@ -358,10 +358,6 @@ void Source::ClangViewParse::update_diagnostics() {
update_status_diagnostics(this); update_status_diagnostics(this);
} }
void Source::ClangViewParse::show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) {
diagnostic_tooltips.show(rectangle);
}
void Source::ClangViewParse::show_type_tooltips(const Gdk::Rectangle &rectangle) { void Source::ClangViewParse::show_type_tooltips(const Gdk::Rectangle &rectangle) {
if(parsed) { if(parsed) {
Gtk::TextIter iter; Gtk::TextIter iter;

1
src/source_clang.h

@ -30,7 +30,6 @@ namespace Source {
std::vector<std::pair<clangmm::Offset, clangmm::Offset>> clang_tokens_offsets; std::vector<std::pair<clangmm::Offset, clangmm::Offset>> clang_tokens_offsets;
sigc::connection delayed_reparse_connection; sigc::connection delayed_reparse_connection;
void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) override;
void show_type_tooltips(const Gdk::Rectangle &rectangle) override; void show_type_tooltips(const Gdk::Rectangle &rectangle) override;
std::set<int> diagnostic_offsets; std::set<int> diagnostic_offsets;

18
src/source_diff.cc

@ -35,6 +35,11 @@ void Source::DiffView::Renderer::draw_vfunc(const Cairo::RefPtr<Cairo::Context>
} }
Source::DiffView::DiffView(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language) : BaseView(file_path, language), renderer(new Renderer()) { Source::DiffView::DiffView(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language) : BaseView(file_path, language), renderer(new Renderer()) {
boost::system::error_code ec;
canonical_file_path=boost::filesystem::canonical(file_path, ec);
if(ec)
canonical_file_path=file_path;
renderer->tag_added=get_buffer()->create_tag("git_added"); renderer->tag_added=get_buffer()->create_tag("git_added");
renderer->tag_modified=get_buffer()->create_tag("git_modified"); renderer->tag_modified=get_buffer()->create_tag("git_modified");
renderer->tag_removed=get_buffer()->create_tag("git_removed"); renderer->tag_removed=get_buffer()->create_tag("git_removed");
@ -144,7 +149,6 @@ void Source::DiffView::configure() {
if(monitor_event!=Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { if(monitor_event!=Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) {
delayed_monitor_changed_connection.disconnect(); delayed_monitor_changed_connection.disconnect();
delayed_monitor_changed_connection=Glib::signal_timeout().connect([this]() { delayed_monitor_changed_connection=Glib::signal_timeout().connect([this]() {
check_last_write_time();
monitor_changed=true; monitor_changed=true;
parse_state=ParseState::STARTING; parse_state=ParseState::STARTING;
std::unique_lock<std::mutex> lock(parse_mutex); std::unique_lock<std::mutex> lock(parse_mutex);
@ -251,6 +255,16 @@ void Source::DiffView::configure() {
}); });
} }
void Source::DiffView::rename(const boost::filesystem::path &path) {
Source::BaseView::rename(path);
std::lock_guard<std::mutex> lock(canonical_file_path_mutex);
boost::system::error_code ec;
canonical_file_path=boost::filesystem::canonical(path, ec);
if(ec)
canonical_file_path=path;
}
void Source::DiffView::git_goto_next_diff() { void Source::DiffView::git_goto_next_diff() {
auto iter=get_buffer()->get_insert()->get_iter(); auto iter=get_buffer()->get_insert()->get_iter();
auto insert_iter=iter; auto insert_iter=iter;
@ -300,7 +314,7 @@ std::unique_ptr<Git::Repository::Diff> Source::DiffView::get_diff() {
auto work_path=filesystem::get_normal_path(repository->get_work_path()); auto work_path=filesystem::get_normal_path(repository->get_work_path());
boost::filesystem::path relative_path; boost::filesystem::path relative_path;
{ {
std::unique_lock<std::mutex> lock(file_path_mutex); std::unique_lock<std::mutex> lock(canonical_file_path_mutex);
relative_path=filesystem::get_relative_path(canonical_file_path, work_path); relative_path=filesystem::get_relative_path(canonical_file_path, work_path);
if(relative_path.empty()) if(relative_path.empty())
throw std::runtime_error("not a relative path"); throw std::runtime_error("not a relative path");

6
src/source_diff.h

@ -32,13 +32,17 @@ namespace Source {
DiffView(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language); DiffView(const boost::filesystem::path &file_path, Glib::RefPtr<Gsv::Language> language);
~DiffView(); ~DiffView();
public:
void configure() override; void configure() override;
void rename(const boost::filesystem::path &path) override;
void git_goto_next_diff(); void git_goto_next_diff();
std::string git_get_diff_details(); std::string git_get_diff_details();
boost::filesystem::path canonical_file_path;
private: private:
std::mutex canonical_file_path_mutex;
std::unique_ptr<Renderer> renderer; std::unique_ptr<Renderer> renderer;
Dispatcher dispatcher; Dispatcher dispatcher;

8
src/source_language_protocol.cc

@ -417,9 +417,11 @@ Source::LanguageProtocolView::~LanguageProtocolView() {
void Source::LanguageProtocolView::setup_navigation_and_refactoring() { void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
if(capabilities.document_formatting) { if(capabilities.document_formatting) {
format_style=[this](bool continue_without_style_file) { format_style=[this](bool continue_without_style_file) {
if(!continue_without_style_file) {
bool has_style_file=false; bool has_style_file=false;
auto style_file_search_path=this->file_path.parent_path(); auto style_file_search_path=this->file_path.parent_path();
auto style_file='.'+language_id+"-format"; auto style_file='.'+language_id+"-format";
while(true) { while(true) {
if(boost::filesystem::exists(style_file_search_path/style_file)) { if(boost::filesystem::exists(style_file_search_path/style_file)) {
has_style_file=true; has_style_file=true;
@ -429,8 +431,10 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
break; break;
style_file_search_path=style_file_search_path.parent_path(); style_file_search_path=style_file_search_path.parent_path();
} }
if(!has_style_file && !continue_without_style_file) if(!has_style_file && !continue_without_style_file)
return; return;
}
class Replace { class Replace {
public: public:
@ -945,10 +949,6 @@ Gtk::TextIter Source::LanguageProtocolView::get_iter_at_line_pos(int line, int p
return get_buffer()->get_iter_at_line_offset(line, pos); return get_buffer()->get_iter_at_line_offset(line, pos);
} }
void Source::LanguageProtocolView::show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) {
diagnostic_tooltips.show(rectangle);
}
void Source::LanguageProtocolView::show_type_tooltips(const Gdk::Rectangle &rectangle) { void Source::LanguageProtocolView::show_type_tooltips(const Gdk::Rectangle &rectangle) {
if(!capabilities.hover) if(!capabilities.hover)
return; return;

1
src/source_language_protocol.h

@ -93,7 +93,6 @@ namespace Source {
Gtk::TextIter get_iter_at_line_pos(int line, int pos) override; Gtk::TextIter get_iter_at_line_pos(int line, int pos) override;
protected: protected:
void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) override;
void show_type_tooltips(const Gdk::Rectangle &rectangle) override; void show_type_tooltips(const Gdk::Rectangle &rectangle) override;
private: private:

7
src/terminal.cc

@ -38,7 +38,7 @@ int Terminal::process(const std::string &command, const boost::filesystem::path
return process->get_exit_status(); return process->get_exit_status();
} }
int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path) { int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path, std::ostream *stderr_stream) {
TinyProcessLib::Process process(command, path.string(), [&stdout_stream](const char* bytes, size_t n) { TinyProcessLib::Process process(command, path.string(), [&stdout_stream](const char* bytes, size_t n) {
Glib::ustring umessage(std::string(bytes, n)); Glib::ustring umessage(std::string(bytes, n));
Glib::ustring::iterator iter; Glib::ustring::iterator iter;
@ -48,7 +48,10 @@ int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, c
umessage.replace(iter, next_char_iter, "?"); umessage.replace(iter, next_char_iter, "?");
} }
stdout_stream.write(umessage.data(), n); stdout_stream.write(umessage.data(), n);
}, [this](const char* bytes, size_t n) { }, [this, stderr_stream](const char* bytes, size_t n) {
if(stderr_stream)
stderr_stream->write(bytes, n);
else
async_print(std::string(bytes, n), true); async_print(std::string(bytes, n), true);
}, true); }, true);

2
src/terminal.h

@ -17,7 +17,7 @@ public:
} }
int process(const std::string &command, const boost::filesystem::path &path="", bool use_pipes=true); int process(const std::string &command, const boost::filesystem::path &path="", bool use_pipes=true);
int process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path=""); int process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path="", std::ostream *stderr_stream=nullptr);
void async_process(const std::string &command, const boost::filesystem::path &path="", std::function<void(int exit_status)> callback=nullptr, bool quiet=false); void async_process(const std::string &command, const boost::filesystem::path &path="", std::function<void(int exit_status)> callback=nullptr, bool quiet=false);
void kill_last_async_process(bool force=false); void kill_last_async_process(bool force=false);
void kill_async_processes(bool force=false); void kill_async_processes(bool force=false);

6
src/window.cc

@ -285,14 +285,12 @@ void Window::set_menu_actions() {
return; return;
} }
view->load(); if(view->load()) {
while(Gtk::Main::events_pending())
Gtk::Main::iteration(false);
Notebook::get().delete_cursor_locations(view);
view->get_buffer()->set_modified(false); view->get_buffer()->set_modified(false);
view->full_reparse(); view->full_reparse();
} }
} }
}
}); });
menu.add_action("file_save", [this]() { menu.add_action("file_save", [this]() {

Loading…
Cancel
Save