Browse Source

Merge pull request #85 from eidheim/master

Mostly minor cleanup and fixes, added two new features.
merge-requests/365/head
Jørgen Lien Sellæg 10 years ago
parent
commit
3aedffb708
  1. 15
      docs/install.md
  2. 5
      src/CMakeLists.txt
  3. 7
      src/cmake.cc
  4. 16
      src/config.cc
  5. 2
      src/config.h
  6. 83
      src/dialogs.cc
  7. 13
      src/dialogs.h
  8. 32
      src/dialogs_unix.cc
  9. 30
      src/dialogs_win.cc
  10. 4
      src/files.h
  11. 15
      src/juci.cc
  12. 45
      src/notebook.cc
  13. 1
      src/notebook.h
  14. 6
      src/source.cc
  15. 10
      src/source_clang.cc
  16. 6
      src/terminal_unix.cc
  17. 6
      src/terminal_win.cc
  18. 58
      src/window.cc

15
docs/install.md

@ -4,6 +4,7 @@
Install dependencies: Install dependencies:
```sh ```sh
sudo apt-get install git cmake make g++ libclang-dev pkg-config libboost-system-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libgtkmm-3.0-dev libgtksourceviewmm-3.0-dev aspell-en libaspell-dev sudo apt-get install git cmake make g++ libclang-dev pkg-config libboost-system-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libgtkmm-3.0-dev libgtksourceviewmm-3.0-dev aspell-en libaspell-dev
sudo apt-get install clang-format-3.6 || sudo apt-get install clang-format-3.5
``` ```
Get juCi++ source, compile and install: Get juCi++ source, compile and install:
@ -15,12 +16,6 @@ make
sudo make install sudo make install
``` ```
To use clang-format for auto-indentation of C++ files (replace \[version\] with an available clang-format version):
```sh
sudo apt-get install clang-format-[version]
sudo ln -s /usr/bin/clang-format-[version] /usr/local/bin/clang-format
```
## Ubuntu 14/Linux Mint 17 ## Ubuntu 14/Linux Mint 17
Install dependencies: Install dependencies:
```sh ```sh
@ -28,7 +23,7 @@ sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update sudo apt-get update
sudo apt-get install g++-4.9 sudo apt-get install g++-4.9
sudo apt-get remove g++-4.8 sudo apt-get remove g++-4.8
sudo apt-get install git cmake make g++ libclang-3.6-dev pkg-config libboost-system1.55-dev libboost-thread1.55-dev libboost-filesystem1.55-dev libboost-log1.55-dev libgtkmm-3.0-dev libgtksourceviewmm-3.0-dev aspell-en libaspell-dev sudo apt-get install git cmake make g++ libclang-3.6-dev clang-format-3.6 pkg-config libboost-system1.55-dev libboost-thread1.55-dev libboost-filesystem1.55-dev libboost-log1.55-dev libgtkmm-3.0-dev libgtksourceviewmm-3.0-dev aspell-en libaspell-dev
``` ```
Get juCi++ source, compile and install: Get juCi++ source, compile and install:
@ -40,12 +35,6 @@ make
sudo make install sudo make install
``` ```
To use clang-format for auto-indentation of C++ files (replace \[version\] with an available clang-format version):
```sh
sudo apt-get install clang-format-[version]
sudo ln -s /usr/bin/clang-format-[version] /usr/local/bin/clang-format
```
## OS X with Homebrew (http://brew.sh/) ## OS X with Homebrew (http://brew.sh/)
Install dependencies (installing llvm may take some time): Install dependencies (installing llvm may take some time):
```sh ```sh

5
src/CMakeLists.txt

@ -72,6 +72,7 @@ set(source_files juci.h
singletons.cc singletons.cc
cmake.h cmake.h
cmake.cc cmake.cc
dialogs.cc
../libclangmm/src/CodeCompleteResults.cc ../libclangmm/src/CodeCompleteResults.cc
../libclangmm/src/CompilationDatabase.cc ../libclangmm/src/CompilationDatabase.cc
@ -92,8 +93,8 @@ if(MSYS)
list(APPEND source_files terminal_win.cc) list(APPEND source_files terminal_win.cc)
list(APPEND source_files dialogs_win.cc) list(APPEND source_files dialogs_win.cc)
else() else()
list(APPEND source_files terminal.cc) list(APPEND source_files terminal_unix.cc)
list(APPEND source_files dialogs.cc) list(APPEND source_files dialogs_unix.cc)
endif() endif()
add_executable(${project_name} ${source_files}) add_executable(${project_name} ${source_files})

7
src/cmake.cc

@ -2,6 +2,7 @@
#include "singletons.h" #include "singletons.h"
#include "filesystem.h" #include "filesystem.h"
#include <regex> #include <regex>
#include "dialogs.h"
#include <iostream> //TODO: remove #include <iostream> //TODO: remove
using namespace std; //TODO: remove using namespace std; //TODO: remove
@ -45,8 +46,10 @@ CMake::CMake(const boost::filesystem::path &path) {
} }
bool CMake::create_compile_commands(const boost::filesystem::path &path) { bool CMake::create_compile_commands(const boost::filesystem::path &path) {
Singleton::terminal->print("Creating "+path.string()+"/compile_commands.json\n"); Dialog::Message message("Creating "+path.string()+"/compile_commands.json");
if(Singleton::terminal->execute(Singleton::config->terminal.cmake_command+" . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", path)==EXIT_SUCCESS) { auto exit_code=Singleton::terminal->execute(Singleton::config->terminal.cmake_command+" . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", path);
message.hide();
if(exit_code==EXIT_SUCCESS) {
#ifdef _WIN32 //Temporary fix to MSYS2's libclang #ifdef _WIN32 //Temporary fix to MSYS2's libclang
auto compile_commands_path=path; auto compile_commands_path=path;
compile_commands_path+="/compile_commands.json"; compile_commands_path+="/compile_commands.json";

16
src/config.cc

@ -89,8 +89,20 @@ void Config::retrieve_config() {
window.default_size = {cfg.get<int>("default_window_size.width"), cfg.get<int>("default_window_size.height")}; window.default_size = {cfg.get<int>("default_window_size.width"), cfg.get<int>("default_window_size.height")};
terminal.make_command=cfg.get<std::string>("project.make_command"); terminal.make_command=cfg.get<std::string>("project.make_command");
terminal.cmake_command=cfg.get<std::string>("project.cmake_command"); terminal.cmake_command=cfg.get<std::string>("project.cmake_command");
terminal.clang_format_command=cfg.get<std::string>("project.clang_format_command", "clang-format");
terminal.history_size=cfg.get<int>("terminal_history_size"); terminal.history_size=cfg.get<int>("terminal_history_size");
terminal.clang_format_command=cfg.get<std::string>("project.clang_format_command", "clang-format");
#ifdef __linux
if(terminal.clang_format_command=="clang-format" &&
!boost::filesystem::exists("/usr/bin/clang-format") && !boost::filesystem::exists("/usr/local/bin/clang-format")) {
if(boost::filesystem::exists("/usr/bin/clang-format-3.7"))
terminal.clang_format_command="/usr/bin/clang-format-3.7";
else if(boost::filesystem::exists("/usr/bin/clang-format-3.6"))
terminal.clang_format_command="/usr/bin/clang-format-3.6";
else if(boost::filesystem::exists("/usr/bin/clang-format-3.5"))
terminal.clang_format_command="/usr/bin/clang-format-3.5";
}
#endif
} }
bool Config::check_config_file(const boost::property_tree::ptree &default_cfg, std::string parent_path) { bool Config::check_config_file(const boost::property_tree::ptree &default_cfg, std::string parent_path) {
@ -146,6 +158,8 @@ void Config::get_source() {
source.style=source_json.get<std::string>("style"); source.style=source_json.get<std::string>("style");
source.font=source_json.get<std::string>("font"); source.font=source_json.get<std::string>("font");
source.cleanup_whitespace_characters=source_json.get<bool>("cleanup_whitespace_characters");
source.show_map = source_json.get<bool>("show_map"); source.show_map = source_json.get<bool>("show_map");
source.map_font_size = source_json.get<std::string>("map_font_size"); source.map_font_size = source_json.get<std::string>("map_font_size");

2
src/config.h

@ -49,6 +49,8 @@ public:
std::string font; std::string font;
std::string spellcheck_language; std::string spellcheck_language;
bool cleanup_whitespace_characters;
bool show_map; bool show_map;
std::string map_font_size; std::string map_font_size;

83
src/dialogs.cc

@ -1,59 +1,56 @@
#include "dialogs.h" #include "dialogs.h"
#include "singletons.h"
#include <gtkmm.h>
#include <vector>
#include "juci.h" #include "juci.h"
#include "singletons.h"
#include <cmath>
namespace sigc {
#ifndef SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
template <typename Functor>
struct functor_trait<Functor, false> {
typedef decltype (::sigc::mem_fun(std::declval<Functor&>(),
&Functor::operator())) _intermediate;
typedef typename _intermediate::result_type result_type;
typedef Functor functor_type;
};
#else
SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
#endif
}
Dialog::Message::Message(const std::string &text): Gtk::MessageDialog(text, false, Gtk::MessageType::MESSAGE_INFO, Gtk::ButtonsType::BUTTONS_NONE, true) {
auto g_application=g_application_get_default();
auto gio_application=Glib::wrap(g_application, true);
auto application=Glib::RefPtr<Application>::cast_static(gio_application);
set_transient_for(*application->window);
set_position(Gtk::WindowPosition::WIN_POS_CENTER_ON_PARENT);
show_now();
std::string open_dialog(const std::string &title, while(g_main_context_pending(NULL))
g_main_context_iteration(NULL, false);
}
std::string Dialog::gtk_dialog(const std::string &title,
const std::vector<std::pair<std::string, Gtk::ResponseType>> &buttons, const std::vector<std::pair<std::string, Gtk::ResponseType>> &buttons,
Gtk::FileChooserAction gtk_options, Gtk::FileChooserAction gtk_options,
const std::string &file_name = "") { const std::string &file_name) {
Gtk::FileChooserDialog dialog(title, gtk_options); Gtk::FileChooserDialog dialog(title, gtk_options);
if(!Singleton::directories->current_path.empty())
gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), Singleton::directories->current_path.string().c_str());
else
gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), boost::filesystem::current_path().string().c_str());
if (!file_name.empty())
gtk_file_chooser_set_filename((GtkFileChooser*)dialog.gobj(), file_name.c_str());
dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ALWAYS);
auto g_application=g_application_get_default(); //TODO: Post issue that Gio::Application::get_default should return pointer and not Glib::RefPtr auto g_application=g_application_get_default(); //TODO: Post issue that Gio::Application::get_default should return pointer and not Glib::RefPtr
auto gio_application=Glib::wrap(g_application, true); auto gio_application=Glib::wrap(g_application, true);
auto application=Glib::RefPtr<Application>::cast_static(gio_application); auto application=Glib::RefPtr<Application>::cast_static(gio_application);
dialog.set_transient_for(*application->window); dialog.set_transient_for(*application->window);
auto current_path=application->window->notebook.get_current_folder();
if(current_path.empty())
current_path=boost::filesystem::current_path();
gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), current_path.string().c_str());
if (!file_name.empty())
gtk_file_chooser_set_filename((GtkFileChooser*)dialog.gobj(), file_name.c_str());
dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ON_PARENT);
for (auto &button : buttons) for (auto &button : buttons)
dialog.add_button(button.first, button.second); dialog.add_button(button.first, button.second);
return dialog.run() == Gtk::RESPONSE_OK ? dialog.get_filename() : ""; return dialog.run() == Gtk::RESPONSE_OK ? dialog.get_filename() : "";
} }
std::string Dialog::open_folder() {
return open_dialog("Open Folder",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Open", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
}
std::string Dialog::new_file() {
return open_dialog("New File",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL), std::make_pair("Save", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_SAVE);
}
std::string Dialog::new_folder() {
return open_dialog("New Folder",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Create", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER);
}
std::string Dialog::open_file() {
return open_dialog("Open File",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Select", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_OPEN);
}
std::string Dialog::save_file_as(const boost::filesystem::path &file_path) {
return open_dialog("Save File As",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Save", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_SAVE, file_path.string());
}

13
src/dialogs.h

@ -2,6 +2,8 @@
#define JUCI_DIALOG_H_ #define JUCI_DIALOG_H_
#include <string> #include <string>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <vector>
#include <gtkmm.h>
class Dialog { class Dialog {
public: public:
@ -10,6 +12,17 @@ public:
static std::string new_file(); static std::string new_file();
static std::string new_folder(); static std::string new_folder();
static std::string save_file_as(const boost::filesystem::path &file_path); static std::string save_file_as(const boost::filesystem::path &file_path);
class Message : public Gtk::MessageDialog {
public:
Message(const std::string &text);
};
private:
static std::string gtk_dialog(const std::string &title,
const std::vector<std::pair<std::string, Gtk::ResponseType>> &buttons,
Gtk::FileChooserAction gtk_options,
const std::string &file_name = "");
}; };
#endif //JUCI_DIALOG_H_ #endif //JUCI_DIALOG_H_

32
src/dialogs_unix.cc

@ -0,0 +1,32 @@
#include "dialogs.h"
std::string Dialog::open_folder() {
return gtk_dialog("Open Folder",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Open", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
}
std::string Dialog::new_file() {
return gtk_dialog("New File",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL), std::make_pair("Save", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_SAVE);
}
std::string Dialog::new_folder() {
return gtk_dialog("New Folder",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Create", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER);
}
std::string Dialog::open_file() {
return gtk_dialog("Open File",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Select", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_OPEN);
}
std::string Dialog::save_file_as(const boost::filesystem::path &file_path) {
return gtk_dialog("Save File As",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Save", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_SAVE, file_path.string());
}

30
src/dialogs_win.cc

@ -1,5 +1,6 @@
#include "dialogs.h" #include "dialogs.h"
#include "singletons.h" #include "singletons.h"
#include "juci.h"
#undef NTDDI_VERSION #undef NTDDI_VERSION
#define NTDDI_VERSION NTDDI_VISTA #define NTDDI_VERSION NTDDI_VISTA
@ -29,8 +30,7 @@ public:
if(!set_title(title) || !add_option(option)) if(!set_title(title) || !add_option(option))
return ""; return "";
auto dirs = Singleton::directories->current_path; if(!set_folder())
if(!set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native()))
return ""; return "";
return show(); return show();
@ -42,10 +42,10 @@ public:
if(!set_title(title) || !add_option(option)) if(!set_title(title) || !add_option(option))
return ""; return "";
if(!set_folder())
return "";
std::vector<COMDLG_FILTERSPEC> extensions; std::vector<COMDLG_FILTERSPEC> extensions;
if(!file_path.empty()) { if(!file_path.empty()) {
if(!set_folder(file_path.parent_path().native()))
return "";
if(file_path.has_extension() && file_path.filename()!=file_path.extension()) { if(file_path.has_extension() && file_path.filename()!=file_path.extension()) {
auto extension=(L"*"+file_path.extension().native()).c_str(); auto extension=(L"*"+file_path.extension().native()).c_str();
extensions.emplace_back(COMDLG_FILTERSPEC{extension, extension}); extensions.emplace_back(COMDLG_FILTERSPEC{extension, extension});
@ -53,11 +53,6 @@ public:
return ""; return "";
} }
} }
else {
auto dirs = Singleton::directories->current_path;
if(!set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native()))
return "";
}
extensions.emplace_back(COMDLG_FILTERSPEC{L"All files", L"*.*"}); extensions.emplace_back(COMDLG_FILTERSPEC{L"All files", L"*.*"});
if(dialog->SetFileTypes(extensions.size(), extensions.data())!=S_OK) if(dialog->SetFileTypes(extensions.size(), extensions.data())!=S_OK)
return ""; return "";
@ -98,8 +93,16 @@ private:
} }
/** Sets the directory to start browsing */ /** Sets the directory to start browsing */
bool set_folder(const std::wstring &directory_path) { bool set_folder() {
std::wstring path=directory_path; auto g_application=g_application_get_default(); //TODO: Post issue that Gio::Application::get_default should return pointer and not Glib::RefPtr
auto gio_application=Glib::wrap(g_application, true);
auto application=Glib::RefPtr<Application>::cast_static(gio_application);
auto current_path=application->window->notebook.get_current_folder();
if(current_path.empty())
current_path=boost::filesystem::current_path();
std::wstring path=current_path.native();
size_t pos=0; size_t pos=0;
while((pos=path.find(L'/', pos))!=std::wstring::npos) {//TODO: issue bug report on boost::filesystem::path::native on MSYS2 while((pos=path.find(L'/', pos))!=std::wstring::npos) {//TODO: issue bug report on boost::filesystem::path::native on MSYS2
path.replace(pos, 1, L"\\"); path.replace(pos, 1, L"\\");
@ -142,7 +145,10 @@ std::string Dialog::new_file() {
} }
std::string Dialog::new_folder() { std::string Dialog::new_folder() {
return Win32Dialog().open(L"New Folder", FOS_PICKFOLDERS); //TODO: this is not working correctly yet //Win32 (IFileDialog) does not support create folder...
return gtk_dialog("New Folder",
{std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Create", Gtk::RESPONSE_OK)},
Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER);
} }
std::string Dialog::open_file() { std::string Dialog::open_file() {

4
src/files.h

@ -1,6 +1,6 @@
#include <string> #include <string>
#define JUCI_VERSION "0.9.4" #define JUCI_VERSION "0.9.5"
const std::string configjson = const std::string configjson =
"{\n" "{\n"
@ -29,6 +29,8 @@ const std::string configjson =
" \"font\": \"Monospace\",\n" " \"font\": \"Monospace\",\n"
#endif #endif
#endif #endif
" \"cleanup_whitespace_characters_comment\": \"Remove trailing whitespace characters on save, and add trailing newline if missing\",\n"
" \"cleanup_whitespace_characters\": false,\n"
" \"show_map\": true,\n" " \"show_map\": true,\n"
" \"map_font_size\": \"1\",\n" " \"map_font_size\": \"1\",\n"
" \"spellcheck_language_comment\": \"Use \\\"\\\" to set language from your locale settings\",\n" " \"spellcheck_language_comment\": \"Use \\\"\\\" to set language from your locale settings\",\n"

15
src/juci.cc

@ -29,8 +29,18 @@ int Application::on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine>
else if(boost::filesystem::is_directory(p)) else if(boost::filesystem::is_directory(p))
directories.emplace_back(p); directories.emplace_back(p);
} }
else { //Open new file if parent path exists
auto parent_p=p.parent_path();
boost::system::error_code ec;
auto new_p=boost::filesystem::canonical(parent_p, ec);
if(!ec && boost::filesystem::is_directory(new_p)) {
new_p+="/";
new_p+=p.filename();
files.emplace_back(new_p);
}
else else
std::cerr << "Path " << p << " does not exist." << std::endl; Singleton::terminal->print("Error: folder path "+parent_p.string()+" does not exist.\n", true);
}
} }
} }
activate(); activate();
@ -92,6 +102,9 @@ Application::Application() : Gtk::Application("no.sout.juci", Gio::APPLICATION_N
Glib::set_application_name("juCi++"); Glib::set_application_name("juCi++");
//Gtk::MessageDialog without buttons caused text to be selected, this prevents that
Gtk::Settings::get_default()->property_gtk_label_select_on_focus()=false;
window=std::unique_ptr<Window>(new Window()); window=std::unique_ptr<Window>(new Window());
} }

45
src/notebook.cc

@ -65,12 +65,14 @@ void Notebook::open(const boost::filesystem::path &file_path) {
} }
} }
if(boost::filesystem::exists(file_path)) {
std::ifstream can_read(file_path.string()); std::ifstream can_read(file_path.string());
if(!can_read) { if(!can_read) {
Singleton::terminal->print("Error: could not open "+file_path.string()+"\n"); Singleton::terminal->print("Error: could not open "+file_path.string()+"\n", true);
return; return;
} }
can_read.close(); can_read.close();
}
auto language=Source::guess_language(file_path); auto language=Source::guess_language(file_path);
boost::filesystem::path project_path; boost::filesystem::path project_path;
@ -170,6 +172,32 @@ bool Notebook::save(int page, bool reparse_needed) {
} }
auto view=get_view(page); auto view=get_view(page);
if (view->file_path != "" && view->get_buffer()->get_modified()) { if (view->file_path != "" && view->get_buffer()->get_modified()) {
//Remove trailing whitespace characters on save, and add trailing newline if missing
if(Singleton::config->source.cleanup_whitespace_characters) {
auto buffer=view->get_buffer();
buffer->begin_user_action();
for(int line=0;line<buffer->get_line_count();line++) {
auto iter=buffer->get_iter_at_line(line);
auto end_iter=iter;
while(!end_iter.ends_line())
end_iter.forward_char();
if(iter==end_iter)
continue;
iter=end_iter;
while(!iter.starts_line() && (*iter==' ' || *iter=='\t' || iter.ends_line()))
iter.backward_char();
if(*iter!=' ' && *iter!='\t')
iter.forward_char();
if(iter==end_iter)
continue;
buffer->erase(iter, end_iter);
}
auto iter=buffer->end();
if(!iter.starts_line())
buffer->insert(buffer->end(), "\n");
buffer->end_user_action();
}
if(filesystem::write(view->file_path, view->get_buffer())) { if(filesystem::write(view->file_path, view->get_buffer())) {
if(reparse_needed) { if(reparse_needed) {
if(auto clang_view=dynamic_cast<Source::ClangView*>(view)) { if(auto clang_view=dynamic_cast<Source::ClangView*>(view)) {
@ -206,7 +234,7 @@ bool Notebook::save(int page, bool reparse_needed) {
if(source_clang_view->restart_parse()) if(source_clang_view->restart_parse())
Singleton::terminal->async_print("Reparsing "+source_clang_view->file_path.string()+"\n"); Singleton::terminal->async_print("Reparsing "+source_clang_view->file_path.string()+"\n");
else else
Singleton::terminal->async_print("Error: failed to reparse "+source_clang_view->file_path.string()+". Please reopen the file manually.\n"); Singleton::terminal->async_print("Error: failed to reparse "+source_clang_view->file_path.string()+". Please reopen the file manually.\n", true);
} }
} }
} }
@ -215,7 +243,7 @@ bool Notebook::save(int page, bool reparse_needed) {
JDEBUG("end true"); JDEBUG("end true");
return true; return true;
} }
Singleton::terminal->print("Error: could not save file " +view->file_path.string()+"\n"); Singleton::terminal->print("Error: could not save file " +view->file_path.string()+"\n", true);
} }
JDEBUG("end false"); JDEBUG("end false");
return false; return false;
@ -260,6 +288,17 @@ bool Notebook::close_current_page() {
return true; return true;
} }
boost::filesystem::path Notebook::get_current_folder() {
boost::filesystem::path current_path;
if(get_current_page()!=-1)
current_path=get_current_view()->project_path;
else
current_path=Singleton::directories->current_path;
return current_path;
}
bool Notebook::save_modified_dialog() { bool Notebook::save_modified_dialog() {
Gtk::MessageDialog dialog((Gtk::Window&)(*get_toplevel()), "Save file!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); Gtk::MessageDialog dialog((Gtk::Window&)(*get_toplevel()), "Save file!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO);
dialog.set_default_response(Gtk::RESPONSE_YES); dialog.set_default_response(Gtk::RESPONSE_YES);

1
src/notebook.h

@ -21,6 +21,7 @@ public:
bool save(int page, bool reparse_needed=false); bool save(int page, bool reparse_needed=false);
bool save_current(); bool save_current();
void configure(int view_nr); void configure(int view_nr);
boost::filesystem::path get_current_folder();
private: private:
bool save_modified_dialog(); bool save_modified_dialog();

6
src/source.cc

@ -91,7 +91,7 @@ Source::View::View(const boost::filesystem::path &file_path, const boost::filesy
} }
else { else {
if(filesystem::read(file_path, get_buffer())==-1) if(filesystem::read(file_path, get_buffer())==-1)
Singleton::terminal->print("Error: "+file_path.string()+" is not a valid UTF-8 file.\n"); Singleton::terminal->print("Error: "+file_path.string()+" is not a valid UTF-8 file.\n", true);
} }
get_source_buffer()->end_not_undoable_action(); get_source_buffer()->end_not_undoable_action();
@ -304,7 +304,7 @@ void Source::View::configure() {
if(scheme) if(scheme)
get_source_buffer()->set_style_scheme(scheme); get_source_buffer()->set_style_scheme(scheme);
else else
Singleton::terminal->print("Error: Could not find gtksourceview style: "+Singleton::config->source.style+'\n'); Singleton::terminal->print("Error: Could not find gtksourceview style: "+Singleton::config->source.style+'\n', true);
} }
if(Singleton::config->source.wrap_lines) if(Singleton::config->source.wrap_lines)
@ -1306,7 +1306,7 @@ Source::GenericView::GenericView(const boost::filesystem::path &file_path, const
boost::property_tree::xml_parser::read_xml(language_file.string(), pt); boost::property_tree::xml_parser::read_xml(language_file.string(), pt);
} }
catch(const std::exception &e) { catch(const std::exception &e) {
Singleton::terminal->print("Error: error parsing language file "+language_file.string()+": "+e.what()+'\n'); Singleton::terminal->print("Error: error parsing language file "+language_file.string()+": "+e.what()+'\n', true);
} }
bool has_context_class=false; bool has_context_class=false;
parse_language_file(completion_buffer_keywords, has_context_class, pt); parse_language_file(completion_buffer_keywords, has_context_class, pt);

10
src/source_clang.cc

@ -59,7 +59,7 @@ Source::View(file_path, project_path, language), parse_error(false) {
} }
}); });
parse_fail_connection=parse_fail.connect([this](){ parse_fail_connection=parse_fail.connect([this](){
Singleton::terminal->print("Error: failed to reparse "+this->file_path.string()+".\n"); Singleton::terminal->print("Error: failed to reparse "+this->file_path.string()+".\n", true);
set_status(""); set_status("");
set_info(""); set_info("");
parsing_in_progress->cancel("failed"); parsing_in_progress->cancel("failed");
@ -145,7 +145,7 @@ void Source::ClangViewParse::init_parse() {
parse_start(); parse_start();
} }
else if (parse_thread_mapped && parsing_mutex.try_lock() && parse_thread_buffer_map_mutex.try_lock()) { else if (parse_thread_mapped && parsing_mutex.try_lock() && parse_thread_buffer_map_mutex.try_lock()) {
int status=clang_tu->ReparseTranslationUnit(parse_thread_buffer_map); auto status=clang_tu->ReparseTranslationUnit(parse_thread_buffer_map);
if(status==0) if(status==0)
clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer_map.find(file_path.string())->second.size()-1); clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer_map.find(file_path.string())->second.size()-1);
else else
@ -649,7 +649,7 @@ Source::ClangViewParse(file_path, project_path, language), autocomplete_cancel_s
}); });
autocomplete_fail_connection=autocomplete_fail.connect([this]() { autocomplete_fail_connection=autocomplete_fail.connect([this]() {
Singleton::terminal->print("Error: autocomplete failed, reparsing "+this->file_path.string()+"\n"); Singleton::terminal->print("Error: autocomplete failed, reparsing "+this->file_path.string()+"\n", true);
restart_parse(); restart_parse();
autocomplete_starting=false; autocomplete_starting=false;
autocomplete_cancel_starting=false; autocomplete_cancel_starting=false;
@ -963,8 +963,8 @@ Source::ClangViewAutocomplete(file_path, project_path, language) {
iter.forward_char(); iter.forward_char();
} }
get_buffer()->place_cursor(iter); get_buffer()->place_cursor(iter);
while(gtk_events_pending()) while(g_main_context_pending(NULL))
gtk_main_iteration(); g_main_context_iteration(NULL, false);
scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5); scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5);
} }
get_source_buffer()->end_user_action(); get_source_buffer()->end_user_action();

6
src/terminal.cc → src/terminal_unix.cc

@ -155,7 +155,7 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path
pid=popen3(command, path.string(), nullptr, nullptr, nullptr); pid=popen3(command, path.string(), nullptr, nullptr, nullptr);
if (pid<=0) { if (pid<=0) {
async_print("Error: Failed to run command: " + command + "\n"); async_print("Error: Failed to run command: " + command + "\n", true);
return -1; return -1;
} }
else { else {
@ -203,7 +203,7 @@ int Terminal::execute(std::istream &stdin_stream, std::ostream &stdout_stream, c
auto pid=popen3(command, path.string(), &stdin_fd, &stdout_fd, &stderr_fd); auto pid=popen3(command, path.string(), &stdin_fd, &stdout_fd, &stderr_fd);
if (pid<=0) { if (pid<=0) {
async_print("Error: Failed to run command: " + command + "\n"); async_print("Error: Failed to run command: " + command + "\n", true);
return -1; return -1;
} }
else { else {
@ -269,7 +269,7 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem
async_executes_mutex.unlock(); async_executes_mutex.unlock();
if (pid<=0) { if (pid<=0) {
async_print("Error: Failed to run command: " + command + "\n"); async_print("Error: Failed to run command: " + command + "\n", true);
if(callback) if(callback)
callback(-1); callback(-1);
} }

6
src/terminal_win.cc

@ -200,7 +200,7 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path
else else
process=popen3(command, path.string(), nullptr, nullptr, nullptr); process=popen3(command, path.string(), nullptr, nullptr, nullptr);
if(process==NULL) { if(process==NULL) {
async_print("Error: Failed to run command: " + command + "\n"); async_print("Error: Failed to run command: " + command + "\n", true);
return -1; return -1;
} }
if(use_pipes) { if(use_pipes) {
@ -257,7 +257,7 @@ int Terminal::execute(std::istream &stdin_stream, std::ostream &stdout_stream, c
auto process=popen3(command, path.string(), &stdin_h, &stdout_h, &stderr_h); auto process=popen3(command, path.string(), &stdin_h, &stdout_h, &stderr_h);
if(process==NULL) { if(process==NULL) {
async_print("Error: Failed to run command: " + command + "\n"); async_print("Error: Failed to run command: " + command + "\n", true);
return -1; return -1;
} }
std::thread stderr_thread([this, stderr_h](){ std::thread stderr_thread([this, stderr_h](){
@ -331,7 +331,7 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem
auto process=popen3(command, path.string(), &stdin_h, &stdout_h, &stderr_h); auto process=popen3(command, path.string(), &stdin_h, &stdout_h, &stderr_h);
if(process==NULL) { if(process==NULL) {
async_executes_mutex.unlock(); async_executes_mutex.unlock();
async_print("Error: Failed to run command: " + command + "\n"); async_print("Error: Failed to run command: " + command + "\n", true);
if(callback) if(callback)
callback(-1); callback(-1);
return; return;

58
src/window.cc

@ -154,7 +154,7 @@ void Window::set_menu_actions() {
boost::filesystem::path path = Dialog::new_file(); boost::filesystem::path path = Dialog::new_file();
if(path!="") { if(path!="") {
if(boost::filesystem::exists(path)) { if(boost::filesystem::exists(path)) {
Singleton::terminal->print("Error: "+path.string()+" already exists.\n"); Singleton::terminal->print("Error: "+path.string()+" already exists.\n", true);
} }
else { else {
if(filesystem::write(path)) { if(filesystem::write(path)) {
@ -164,7 +164,7 @@ void Window::set_menu_actions() {
Singleton::terminal->print("New file "+path.string()+" created.\n"); Singleton::terminal->print("New file "+path.string()+" created.\n");
} }
else else
Singleton::terminal->print("Error: could not create new file "+path.string()+".\n"); Singleton::terminal->print("Error: could not create new file "+path.string()+".\n", true);
} }
} }
}); });
@ -178,7 +178,7 @@ void Window::set_menu_actions() {
Singleton::terminal->print("New folder "+path.string()+" created.\n"); Singleton::terminal->print("New folder "+path.string()+" created.\n");
} }
else else
Singleton::terminal->print("Error: "+path.string()+" already exists.\n"); Singleton::terminal->print("Error: "+path.string()+" already exists.\n", true);
Singleton::directories->select(path); Singleton::directories->select(path);
} }
}); });
@ -195,11 +195,11 @@ void Window::set_menu_actions() {
auto cpp_main_path=project_path; auto cpp_main_path=project_path;
cpp_main_path+="/main.cpp"; cpp_main_path+="/main.cpp";
if(boost::filesystem::exists(cmakelists_path)) { if(boost::filesystem::exists(cmakelists_path)) {
Singleton::terminal->print("Error: "+cmakelists_path.string()+" already exists.\n"); Singleton::terminal->print("Error: "+cmakelists_path.string()+" already exists.\n", true);
return; return;
} }
if(boost::filesystem::exists(cpp_main_path)) { if(boost::filesystem::exists(cpp_main_path)) {
Singleton::terminal->print("Error: "+cpp_main_path.string()+" already exists.\n"); Singleton::terminal->print("Error: "+cpp_main_path.string()+" already exists.\n", true);
return; return;
} }
std::string cmakelists="cmake_minimum_required(VERSION 2.8)\n\nproject("+project_name+")\n\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++1y -Wall\")\n\nadd_executable("+project_name+" main.cpp)\n"; std::string cmakelists="cmake_minimum_required(VERSION 2.8)\n\nproject("+project_name+")\n\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++1y -Wall\")\n\nadd_executable("+project_name+" main.cpp)\n";
@ -210,7 +210,7 @@ void Window::set_menu_actions() {
Singleton::terminal->print("C++ project "+project_name+" created.\n"); Singleton::terminal->print("C++ project "+project_name+" created.\n");
} }
else else
Singleton::terminal->print("Error: Could not create project "+project_path.string()+"\n"); Singleton::terminal->print("Error: Could not create project "+project_path.string()+"\n", true);
} }
}); });
@ -330,8 +330,8 @@ void Window::set_menu_actions() {
}); });
menu->add_action("source_center_cursor", [this]() { menu->add_action("source_center_cursor", [this]() {
if(notebook.get_current_page()!=-1) { if(notebook.get_current_page()!=-1) {
while(gtk_events_pending()) while(g_main_context_pending(NULL))
gtk_main_iteration(); g_main_context_iteration(NULL, false);
if(notebook.get_current_page()!=-1) if(notebook.get_current_page()!=-1)
notebook.get_current_view()->scroll_to(notebook.get_current_view()->get_buffer()->get_insert(), 0.0, 1.0, 0.5); notebook.get_current_view()->scroll_to(notebook.get_current_view()->get_buffer()->get_insert(), 0.0, 1.0, 0.5);
} }
@ -396,8 +396,8 @@ void Window::set_menu_actions() {
index=std::min(index, end_line_index); index=std::min(index, end_line_index);
buffer->place_cursor(buffer->get_iter_at_line_index(line, index)); buffer->place_cursor(buffer->get_iter_at_line_index(line, index));
while(gtk_events_pending()) while(g_main_context_pending(NULL))
gtk_main_iteration(); g_main_context_iteration(NULL, false);
if(notebook.get_current_page()!=-1) if(notebook.get_current_page()!=-1)
notebook.get_current_view()->scroll_to(notebook.get_current_view()->get_buffer()->get_insert(), 0.0, 1.0, 0.5); notebook.get_current_view()->scroll_to(notebook.get_current_view()->get_buffer()->get_insert(), 0.0, 1.0, 0.5);
} }
@ -432,9 +432,16 @@ void Window::set_menu_actions() {
}); });
menu->add_action("compile_and_run", [this]() { menu->add_action("compile_and_run", [this]() {
if(notebook.get_current_page()==-1 || compiling) if(compiling)
return; return;
CMake cmake(notebook.get_current_view()->file_path); boost::filesystem::path cmake_path;
if(notebook.get_current_page()!=-1)
cmake_path=notebook.get_current_view()->file_path.parent_path();
else
cmake_path=Singleton::directories->current_path;
if(cmake_path.empty())
return;
CMake cmake(cmake_path);
auto executables = cmake.get_functions_parameters("add_executable"); auto executables = cmake.get_functions_parameters("add_executable");
boost::filesystem::path executable_path; boost::filesystem::path executable_path;
if(executables.size()>0 && executables[0].second.size()>0) { if(executables.size()>0 && executables[0].second.size()>0) {
@ -472,9 +479,16 @@ void Window::set_menu_actions() {
} }
}); });
menu->add_action("compile", [this]() { menu->add_action("compile", [this]() {
if(notebook.get_current_page()==-1 || compiling) if(compiling)
return;
boost::filesystem::path cmake_path;
if(notebook.get_current_page()!=-1)
cmake_path=notebook.get_current_view()->file_path.parent_path();
else
cmake_path=Singleton::directories->current_path;
if(cmake_path.empty())
return; return;
CMake cmake(notebook.get_current_view()->file_path); CMake cmake(cmake_path);
if(cmake.project_path!="") { if(cmake.project_path!="") {
compiling=true; compiling=true;
Singleton::terminal->print("Compiling project "+cmake.project_path.string()+"\n"); Singleton::terminal->print("Compiling project "+cmake.project_path.string()+"\n");
@ -489,21 +503,13 @@ void Window::set_menu_actions() {
entry_box.labels.emplace_back(); entry_box.labels.emplace_back();
auto label_it=entry_box.labels.begin(); auto label_it=entry_box.labels.begin();
label_it->update=[label_it](int state, const std::string& message){ label_it->update=[label_it](int state, const std::string& message){
label_it->set_text("Run Command directory order: file project path, file directory, opened directory, current directory"); label_it->set_text("Run Command directory order: file project path, opened directory, current directory");
}; };
label_it->update(0, ""); label_it->update(0, "");
entry_box.entries.emplace_back(last_run_command, [this](const std::string& content){ entry_box.entries.emplace_back(last_run_command, [this](const std::string& content){
if(content!="") { if(content!="") {
last_run_command=content; last_run_command=content;
boost::filesystem::path run_path; auto run_path=notebook.get_current_folder();
if(notebook.get_current_page()!=-1) {
if(notebook.get_current_view()->project_path!="")
run_path=notebook.get_current_view()->project_path;
else
run_path=notebook.get_current_view()->file_path.parent_path();
}
else
run_path=Singleton::directories->current_path;
Singleton::terminal->async_print("Running: "+content+'\n'); Singleton::terminal->async_print("Running: "+content+'\n');
Singleton::terminal->async_execute(content, run_path, [this, content](int exit_code){ Singleton::terminal->async_execute(content, run_path, [this, content](int exit_code){
@ -776,8 +782,8 @@ void Window::goto_line_entry() {
if(line>0 && line<=buffer->get_line_count()) { if(line>0 && line<=buffer->get_line_count()) {
line--; line--;
buffer->place_cursor(buffer->get_iter_at_line(line)); buffer->place_cursor(buffer->get_iter_at_line(line));
while(gtk_events_pending()) while(g_main_context_pending(NULL))
gtk_main_iteration(); g_main_context_iteration(NULL, false);
if(notebook.get_current_page()!=-1) if(notebook.get_current_page()!=-1)
notebook.get_current_view()->scroll_to(buffer->get_insert(), 0.0, 1.0, 0.5); notebook.get_current_view()->scroll_to(buffer->get_insert(), 0.0, 1.0, 0.5);
} }

Loading…
Cancel
Save