Browse Source

Merge branch 'master' of github.com:cppit/jucipp into ci

merge-requests/365/head
Jørgen Lien Sellæg 10 years ago
parent
commit
d69057aefd
  1. 7
      .gitmodules
  2. 2
      .travis.yml
  3. 52
      CMakeLists.txt
  4. 0
      cmake_modules/FindLibClang.cmake
  5. 0
      cmake_modules/FindPlantuml.cmake
  6. 97
      src/CMakeLists.txt
  7. 20
      src/cmake/Modules/FindLibClangmm.cmake
  8. 7
      src/config.cc
  9. 1
      src/config.h
  10. 2
      src/debug_clang.cc
  11. 2
      src/debug_clang.h
  12. 639
      src/files.h
  13. 24
      src/notebook.cc
  14. 7
      src/notebook.h
  15. 4
      src/project.cc
  16. 4
      src/project.h
  17. 61
      src/source.cc
  18. 7
      src/source.h
  19. 100
      src/source_clang.cc
  20. 61
      src/window.cc
  21. 75
      tests/CMakeLists.txt
  22. 2
      tests/cmake_build_test.cc
  23. 16
      tests/example_test.cc
  24. 71
      tests/lldb_test.cc
  25. 5
      tests/lldb_test_files/CMakeLists.txt
  26. 4
      tests/lldb_test_files/main.cpp
  27. 50
      tests/process_test.cc
  28. 81
      tests/source_clang_test.cc
  29. 1
      tests/source_clang_test_files/CMakeLists.txt
  30. 7
      tests/source_clang_test_files/build/compile_commands.json
  31. 15
      tests/source_clang_test_files/main.cpp
  32. 43
      tests/source_test.cc
  33. 5
      tests/stubs/dispatcher.cc
  34. 26
      tests/stubs/selectiondialog.cc
  35. 18
      tests/stubs/terminal.cc
  36. 16
      tests/stubs/tooltips.cc
  37. 0
      tests/tmp/.keep
  38. 2
      tiny-process-library

7
.gitmodules vendored

@ -1,7 +1,6 @@
[submodule "tiny-process-library"]
path = tiny-process-library
url = https://github.com/eidheim/tiny-process-library
branch = v1.0.4
[submodule "libclangmm"]
path = libclangmm
url = https://github.com/cppit/libclangmm
[submodule "tiny-process-library"]
path = tiny-process-library
url = https://github.com/eidheim/tiny-process-library

2
.travis.yml

@ -24,4 +24,4 @@ script:
- script=clean ./ci/execute.sh
- script=compile CXX=g++ CC=gcc ./ci/execute.sh
- script=static_analysis ./ci/execute.sh
- script=compile make_command="broadwayd & make test" ./ci/execute.sh
- script=compile make_command="broadwayd & CTEST_OUTPUT_ON_FAILURE=1 make test" ./ci/execute.sh

52
CMakeLists.txt

@ -1,16 +1,56 @@
cmake_minimum_required (VERSION 2.8.4)
cmake_minimum_required (VERSION 2.8.8)
set(project_name juci)
project (${project_name})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -Wall -Wextra -Wno-unused-parameter -Wno-reorder")
if(CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -undefined dynamic_lookup") #TODO: fix this
link_directories(/usr/local/lib /usr/local/opt/gettext/lib)
include_directories(/usr/local/opt/gettext/include)
set(CMAKE_MACOSX_RPATH 1)
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig")
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake_modules/")
find_package(LibClang REQUIRED)
#Find liblldb with the same version as the version of libclang found
string(REPLACE libclang liblldb LIBLLDB_LIBRARIES "${LIBCLANG_LIBRARIES}")
if(EXISTS "${LIBLLDB_LIBRARIES}")
set(LIBLLDB_FOUND TRUE)
elseif(EXISTS "${LIBLLDB_LIBRARIES}.1")
set(LIBLLDB_LIBRARIES "${LIBLLDB_LIBRARIES}.1")
set(LIBLLDB_FOUND TRUE)
endif()
if(LIBLLDB_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DJUCI_ENABLE_DEBUG")
else()
set(LIBLLDB_LIBRARIES "")
message("liblldb not found. Building juCi++ without debugging support")
endif()
find_package(Boost 1.54 COMPONENTS regex system filesystem REQUIRED)
find_package(ASPELL REQUIRED)
include(FindPkgConfig)
pkg_check_modules(GTKMM gtkmm-3.0 REQUIRED)
pkg_check_modules(GTKSVMM gtksourceviewmm-3.0 REQUIRED)
add_subdirectory("src")
#TODO: instead of the if-expression below, disable tests on Travis CI for clang++ builds
if(NOT (("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") AND (NOT $ENV{distribution} STREQUAL "")))
if(ENABLE_TESTING)
enable_testing()
add_subdirectory(tests)
endif()
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD")
install(FILES "${CMAKE_SOURCE_DIR}/share/juci.desktop"
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/applications")
endif()
if(ENABLE_TESTING)
enable_testing()
add_subdirectory(tests)
endif()

0
src/cmake/Modules/FindLibClang.cmake → cmake_modules/FindLibClang.cmake

0
src/cmake/Modules/FindPlantuml.cmake → cmake_modules/FindPlantuml.cmake

97
src/CMakeLists.txt

@ -1,15 +1,3 @@
add_definitions(-DBOOST_LOG_DYN_LINK)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++11 -pthread -Wall -Wextra -Wno-unused-parameter -Wno-reorder")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules/")
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -undefined dynamic_lookup")
link_directories(/usr/local/lib /usr/local/opt/gettext/lib)
include_directories(/usr/local/opt/gettext/include)
set(CMAKE_MACOSX_RPATH 1)
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig")
endif()
if(UNIX) #Checking if compiling on Ubuntu that for instance has a buggy menu system
find_program(LSB_RELEASE_BIN lsb_release)
if(LSB_RELEASE_BIN)
@ -25,89 +13,51 @@ if(MSYS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMSYS_PROCESS_USE_SH")
endif()
find_package(LibClang REQUIRED)
find_package(Boost 1.54 COMPONENTS regex system filesystem REQUIRED)
find_package(ASPELL REQUIRED)
set(LIBCLANGMM_INCLUDE_DIR ../libclangmm/src)
set(TINY_PROCESS_INCLUDE_DIR ../tiny-process-library)
string(REPLACE libclang liblldb LIBLLDB_LIBRARIES "${LIBCLANG_LIBRARIES}")
if(EXISTS "${LIBLLDB_LIBRARIES}")
set(LIBLLDB_FOUND TRUE)
elseif(EXISTS "${LIBLLDB_LIBRARIES}.1")
set(LIBLLDB_LIBRARIES "${LIBLLDB_LIBRARIES}.1")
set(LIBLLDB_FOUND TRUE)
endif()
if(LIBLLDB_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DJUCI_ENABLE_DEBUG")
else()
set(LIBLLDB_LIBRARIES "")
message("liblldb not found. Building juCi++ without debugging support")
endif()
include(FindPkgConfig)
pkg_check_modules(GTKMM gtkmm-3.0 REQUIRED)
pkg_check_modules(GTKSVMM gtksourceviewmm-3.0 REQUIRED)
set(global_includes
${Boost_INCLUDE_DIRS}
${GTKMM_INCLUDE_DIRS}
${GTKSVMM_INCLUDE_DIRS}
${LIBCLANG_INCLUDE_DIRS}
${LIBCLANGMM_INCLUDE_DIR}
${ASPELL_INCLUDE_DIR}
${TINY_PROCESS_INCLUDE_DIR}
../libclangmm/src
../tiny-process-library
.
)
set(global_libraries
${LIBCLANG_LIBRARIES}
${GTKMM_LIBRARIES}
${GTKSVMM_LIBRARIES}
${Boost_LIBRARIES}
${ASPELL_LIBRARIES}
${LIBCLANG_LIBRARIES}
${LIBLLDB_LIBRARIES}
${ASPELL_LIBRARIES}
)
set(project_files
cmake.cc
cmake.h
config.cc
config.h
dialogs.cc
dialogs.h
dialogs_unix.cc
directories.cc
directories.h
dispatcher.cc
dispatcher.h
entrybox.cc
entrybox.h
files.h
filesystem.cc
filesystem.h
info.h
info.cc
juci.cc
juci.h
menu.cc
menu.h
notebook.cc
notebook.h
project.cc
project.h
project_build.h
project_build.cc
selectiondialog.cc
selectiondialog.h
source.cc
source.h
source_clang.cc
source_clang.h
terminal.cc
terminal.h
tooltips.cc
tooltips.h
window.cc
window.h
)
#Files used both in ../src and ../tests
set(project_shared_files
cmake.cc
dispatcher.cc
filesystem.cc
project_build.cc
source.cc
source_clang.cc
../libclangmm/src/CodeCompleteResults.cc
../libclangmm/src/CompilationDatabase.cc
@ -123,25 +73,28 @@ set(project_files
../libclangmm/src/Tokens.cc
../libclangmm/src/TranslationUnit.cc
../libclangmm/src/Utility.cc
../tiny-process-library/process.cpp)
../tiny-process-library/process.cpp
)
if(LIBLLDB_FOUND)
list(APPEND project_files debug_clang.h debug_clang.cc)
list(APPEND project_shared_files debug_clang.cc)
endif()
if(MSYS)
list(APPEND project_files dialogs_unix.cc ../tiny-process-library/process_win.cpp)
list(APPEND project_shared_files ../tiny-process-library/process_win.cpp)
else()
list(APPEND project_files dialogs_unix.cc ../tiny-process-library/process_unix.cpp)
list(APPEND project_shared_files ../tiny-process-library/process_unix.cpp)
endif()
include_directories(${global_includes})
add_library(project_shared OBJECT ${project_shared_files})
if(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") AND (NOT $ENV{distribution} STREQUAL ""))
add_library(${project_name} OBJECT ${project_files})
else()
add_executable(${project_name} ${project_files})
add_executable(${project_name} ${project_files} $<TARGET_OBJECTS:project_shared>)
target_link_libraries(${project_name} ${global_libraries})
install(TARGETS ${project_name}
RUNTIME DESTINATION bin

20
src/cmake/Modules/FindLibClangmm.cmake

@ -1,20 +0,0 @@
# LCL_FOUND - Libclangmm is available
# LCL_INCLUDE_DIRS - The libclangmm include directories
# LCL_LIBRARIES -
find_package(PkgConfig)
find_path(LCL_INCLUDE_DIR clangmm.h
PATH_SUFFIXES libclangmm
)
find_library(LCL_LIBRARY NAMES clangmm)
set(LCL_LIBRARIES ${LCL_LIBRARY} )
set(LCL_INCLUDE_DIRS ${LCL_INCLUDE_DIR} )
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LCL DEFAULT_MSG
LCL_LIBRARY LCL_INCLUDE_DIR)
mark_as_advanced(LCL_INCLUDE_DIR LCL_LIBRARY )

7
src/config.cc

@ -49,7 +49,7 @@ void Config::load() {
catch(const std::exception &e) {
::Terminal::get().print("Error: could not parse "+config_json+": "+e.what()+"\n", true);
std::stringstream ss;
ss << configjson;
ss << default_config_file;
boost::property_tree::read_json(ss, cfg);
retrieve_config();
}
@ -63,7 +63,7 @@ void Config::find_or_create_config_files() {
boost::filesystem::create_directories(config_dir); // io exp captured by calling method
if (!boost::filesystem::exists(config_json))
filesystem::write(config_json, configjson);
filesystem::write(config_json, default_config_file);
auto juci_style_path = home/"styles";
boost::filesystem::create_directories(juci_style_path); // io exp captured by calling method
@ -160,7 +160,7 @@ void Config::update_config_file() {
try {
if(cfg.get<std::string>("version")!=JUCI_VERSION) {
std::stringstream ss;
ss << configjson;
ss << default_config_file;
boost::property_tree::read_json(ss, default_cfg);
cfg_ok=false;
if(cfg.count("version")>0)
@ -196,6 +196,7 @@ void Config::get_source() {
source.default_tab_char = source_json.get<char>("default_tab_char");
source.default_tab_size = source_json.get<unsigned>("default_tab_size");
source.auto_tab_char_and_size = source_json.get<bool>("auto_tab_char_and_size");
source.tab_indents_line = source_json.get<bool>("tab_indents_line");
source.wrap_lines = source_json.get<bool>("wrap_lines");

1
src/config.h

@ -64,6 +64,7 @@ public:
bool auto_tab_char_and_size;
char default_tab_char;
unsigned default_tab_size;
bool tab_indents_line;
bool wrap_lines;
bool highlight_current_line;
bool show_line_numbers;

2
src/debug_clang.cc

@ -357,7 +357,7 @@ void Debug::Clang::select_frame(uint32_t frame_index, uint32_t thread_index_id)
}
}
void Debug::Clang::delete_debug() {
void Debug::Clang::cancel() {
kill();
if(debug_thread.joinable())
debug_thread.join();

2
src/debug_clang.h

@ -55,7 +55,7 @@ namespace Debug {
std::vector<Variable> get_variables();
void select_frame(uint32_t frame_index, uint32_t thread_index_id=0);
void delete_debug(); //can't use delete as function name
void cancel();
std::string get_value(const std::string &variable, const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index);
std::string get_return_value(const boost::filesystem::path &file_path, unsigned int line_nr, unsigned int line_index);

639
src/files.h

@ -2,331 +2,342 @@
#define JUCI_FILES_H_
#include <string>
#define JUCI_VERSION "1.1.3-3"
const std::string configjson =
"{\n"
" \"version\": \""+std::string(JUCI_VERSION)+"\",\n"
" \"default_window_size\": {\n"
" \"width\": 800,\n"
" \"height\": 600\n"
" },\n"
" \"gtk_theme\": {\n"
" \"name_comment\": \"Use \\\"\\\" for default theme, At least these two exist on all systems: Adwaita, Raleigh\",\n"
" \"name\": \"\",\n"
" \"variant_comment\": \"Use \\\"\\\" for default variant, and \\\"dark\\\" for dark theme variant. Note that not all themes support dark variant, but for instance Adwaita does\",\n"
" \"variant\": \"\"\n"
" },\n"
" \"terminal\": {\n"
" \"history_size\": 1000,\n"
" \"font_comment\": \"Use \\\"\\\" to use source.font with slightly smaller size\",\n"
" \"font\": \"\"\n"
" },\n"
" \"source\": {\n"
" \"style_comment\": \"Use \\\"\\\" for default style, and for instance juci-dark or juci-dark-blue together with dark gtk_theme variant. Styles from normal gtksourceview install: classic, cobalt, kate, oblivion, solarized-dark, solarized-light, tango\",\n"
" \"style\": \"juci-light\",\n"
" \"font_comment\": \"Use \\\"\\\" for default font, and for instance \\\"Monospace 12\\\" to also set size\",\n"
#define JUCI_VERSION "1.1.3-4"
const std::string default_config_file = R"RAW({
"version": ")RAW"+std::string(JUCI_VERSION)+R"RAW(",
"default_window_size": {
"width": 800,
"height": 600
},
"gtk_theme": {
"name_comment": "Use \"\" for default theme, At least these two exist on all systems: Adwaita, Raleigh",
"name": "",
"variant_comment": "Use \"\" for default variant, and \"dark\" for dark theme variant. Note that not all themes support dark variant, but for instance Adwaita does",
"variant": ""
},
"terminal": {
"history_size": 1000,
"font_comment": "Use \"\" to use source.font with slightly smaller size",
"font": ""
},
"source": {
"style_comment": "Use \"\" for default style, and for instance juci-dark or juci-dark-blue together with dark gtk_theme variant. Styles from normal gtksourceview install: classic, cobalt, kate, oblivion, solarized-dark, solarized-light, tango",
"style": "juci-light",
"font_comment": "Use \"\" for default font, and for instance \"Monospace 12\" to also set size",)RAW"
#ifdef __APPLE__
" \"font\": \"Menlo 11\",\n"
R"RAW(
"font": "Menlo 11",)RAW"
#else
#ifdef _WIN32
" \"font\": \"Consolas\",\n"
R"RAW(
"font": "Consolas",)RAW"
#else
" \"font\": \"Monospace\",\n"
R"RAW(
"font": "Monospace",)RAW"
#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_whitespace_characters_comment\": \"Determines what kind of whitespaces should be drawn. Use comma-separated list of: space, tab, newline, nbsp, leading, text, trailing or all\",\n"
" \"show_whitespace_characters\": \"\",\n"
" \"show_map\": true,\n"
" \"map_font_size\": \"1\",\n"
" \"spellcheck_language_comment\": \"Use \\\"\\\" to set language from your locale settings\",\n"
" \"spellcheck_language\": \"en_US\",\n"
" \"auto_tab_char_and_size_comment\": \"Use false to always use default tab char and size\",\n"
" \"auto_tab_char_and_size\": true,\n"
" \"default_tab_char_comment\": \"Use \\\"\\t\\\" for regular tab\",\n"
" \"default_tab_char\": \" \",\n"
" \"default_tab_size\": 2,\n"
" \"wrap_lines\": false,\n"
" \"highlight_current_line\": true,\n"
" \"show_line_numbers\": true,\n"
" \"clang_types\": {\n"
" \"8\": \"def:function\",\n"
" \"21\": \"def:function\",\n"
" \"22\": \"def:identifier\",\n"
" \"24\": \"def:function\",\n"
" \"25\": \"def:function\",\n"
" \"43\": \"def:type\",\n"
" \"44\": \"def:type\",\n"
" \"45\": \"def:type\",\n"
" \"46\": \"def:identifier\",\n"
" \"109\": \"def:string\",\n"
" \"702\": \"def:statement\",\n"
" \"705\": \"def:comment\"\n"
" },\n"
" \"clang_format_style_comment\": \"IndentWidth, AccessModifierOffset and UseTab are set automatically. See http://clang.llvm.org/docs/ClangFormatStyleOptions.html\",\n"
" \"clang_format_style\": \"ColumnLimit: 0, MaxEmptyLinesToKeep: 2\"\n"
" },\n"
" \"keybindings\": {\n"
" \"preferences\": \"<primary>comma\",\n"
" \"quit\": \"<primary>q\",\n"
" \"new_file\": \"<primary>n\",\n"
" \"new_folder\": \"<primary><shift>n\",\n"
" \"open_file\": \"<primary>o\",\n"
" \"open_folder\": \"<primary><shift>o\",\n"
" \"save\": \"<primary>s\",\n"
" \"save_as\": \"<primary><shift>s\",\n"
" \"print\": \"<primary>p\",\n"
" \"edit_undo\": \"<primary>z\",\n"
" \"edit_redo\": \"<primary><shift>z\",\n"
" \"edit_cut\": \"<primary>x\",\n"
" \"edit_copy\": \"<primary>c\",\n"
" \"edit_paste\": \"<primary>v\",\n"
" \"edit_find\": \"<primary>f\",\n"
" \"edit_set_tab\": \"\",\n"
" \"source_spellcheck\": \"\",\n"
" \"source_spellcheck_clear\": \"\",\n"
" \"source_spellcheck_next_error\": \"<primary><shift>e\",\n"
" \"source_indentation_set_buffer_tab\": \"\",\n"
" \"source_indentation_auto_indent_buffer\": \"<primary><shift>i\",\n"
" \"source_goto_line\": \"<primary>g\",\n"
" \"source_center_cursor\": \"<primary>l\",\n"
" \"source_find_documentation\": \"<primary><shift>d\",\n"
" \"source_goto_declaration\": \"<primary>d\",\n"
" \"source_goto_implementation\": \"<primary>i\",\n"
" \"source_goto_usage\": \"<primary>u\",\n"
" \"source_goto_method\": \"<primary>m\",\n"
" \"source_rename\": \"<primary>r\",\n"
" \"source_goto_next_diagnostic\": \"<primary>e\",\n"
" \"source_apply_fix_its\": \"<control>space\",\n"
" \"project_set_run_arguments\": \"\",\n"
" \"compile_and_run\": \"<primary>Return\",\n"
" \"compile\": \"<primary><shift>Return\",\n"
" \"run_command\": \"<alt>Return\",\n"
" \"kill_last_running\": \"<primary>Escape\",\n"
" \"force_kill_last_running\": \"<primary><shift>Escape\",\n"
" \"debug_set_run_arguments\": \"\",\n"
" \"debug_start_continue\": \"<primary>y\",\n"
" \"debug_stop\": \"<primary><shift>y\",\n"
" \"debug_kill\": \"<primary><shift>k\",\n"
" \"debug_step_over\": \"<primary>j\",\n"
" \"debug_step_into\": \"<primary>t\",\n"
" \"debug_step_out\": \"<primary><shift>t\",\n"
" \"debug_backtrace\": \"<primary><shift>j\",\n"
" \"debug_show_variables\": \"<primary><shift>b\",\n"
" \"debug_run_command\": \"<alt><shift>Return\",\n"
" \"debug_toggle_breakpoint\": \"<primary>b\",\n"
" \"debug_goto_stop\": \"<primary><shift>l\",\n"
R"RAW(
"cleanup_whitespace_characters_comment": "Remove trailing whitespace characters on save, and add trailing newline if missing",
"cleanup_whitespace_characters": false,
"show_whitespace_characters_comment": "Determines what kind of whitespaces should be drawn. Use comma-separated list of: space, tab, newline, nbsp, leading, text, trailing or all",
"show_whitespace_characters": "",
"show_map": true,
"map_font_size": "1",
"spellcheck_language_comment": "Use \"\" to set language from your locale settings",
"spellcheck_language": "en_US",
"auto_tab_char_and_size_comment": "Use false to always use default tab char and size",
"auto_tab_char_and_size": true,
"default_tab_char_comment": "Use \"\t\" for regular tab",
"default_tab_char": " ",
"default_tab_size": 2,
"tab_indents_line": true,
"wrap_lines": false,
"highlight_current_line": true,
"show_line_numbers": true,
"clang_types": {
"8": "def:function",
"21": "def:function",
"22": "def:identifier",
"24": "def:function",
"25": "def:function",
"43": "def:type",
"44": "def:type",
"45": "def:type",
"46": "def:identifier",
"109": "def:string",
"702": "def:statement",
"705": "def:comment"
},
"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"
},
"keybindings": {
"preferences": "<primary>comma",
"quit": "<primary>q",
"new_file": "<primary>n",
"new_folder": "<primary><shift>n",
"open_file": "<primary>o",
"open_folder": "<primary><shift>o",
"save": "<primary>s",
"save_as": "<primary><shift>s",
"print": "<primary>p",
"edit_undo": "<primary>z",
"edit_redo": "<primary><shift>z",
"edit_cut": "<primary>x",
"edit_copy": "<primary>c",
"edit_paste": "<primary>v",
"edit_find": "<primary>f",
"edit_set_tab": "",
"source_spellcheck": "",
"source_spellcheck_clear": "",
"source_spellcheck_next_error": "<primary><shift>e",
"source_indentation_set_buffer_tab": "",
"source_indentation_auto_indent_buffer": "<primary><shift>i",
"source_goto_line": "<primary>g",
"source_center_cursor": "<primary>l",
"source_find_documentation": "<primary><shift>d",
"source_goto_declaration": "<primary>d",
"source_goto_implementation": "<primary>i",
"source_goto_usage": "<primary>u",
"source_goto_method": "<primary>m",
"source_rename": "<primary>r",
"source_goto_next_diagnostic": "<primary>e",
"source_apply_fix_its": "<control>space",
"project_set_run_arguments": "",
"compile_and_run": "<primary>Return",
"compile": "<primary><shift>Return",
"run_command": "<alt>Return",
"kill_last_running": "<primary>Escape",
"force_kill_last_running": "<primary><shift>Escape",
"debug_set_run_arguments": "",
"debug_start_continue": "<primary>y",
"debug_stop": "<primary><shift>y",
"debug_kill": "<primary><shift>k",
"debug_step_over": "<primary>j",
"debug_step_into": "<primary>t",
"debug_step_out": "<primary><shift>t",
"debug_backtrace": "<primary><shift>j",
"debug_show_variables": "<primary><shift>b",
"debug_run_command": "<alt><shift>Return",
"debug_toggle_breakpoint": "<primary>b",
"debug_goto_stop": "<primary><shift>l",)RAW"
#ifdef __linux
" \"next_tab\": \"<primary>Tab\",\n"
" \"previous_tab\": \"<primary><shift>Tab\",\n"
R"RAW(
"next_tab": "<primary>Tab",
"previous_tab": "<primary><shift>Tab",)RAW"
#else
" \"next_tab\": \"<primary><alt>Right\",\n"
" \"previous_tab\": \"<primary><alt>Left\",\n"
R"RAW(
"next_tab": "<primary><alt>Right",
"previous_tab": "<primary><alt>Left",)RAW"
#endif
" \"close_tab\": \"<primary>w\"\n"
" },\n"
" \"project\": {\n"
" \"default_build_path_comment\": \"Use <project_directory_name> to insert the project top level directory name\",\n"
" \"default_build_path\": \"./build\",\n"
" \"debug_build_path_comment\": \"Use <project_directory_name> to insert the project top level directory name, and <default_build_path> to insert your default_build_path setting.\",\n"
" \"debug_build_path\": \"<default_build_path>/debug\",\n"
R"RAW(
"close_tab": "<primary>w"
},
"project": {
"default_build_path_comment": "Use <project_directory_name> to insert the project top level directory name",
"default_build_path": "./build",
"debug_build_path_comment": "Use <project_directory_name> to insert the project top level directory name, and <default_build_path> to insert your default_build_path setting.",
"debug_build_path": "<default_build_path>/debug",)RAW"
#ifdef _WIN32
" \"cmake_command\": \"cmake -G\\\"MSYS Makefiles\\\"\",\n"
R"RAW(
"cmake_command": "cmake -G\"MSYS Makefiles\"",)RAW"
#else
" \"cmake_command\": \"cmake\",\n"
R"RAW(
"cmake_command": "cmake",)RAW"
#endif
" \"make_command\": \"cmake --build .\",\n"
" \"save_on_compile_or_run\": true,\n"
" \"clear_terminal_on_compile\": true\n"
" },\n"
" \"documentation_searches\": {\n"
" \"clang\": {\n"
" \"separator\": \"::\",\n"
" \"queries\": {\n"
" \"@empty\": \"https://www.google.com/search?btnI&q=c%2B%2B+\",\n"
" \"std\": \"https://www.google.com/search?btnI&q=site:http://www.cplusplus.com/reference/+\",\n"
" \"boost\": \"https://www.google.com/search?btnI&q=site:http://www.boost.org/doc/libs/1_59_0/+\",\n"
" \"Gtk\": \"https://www.google.com/search?btnI&q=site:https://developer.gnome.org/gtkmm/stable/+\",\n"
" \"@any\": \"https://www.google.com/search?btnI&q=\"\n"
" }\n"
" }\n"
" }\n"
"}\n";
const std::string juci_light_style =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"\n"
"<style-scheme id=\"juci-light\" _name=\"juci\" version=\"1.0\">\n"
" <author>juCi++ team</author>\n"
" <_description>Default juCi++ style</_description>\n"
"\n"
" <!-- Palette -->\n"
" <color name=\"white\" value=\"#FFFFFF\"/>\n"
" <color name=\"black\" value=\"#000000\"/>\n"
" <color name=\"gray\" value=\"#888888\"/>\n"
" <color name=\"red\" value=\"#CC0000\"/>\n"
" <color name=\"green\" value=\"#008800\"/>\n"
" <color name=\"blue\" value=\"#0000FF\"/>\n"
" <color name=\"dark-blue\" value=\"#002299\"/>\n"
" <color name=\"yellow\" value=\"#FFFF00\"/>\n"
" <color name=\"light-yellow\" value=\"#FFFF88\"/>\n"
" <color name=\"orange\" value=\"#FF8800\"/>\n"
" <color name=\"purple\" value=\"#990099\"/>\n"
"\n"
" <style name=\"text\" foreground=\"#000000\" background=\"#FFFFFF\"/>\n"
" <style name=\"background-pattern\" background=\"#rgba(0,0,0,.03)\"/>\n"
" <style name=\"selection\" background=\"#4A90D9\"/>\n"
"\n"
" <!-- Current Line Highlighting -->\n"
" <style name=\"current-line\" background=\"#rgba(0,0,0,.07)\"/>\n"
"\n"
" <!-- Bracket Matching -->\n"
" <style name=\"bracket-match\" foreground=\"white\" background=\"gray\" bold=\"true\"/>\n"
" <style name=\"bracket-mismatch\" foreground=\"white\" background=\"#FF0000\" bold=\"true\"/>\n"
"\n"
" <!-- Search Matching -->\n"
" <style name=\"search-match\" background=\"yellow\"/>\n"
"\n"
" <!-- Language specifics -->\n"
" <style name=\"def:builtin\" foreground=\"blue\"/>\n"
" <style name=\"def:constant\" foreground=\"blue\"/>\n"
" <style name=\"def:boolean\" foreground=\"red\"/>\n"
" <style name=\"def:decimal\" foreground=\"red\"/>\n"
" <style name=\"def:base-n-integer\" foreground=\"red\"/>\n"
" <style name=\"def:floating-point\" foreground=\"red\"/>\n"
" <style name=\"def:complex\" foreground=\"red\"/>\n"
" <style name=\"def:character\" foreground=\"red\"/>\n"
" <style name=\"def:special-char\" foreground=\"red\"/>\n"
"\n\n"
" <!-- Language specifics used by clang-parser in default config -->\n"
" <style name=\"def:string\" foreground=\"red\"/>\n"
" <style name=\"def:comment\" foreground=\"gray\"/>\n"
" <style name=\"def:statement\" foreground=\"blue\"/>\n"
" <style name=\"def:type\" foreground=\"blue\"/>\n"
" <style name=\"def:function\" foreground=\"dark-blue\"/>\n"
" <style name=\"def:identifier\" foreground=\"purple\"/>\n"
" <style name=\"def:preprocessor\" foreground=\"green\"/>\n"
" <style name=\"def:error\" foreground=\"red\"/>\n"
" <style name=\"def:warning\" foreground=\"orange\"/>\n"
" <style name=\"def:note\" foreground=\"black\" background=\"light-yellow\"/>\n"
"\n"
"</style-scheme>\n";
const std::string juci_dark_style =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"\n"
"<style-scheme id=\"juci-dark\" _name=\"juci\" version=\"1.0\">\n"
" <author>juCi++ team</author>\n"
" <_description>Dark juCi++ style</_description>\n"
"\n"
" <!-- Palette -->\n"
" <color name=\"white\" value=\"#CCCCCC\"/>\n"
" <color name=\"black\" value=\"#292929\"/>\n"
" <color name=\"gray\" value=\"#888888\"/>\n"
" <color name=\"red\" value=\"#FF9999\"/>\n"
" <color name=\"green\" value=\"#AACC99\"/>\n"
" <color name=\"blue\" value=\"#9090FF\"/>\n"
" <color name=\"light-blue\" value=\"#AAAAFF\"/>\n"
" <color name=\"purple\" value=\"#DD88DD\"/>\n"
"\n"
" <style name=\"text\" foreground=\"white\" background=\"black\"/>\n"
" <style name=\"background-pattern\" background=\"#rgba(255,255,255,.04)\"/>\n"
" <style name=\"selection\" background=\"#215D9C\"/>\n"
"\n"
" <!-- Current Line Highlighting -->\n"
" <style name=\"current-line\" background=\"#rgba(255,255,255,.06)\"/>\n"
"\n"
" <!-- Bracket Matching -->\n"
" <style name=\"bracket-match\" foreground=\"black\" background=\"gray\" bold=\"true\"/>\n"
" <style name=\"bracket-mismatch\" foreground=\"black\" background=\"#FF0000\" bold=\"true\"/>\n"
"\n"
" <!-- Search Matching -->\n"
" <style name=\"search-match\" foreground=\"black\" background=\"white\"/>\n"
"\n"
" <!-- Language specifics -->\n"
" <style name=\"def:builtin\" foreground=\"blue\"/>\n"
" <style name=\"def:constant\" foreground=\"blue\"/>\n"
" <style name=\"def:boolean\" foreground=\"red\"/>\n"
" <style name=\"def:decimal\" foreground=\"red\"/>\n"
" <style name=\"def:base-n-integer\" foreground=\"red\"/>\n"
" <style name=\"def:floating-point\" foreground=\"red\"/>\n"
" <style name=\"def:complex\" foreground=\"red\"/>\n"
" <style name=\"def:character\" foreground=\"red\"/>\n"
" <style name=\"def:special-char\" foreground=\"red\"/>\n"
"\n\n"
" <!-- Language specifics used by clang-parser in default config -->\n"
" <style name=\"def:string\" foreground=\"red\"/>\n"
" <style name=\"def:comment\" foreground=\"gray\"/>\n"
" <style name=\"def:statement\" foreground=\"blue\"/>\n"
" <style name=\"def:type\" foreground=\"blue\"/>\n"
" <style name=\"def:function\" foreground=\"light-blue\"/>\n"
" <style name=\"def:identifier\" foreground=\"purple\"/>\n"
" <style name=\"def:preprocessor\" foreground=\"green\"/>\n"
" <style name=\"def:error\" foreground=\"#FF6666\"/>\n"
" <style name=\"def:warning\" foreground=\"#FFE100\"/>\n"
" <style name=\"def:note\" foreground=\"white\" background=\"#444444\"/>\n"
"\n"
"</style-scheme>\n";
const std::string juci_dark_blue_style =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"\n"
"<style-scheme id=\"juci-dark-blue\" _name=\"juci\" version=\"1.0\">\n"
" <author>juCi++ team</author>\n"
" <_description>Dark blue juCi++ style based on the Emacs deeper blue theme</_description>\n"
"\n"
" <!-- Palette -->\n"
" <color name=\"white\" value=\"#D6D6D6\"/>\n"
" <color name=\"dark-blue\" value=\"#202233\"/>\n"
" <color name=\"gray\" value=\"#919191\"/>\n"
" <color name=\"red\" value=\"#FF7777\"/>\n"
" <color name=\"yellow\" value=\"#FFE100\"/>\n"
" <color name=\"light-yellow\" value=\"#EAC595\"/>\n"
" <color name=\"light-blue\" value=\"#00CCFF\"/>\n"
" <color name=\"green\" value=\"#14ECA8\"/>\n"
" <color name=\"blue\" value=\"#282A40\"/>\n"
" <color name=\"orange\" value=\"#FF8800\"/>\n"
" <color name=\"light-green\" value=\"#A0DB6B\"/>\n"
"\n"
" <style name=\"text\" foreground=\"white\" background=\"dark-blue\"/>\n"
" <style name=\"background-pattern\" background=\"#rgba(255,255,255,.04)\"/>\n"
" <style name=\"selection\" background=\"#215D9C\"/>\n"
"\n"
" <!-- Current Line Highlighting -->\n"
" <style name=\"current-line\" background=\"#rgba(255,255,255,.05)\"/>\n"
"\n"
" <!-- Bracket Matching -->\n"
" <style name=\"bracket-match\" foreground=\"dark-blue\" background=\"gray\" bold=\"true\"/>\n"
" <style name=\"bracket-mismatch\" foreground=\"dark-blue\" background=\"#FF0000\" bold=\"true\"/>\n"
"\n"
" <!-- Search Matching -->\n"
" <style name=\"search-match\" foreground=\"dark-blue\" background=\"white\"/>\n"
"\n"
" <!-- Language specifics -->\n"
" <style name=\"def:builtin\" foreground=\"light-blue\"/>\n"
" <style name=\"def:constant\" foreground=\"light-blue\"/>\n"
" <style name=\"def:boolean\" foreground=\"light-yellow\"/>\n"
" <style name=\"def:decimal\" foreground=\"light-yellow\"/>\n"
" <style name=\"def:base-n-integer\" foreground=\"light-yellow\"/>\n"
" <style name=\"def:floating-point\" foreground=\"light-yellow\"/>\n"
" <style name=\"def:complex\" foreground=\"light-yellow\"/>\n"
" <style name=\"def:character\" foreground=\"light-yellow\"/>\n"
" <style name=\"def:special-char\" foreground=\"light-yellow\"/>\n"
"\n\n"
" <!-- Language specifics used by clang-parser in default config -->\n"
" <style name=\"def:string\" foreground=\"light-yellow\"/>\n"
" <style name=\"def:comment\" foreground=\"gray\"/>\n"
" <style name=\"def:statement\" foreground=\"light-blue\"/>\n"
" <style name=\"def:type\" foreground=\"light-blue\"/>\n"
" <style name=\"def:function\" foreground=\"green\"/>\n"
" <style name=\"def:identifier\" foreground=\"light-green\"/>\n"
" <style name=\"def:preprocessor\" foreground=\"yellow\"/>\n"
" <style name=\"def:error\" foreground=\"red\"/>\n"
" <style name=\"def:warning\" foreground=\"yellow\"/>\n"
" <style name=\"def:note\" foreground=\"white\" background=\"#404466\"/>\n"
"\n"
"</style-scheme>\n";
R"RAW(
"make_command": "cmake --build .",
"save_on_compile_or_run": true,
"clear_terminal_on_compile": true
},
"documentation_searches": {
"clang": {
"separator": "::",
"queries": {
"@empty": "https://www.google.com/search?btnI&q=c%2B%2B+",
"std": "https://www.google.com/search?btnI&q=site:http://www.cplusplus.com/reference/+",
"boost": "https://www.google.com/search?btnI&q=site:http://www.boost.org/doc/libs/1_59_0/+",
"Gtk": "https://www.google.com/search?btnI&q=site:https://developer.gnome.org/gtkmm/stable/+",
"@any": "https://www.google.com/search?btnI&q="
}
}
}
}
)RAW";
const std::string juci_light_style = R"RAW(<?xml version="1.0" encoding="UTF-8"?>
<style-scheme id="juci-light" _name="juci" version="1.0">
<author>juCi++ team</author>
<_description>Default juCi++ style</_description>
<!-- Palette -->
<color name="white" value="#FFFFFF"/>
<color name="black" value="#000000"/>
<color name="gray" value="#888888"/>
<color name="red" value="#CC0000"/>
<color name="green" value="#008800"/>
<color name="blue" value="#0000FF"/>
<color name="dark-blue" value="#002299"/>
<color name="yellow" value="#FFFF00"/>
<color name="light-yellow" value="#FFFF88"/>
<color name="orange" value="#FF8800"/>
<color name="purple" value="#990099"/>
<style name="text" foreground="#000000" background="#FFFFFF"/>
<style name="background-pattern" background="#rgba(0,0,0,.03)"/>
<style name="selection" background="#4A90D9"/>
<!-- Current Line Highlighting -->
<style name="current-line" background="#rgba(0,0,0,.07)"/>
<!-- Bracket Matching -->
<style name="bracket-match" foreground="white" background="gray" bold="true"/>
<style name="bracket-mismatch" foreground="white" background="#FF0000" bold="true"/>
<!-- Search Matching -->
<style name="search-match" background="yellow"/>
<!-- Language specifics -->
<style name="def:builtin" foreground="blue"/>
<style name="def:constant" foreground="blue"/>
<style name="def:boolean" foreground="red"/>
<style name="def:decimal" foreground="red"/>
<style name="def:base-n-integer" foreground="red"/>
<style name="def:floating-point" foreground="red"/>
<style name="def:complex" foreground="red"/>
<style name="def:character" foreground="red"/>
<style name="def:special-char" foreground="red"/>
<!-- Language specifics used by clang-parser in default config -->
<style name="def:string" foreground="red"/>
<style name="def:comment" foreground="gray"/>
<style name="def:statement" foreground="blue"/>
<style name="def:type" foreground="blue"/>
<style name="def:function" foreground="dark-blue"/>
<style name="def:identifier" foreground="purple"/>
<style name="def:preprocessor" foreground="green"/>
<style name="def:error" foreground="red"/>
<style name="def:warning" foreground="orange"/>
<style name="def:note" foreground="black" background="light-yellow"/>
</style-scheme>
)RAW";
const std::string juci_dark_style = R"RAW(<?xml version="1.0" encoding="UTF-8"?>
<style-scheme id="juci-dark" _name="juci" version="1.0">
<author>juCi++ team</author>
<_description>Dark juCi++ style</_description>
<!-- Palette -->
<color name="white" value="#CCCCCC"/>
<color name="black" value="#292929"/>
<color name="gray" value="#888888"/>
<color name="red" value="#FF9999"/>
<color name="green" value="#AACC99"/>
<color name="blue" value="#9090FF"/>
<color name="light-blue" value="#AAAAFF"/>
<color name="purple" value="#DD88DD"/>
<style name="text" foreground="white" background="black"/>
<style name="background-pattern" background="#rgba(255,255,255,.04)"/>
<style name="selection" background="#215D9C"/>
<!-- Current Line Highlighting -->
<style name="current-line" background="#rgba(255,255,255,.06)"/>
<!-- Bracket Matching -->
<style name="bracket-match" foreground="black" background="gray" bold="true"/>
<style name="bracket-mismatch" foreground="black" background="#FF0000" bold="true"/>
<!-- Search Matching -->
<style name="search-match" foreground="black" background="white"/>
<!-- Language specifics -->
<style name="def:builtin" foreground="blue"/>
<style name="def:constant" foreground="blue"/>
<style name="def:boolean" foreground="red"/>
<style name="def:decimal" foreground="red"/>
<style name="def:base-n-integer" foreground="red"/>
<style name="def:floating-point" foreground="red"/>
<style name="def:complex" foreground="red"/>
<style name="def:character" foreground="red"/>
<style name="def:special-char" foreground="red"/>
<!-- Language specifics used by clang-parser in default config -->
<style name="def:string" foreground="red"/>
<style name="def:comment" foreground="gray"/>
<style name="def:statement" foreground="blue"/>
<style name="def:type" foreground="blue"/>
<style name="def:function" foreground="light-blue"/>
<style name="def:identifier" foreground="purple"/>
<style name="def:preprocessor" foreground="green"/>
<style name="def:error" foreground="#FF6666"/>
<style name="def:warning" foreground="#FFE100"/>
<style name="def:note" foreground="white" background="#444444"/>
</style-scheme>
)RAW";
const std::string juci_dark_blue_style = R"RAW(<?xml version="1.0" encoding="UTF-8"?>
<style-scheme id="juci-dark-blue" _name="juci" version="1.0">
<author>juCi++ team</author>
<_description>Dark blue juCi++ style based on the Emacs deeper blue theme</_description>
<!-- Palette -->
<color name="white" value="#D6D6D6"/>
<color name="dark-blue" value="#202233"/>
<color name="gray" value="#919191"/>
<color name="red" value="#FF7777"/>
<color name="yellow" value="#FFE100"/>
<color name="light-yellow" value="#EAC595"/>
<color name="light-blue" value="#00CCFF"/>
<color name="green" value="#14ECA8"/>
<color name="blue" value="#282A40"/>
<color name="orange" value="#FF8800"/>
<color name="light-green" value="#A0DB6B"/>
<style name="text" foreground="white" background="dark-blue"/>
<style name="background-pattern" background="#rgba(255,255,255,.04)"/>
<style name="selection" background="#215D9C"/>
<!-- Current Line Highlighting -->
<style name="current-line" background="#rgba(255,255,255,.05)"/>
<!-- Bracket Matching -->
<style name="bracket-match" foreground="dark-blue" background="gray" bold="true"/>
<style name="bracket-mismatch" foreground="dark-blue" background="#FF0000" bold="true"/>
<!-- Search Matching -->
<style name="search-match" foreground="dark-blue" background="white"/>
<!-- Language specifics -->
<style name="def:builtin" foreground="light-blue"/>
<style name="def:constant" foreground="light-blue"/>
<style name="def:boolean" foreground="light-yellow"/>
<style name="def:decimal" foreground="light-yellow"/>
<style name="def:base-n-integer" foreground="light-yellow"/>
<style name="def:floating-point" foreground="light-yellow"/>
<style name="def:complex" foreground="light-yellow"/>
<style name="def:character" foreground="light-yellow"/>
<style name="def:special-char" foreground="light-yellow"/>
<!-- Language specifics used by clang-parser in default config -->
<style name="def:string" foreground="light-yellow"/>
<style name="def:comment" foreground="gray"/>
<style name="def:statement" foreground="light-blue"/>
<style name="def:type" foreground="light-blue"/>
<style name="def:function" foreground="green"/>
<style name="def:identifier" foreground="light-green"/>
<style name="def:preprocessor" foreground="yellow"/>
<style name="def:error" foreground="red"/>
<style name="def:warning" foreground="yellow"/>
<style name="def:note" foreground="white" background="#404466"/>
</style-scheme>
)RAW";
#endif // JUCI_FILES_H_

24
src/notebook.cc

@ -24,17 +24,28 @@ namespace sigc {
#endif
}
Notebook::TabLabel::TabLabel(const boost::filesystem::path &path) : Gtk::Box(Gtk::ORIENTATION_HORIZONTAL) {
Notebook::TabLabel::TabLabel(const boost::filesystem::path &path, std::function<void()> on_close) {
set_can_focus(false);
set_tooltip_text(path.string());
hbox.set_can_focus(false);
label.set_text(path.filename().string()+' ');
label.set_can_focus(false);
button.set_image_from_icon_name("window-close-symbolic", Gtk::ICON_SIZE_MENU);
button.set_can_focus(false);
button.set_relief(Gtk::ReliefStyle::RELIEF_NONE);
pack_start(label, Gtk::PACK_SHRINK);
pack_end(button, Gtk::PACK_SHRINK);
hbox.pack_start(label, Gtk::PACK_SHRINK);
hbox.pack_end(button, Gtk::PACK_SHRINK);
add(hbox);
button.signal_clicked().connect(on_close);
signal_button_press_event().connect([on_close](GdkEventButton *event) {
if(event->button==GDK_BUTTON_MIDDLE) {
on_close();
return true;
}
return false;
});
show_all();
}
@ -135,16 +146,15 @@ void Notebook::open(const boost::filesystem::path &file_path) {
configure(source_views.size()-1);
//Set up tab label
tab_labels.emplace_back(new TabLabel(file_path));
auto source_view=source_views.back();
tab_labels.back()->button.signal_clicked().connect([this, source_view](){
tab_labels.emplace_back(new TabLabel(file_path, [this, source_view](){
for(int c=0;c<size();c++) {
if(get_view(c)==source_view) {
close(c);
break;
}
}
});
}));
append_page(*hboxes.back(), *tab_labels.back());
set_tab_reorderable(*hboxes.back(), true);

7
src/notebook.h

@ -10,11 +10,12 @@
#include <sigc++/sigc++.h>
class Notebook : public Gtk::Notebook {
class TabLabel : public Gtk::Box {
class TabLabel : public Gtk::EventBox {
Gtk::HBox hbox;
Gtk::Button button;
public:
TabLabel(const boost::filesystem::path &path);
TabLabel(const boost::filesystem::path &path, std::function<void()> on_close);
Gtk::Label label;
Gtk::Button button;
};
private:

4
src/project.cc

@ -504,9 +504,9 @@ void Project::Clang::debug_write(const std::string &buffer) {
Debug::Clang::get().write(buffer);
}
void Project::Clang::debug_delete() {
void Project::Clang::debug_cancel() {
std::unique_lock<std::mutex> lock(debug_start_mutex);
Debug::Clang::get().delete_debug();
Debug::Clang::get().cancel();
}
#endif

4
src/project.h

@ -52,7 +52,7 @@ namespace Project {
virtual void debug_remove_breakpoint(const boost::filesystem::path &file_path, int line_nr, int line_count) {}
virtual bool debug_is_running() { return false; }
virtual void debug_write(const std::string &buffer) {}
virtual void debug_delete() {}
virtual void debug_cancel() {}
};
class Clang : public Base {
@ -83,7 +83,7 @@ namespace Project {
void debug_remove_breakpoint(const boost::filesystem::path &file_path, int line_nr, int line_count) override;
bool debug_is_running() override;
void debug_write(const std::string &buffer) override;
void debug_delete() override;
void debug_cancel() override;
#endif
};

61
src/source.cc

@ -371,6 +371,31 @@ void Source::View::set_tab_char_and_size(char tab_char, unsigned tab_size) {
tab+=tab_char;
}
void Source::View::cleanup_whitespace_characters() {
auto buffer=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();
}
Gsv::DrawSpacesFlags Source::View::parse_show_whitespace_characters(const std::string &text) {
namespace qi = boost::spirit::qi;
@ -398,31 +423,8 @@ Gsv::DrawSpacesFlags Source::View::parse_show_whitespace_characters(const std::s
bool Source::View::save(const std::vector<Source::View*> &views) {
if(file_path.empty() || !get_buffer()->get_modified())
return false;
//Remove trailing whitespace characters on save, and add trailing newline if missing
if(Config::get().source.cleanup_whitespace_characters) {
auto buffer=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(Config::get().source.cleanup_whitespace_characters)
cleanup_whitespace_characters();
if(filesystem::write(file_path, get_buffer())) {
last_read_time=std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
@ -1217,8 +1219,13 @@ bool Source::View::on_key_press_event_basic(GdkEventKey* key) {
get_buffer()->end_user_action();
return true;
}
//Indent right when clicking tab, no matter where in the line the cursor is. Also works on selected text.
else if(key->keyval==GDK_KEY_Tab) {
else if(key->keyval==GDK_KEY_Tab && (key->state&GDK_SHIFT_MASK)==0) {
if(!Config::get().source.tab_indents_line && !get_buffer()->get_has_selection()) {
get_buffer()->insert_at_cursor(tab);
get_buffer()->end_user_action();
return true;
}
//Indent right when clicking tab, no matter where in the line the cursor is. Also works on selected text.
//Special case if insert is at beginning of empty line:
if(iter.starts_line() && iter.ends_line() && !get_buffer()->get_has_selection()) {
auto prev_line_iter=iter;

7
src/source.h

@ -73,15 +73,15 @@ namespace Source {
Glib::RefPtr<Gsv::Language> language;
std::function<void()> auto_indent;
std::function<Offset()> get_declaration_location;
std::function<Offset(const std::vector<Source::View*> &views)> get_declaration_location;
std::function<Offset(const std::vector<Source::View*> &views)> get_implementation_location;
std::function<std::vector<std::pair<Offset, std::string> >(const std::vector<Source::View*> &views)> get_usages;
std::function<void()> goto_method;
std::function<std::vector<std::pair<Offset, std::string> >()> get_methods;
std::function<std::vector<std::string>()> get_token_data;
std::function<std::string()> get_token_spelling;
std::function<std::vector<std::pair<boost::filesystem::path, size_t> >(const std::vector<Source::View*> &views, const std::string &text)> rename_similar_tokens;
std::function<void()> goto_next_diagnostic;
std::function<void()> apply_fix_its;
std::function<std::vector<FixIt>()> get_fix_its;
std::unique_ptr<CompletionDialog> autocomplete_dialog;
std::unique_ptr<SelectionDialog> selection_dialog;
@ -161,6 +161,7 @@ namespace Source {
guint previous_non_modifier_keyval=0;
guint last_keyval=0;
private:
void cleanup_whitespace_characters();
Gsv::DrawSpacesFlags parse_show_whitespace_characters(const std::string &text);
GtkSourceSearchContext *search_context;

100
src/source_clang.cc

@ -965,11 +965,10 @@ Source::ClangViewAutocomplete(file_path, language) {
}
});
get_declaration_location=[this](){
Offset location;
get_declaration_location=[this](const std::vector<Source::View*> &views){
if(!parsed) {
Info::get().print("Buffer is parsing");
return location;
return Offset();
}
auto iter=get_buffer()->get_insert()->get_iter();
auto line=static_cast<unsigned>(iter.get_line());
@ -980,16 +979,43 @@ Source::ClangViewAutocomplete(file_path, language) {
if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index <=token.offsets.second.index-1) {
auto referenced=cursor.get_referenced();
if(referenced) {
location.file_path=referenced.get_source_location().get_path();
auto clang_offset=referenced.get_source_location().get_offset();
location.line=clang_offset.line;
location.index=clang_offset.index;
break;
auto file_path=referenced.get_source_location().get_path();
//if declaration is implementation instead, attempt to find declaration
if(file_path==this->file_path && this->language && this->language->get_id()!="chdr" && this->language->get_id()!="cpphdr") {
auto identifier=Identifier(referenced.get_kind(), token.get_spelling(), referenced.get_usr());
std::vector<Source::View*> search_views;
for(auto &view: views) {
if(view->language && (view->language->get_id()=="chdr" || view->language->get_id()=="cpphdr"))
search_views.emplace_back(view);
}
search_views.emplace_back(this);
wait_parsing(search_views);
for(auto &view: search_views) {
if(auto clang_view=dynamic_cast<Source::ClangView*>(view)) {
for(auto &token: *clang_view->clang_tokens) {
auto cursor=token.get_cursor();
if(token.get_kind()==clang::TokenKind::Token_Identifier && cursor.has_type()) {
auto referenced=cursor.get_referenced();
if(referenced && identifier.kind==referenced.get_kind() &&
identifier.spelling==token.get_spelling() && identifier.usr==referenced.get_usr()) {
auto offset=referenced.get_source_location().get_offset();
return Offset(offset.line, offset.index, referenced.get_source_location().get_path());
}
}
}
}
}
}
auto offset=referenced.get_source_location().get_offset();
return Offset(offset.line, offset.index, file_path);
}
}
}
}
return location;
return Offset();
};
get_implementation_location=[this](const std::vector<Source::View*> &views){
@ -1086,18 +1112,14 @@ Source::ClangViewAutocomplete(file_path, language) {
return usages;
};
goto_method=[this](){
get_methods=[this](){
std::vector<std::pair<Offset, std::string> > methods;
if(!parsed) {
Info::get().print("Buffer is parsing");
return;
return methods;
}
auto iter=get_iter_for_dialog();
selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*this, get_buffer()->create_mark(iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, clang::Offset> >();
auto methods=clang_tokens->get_cxx_methods();
if(methods.size()==0)
return;
for(auto &method: methods) {
auto cxx_methods=clang_tokens->get_cxx_methods();
for(auto &method: cxx_methods) {
std::string row=std::to_string(method.second.line)+": "+Glib::Markup::escape_text(method.first);
//Add bold method token
size_t token_end_pos=row.find('(');
@ -1127,16 +1149,9 @@ Source::ClangViewAutocomplete(file_path, language) {
(row[pos]>='0' && row[pos]<='9') || row[pos]=='_' || row[pos]=='~') && pos>0);
row.insert(token_end_pos, "</b>");
row.insert(pos+1, "<b>");
(*rows)[row]=method.second;
selection_dialog->add_row(row);
methods.emplace_back(Offset(method.second.line, method.second.index), row);
}
selection_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) {
auto offset=rows->at(selected);
get_buffer()->place_cursor(get_buffer()->get_iter_at_line_index(offset.line-1, offset.index-1));
scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5);
delayed_tooltips_connection.disconnect();
};
selection_dialog->show();
return methods;
};
get_token_data=[this]() {
@ -1260,37 +1275,12 @@ Source::ClangViewAutocomplete(file_path, language) {
}
};
apply_fix_its=[this]() {
get_fix_its=[this]() {
if(!parsed) {
Info::get().print("Buffer is parsing");
return;
}
std::vector<std::pair<Glib::RefPtr<Gtk::TextMark>, Glib::RefPtr<Gtk::TextMark> > > fix_it_marks;
for(auto &fix_it: fix_its) {
auto start_iter=get_buffer()->get_iter_at_line_index(fix_it.offsets.first.line-1, fix_it.offsets.first.index-1);
auto end_iter=get_buffer()->get_iter_at_line_index(fix_it.offsets.second.line-1, fix_it.offsets.second.index-1);
fix_it_marks.emplace_back(get_buffer()->create_mark(start_iter), get_buffer()->create_mark(end_iter));
return std::vector<FixIt>();
}
size_t c=0;
get_buffer()->begin_user_action();
for(auto &fix_it: fix_its) {
if(fix_it.type==FixIt::Type::INSERT) {
get_buffer()->insert(fix_it_marks[c].first->get_iter(), fix_it.source);
}
if(fix_it.type==FixIt::Type::REPLACE) {
get_buffer()->erase(fix_it_marks[c].first->get_iter(), fix_it_marks[c].second->get_iter());
get_buffer()->insert(fix_it_marks[c].first->get_iter(), fix_it.source);
}
if(fix_it.type==FixIt::Type::ERASE) {
get_buffer()->erase(fix_it_marks[c].first->get_iter(), fix_it_marks[c].second->get_iter());
}
c++;
}
for(auto &mark_pair: fix_it_marks) {
get_buffer()->delete_mark(mark_pair.first);
get_buffer()->delete_mark(mark_pair.second);
}
get_buffer()->end_user_action();
return fix_its;
};
}

61
src/window.cc

@ -435,7 +435,7 @@ void Window::set_menu_actions() {
menu.add_action("source_goto_declaration", [this]() {
if(notebook.get_current_page()!=-1) {
if(notebook.get_current_view()->get_declaration_location) {
auto location=notebook.get_current_view()->get_declaration_location();
auto location=notebook.get_current_view()->get_declaration_location(notebook.source_views);
if(location) {
boost::filesystem::path declaration_file;
boost::system::error_code ec;
@ -517,8 +517,25 @@ void Window::set_menu_actions() {
});
menu.add_action("source_goto_method", [this]() {
if(notebook.get_current_page()!=-1) {
if(notebook.get_current_view()->goto_method) {
notebook.get_current_view()->goto_method();
auto view=notebook.get_current_view();
if(view->get_methods) {
auto methods=notebook.get_current_view()->get_methods();
if(!methods.empty()) {
auto iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, Source::Offset> >();
for(auto &method: methods) {
(*rows)[method.second]=method.first;
view->selection_dialog->add_row(method.second);
}
view->selection_dialog->on_select=[view, rows](const std::string& selected, bool hide_window) {
auto offset=rows->at(selected);
view->get_buffer()->place_cursor(view->get_buffer()->get_iter_at_line_index(offset.line-1, offset.index-1));
view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5);
view->delayed_tooltips_connection.disconnect();
};
view->selection_dialog->show();
}
}
}
});
@ -535,8 +552,36 @@ void Window::set_menu_actions() {
});
menu.add_action("source_apply_fix_its", [this]() {
if(notebook.get_current_page()!=-1) {
if(notebook.get_current_view()->apply_fix_its) {
notebook.get_current_view()->apply_fix_its();
auto view=notebook.get_current_view();
if(view->get_fix_its) {
auto buffer=view->get_buffer();
auto fix_its=view->get_fix_its();
std::vector<std::pair<Glib::RefPtr<Gtk::TextMark>, Glib::RefPtr<Gtk::TextMark> > > fix_it_marks;
for(auto &fix_it: fix_its) {
auto start_iter=buffer->get_iter_at_line_index(fix_it.offsets.first.line-1, fix_it.offsets.first.index-1);
auto end_iter=buffer->get_iter_at_line_index(fix_it.offsets.second.line-1, fix_it.offsets.second.index-1);
fix_it_marks.emplace_back(buffer->create_mark(start_iter), buffer->create_mark(end_iter));
}
size_t c=0;
buffer->begin_user_action();
for(auto &fix_it: fix_its) {
if(fix_it.type==Source::FixIt::Type::INSERT) {
buffer->insert(fix_it_marks[c].first->get_iter(), fix_it.source);
}
if(fix_it.type==Source::FixIt::Type::REPLACE) {
buffer->erase(fix_it_marks[c].first->get_iter(), fix_it_marks[c].second->get_iter());
buffer->insert(fix_it_marks[c].first->get_iter(), fix_it.source);
}
if(fix_it.type==Source::FixIt::Type::ERASE) {
buffer->erase(fix_it_marks[c].first->get_iter(), fix_it_marks[c].second->get_iter());
}
c++;
}
for(auto &mark_pair: fix_it_marks) {
buffer->delete_mark(mark_pair.first);
buffer->delete_mark(mark_pair.second);
}
buffer->end_user_action();
}
}
});
@ -790,10 +835,10 @@ void Window::activate_menu_items(bool activate) {
menu.actions["source_goto_declaration"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_declaration_location) : false);
menu.actions["source_goto_implementation"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_implementation_location) : false);
menu.actions["source_goto_usage"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_usages) : false);
menu.actions["source_goto_method"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->goto_method) : false);
menu.actions["source_goto_method"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_methods) : false);
menu.actions["source_rename"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->rename_similar_tokens) : false);
menu.actions["source_goto_next_diagnostic"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->goto_next_diagnostic) : false);
menu.actions["source_apply_fix_its"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->apply_fix_its) : false);
menu.actions["source_apply_fix_its"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_fix_its) : false);
#ifdef JUCI_ENABLE_DEBUG
if(notebook.get_current_page()!=-1) {
auto view=notebook.get_current_view();
@ -865,7 +910,7 @@ bool Window::on_delete_event(GdkEventAny *event) {
Terminal::get().kill_async_processes();
#ifdef JUCI_ENABLE_DEBUG
if(Project::current)
Project::current->debug_delete();
Project::current->debug_cancel();
#endif
return false;
}

75
tests/CMakeLists.txt

@ -1,57 +1,62 @@
add_definitions(-DBOOST_LOG_DYN_LINK)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -Wall -Wextra -Wno-unused-parameter -Wno-reorder")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DJUCI_TESTS_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}\\\"")
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -undefined dynamic_lookup")
link_directories(/usr/local/lib /usr/local/opt/gettext/lib)
include_directories(/usr/local/opt/gettext/include)
set(CMAKE_MACOSX_RPATH 1)
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig")
endif()
find_package(Boost 1.54 COMPONENTS regex system filesystem REQUIRED)
set(LIBCLANGMM_INCLUDE_DIR ../libclangmm/src)
include(FindPkgConfig)
pkg_check_modules(GTKMM gtkmm-3.0 REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-access-control -DJUCI_BUILD_PATH=\\\"${CMAKE_BINARY_DIR}\\\" -DJUCI_TESTS_PATH=\\\"${CMAKE_CURRENT_SOURCE_DIR}\\\"")
set(global_includes
${Boost_INCLUDE_DIRS}
${GTKMM_INCLUDE_DIRS}
${GTKSVMM_INCLUDE_DIRS}
../src
${LIBCLANG_INCLUDE_DIRS}
${ASPELL_INCLUDE_DIR}
../libclangmm/src
../tiny-process-library
../src
)
set(global_libraries
${GTKMM_LIBRARIES}
${GTKSVMM_LIBRARIES}
${Boost_LIBRARIES}
${LIBCLANG_LIBRARIES}
${LIBLLDB_LIBRARIES}
${ASPELL_LIBRARIES}
)
set(stub_sources
set(stub_files
stubs/config.cc
stubs/dialogs.cc
stubs/dispatcher.cc
stubs/info.cc
stubs/selectiondialog.cc
stubs/terminal.cc
stubs/tooltips.cc
)
include_directories(${global_includes})
add_library(stubs_library ${stub_sources})
add_library(stubs OBJECT ${stub_files})
add_executable(cmake_test cmake_test.cc
../src/filesystem.cc ../src/cmake.cc ../src/project_build.cc)
target_link_libraries(cmake_test ${global_libraries} stubs_library)
add_test(cmake_test cmake_test)
include_directories(${global_includes})
#Added for example only, and requires display server to work
#However, it is possible to use the Broadway backend if the test is run in a pure terminal environment:
#broadwayd&
#make test
add_executable(example_test example_test.cc)
target_link_libraries(example_test ${global_libraries} stubs_library)
add_test(example_test example_test)
add_executable(process_test process_test.cc
$<TARGET_OBJECTS:project_shared> $<TARGET_OBJECTS:stubs>)
target_link_libraries(process_test ${global_libraries})
add_test(process_test process_test)
add_executable(cmake_build_test cmake_build_test.cc
$<TARGET_OBJECTS:project_shared> $<TARGET_OBJECTS:stubs>)
target_link_libraries(cmake_build_test ${global_libraries})
add_test(cmake_build_test cmake_build_test)
add_executable(source_test source_test.cc
$<TARGET_OBJECTS:project_shared> $<TARGET_OBJECTS:stubs>)
target_link_libraries(source_test ${global_libraries})
add_test(source_test source_test)
add_executable(source_clang_test source_clang_test.cc
$<TARGET_OBJECTS:project_shared> $<TARGET_OBJECTS:stubs>)
target_link_libraries(source_clang_test ${global_libraries})
add_test(source_clang_test source_clang_test)
if(LIBLLDB_FOUND)
add_executable(lldb_test lldb_test.cc
$<TARGET_OBJECTS:project_shared> $<TARGET_OBJECTS:stubs>)
target_link_libraries(lldb_test ${global_libraries})
add_test(lldb_test lldb_test)
add_subdirectory("lldb_test_files")
endif()

2
tests/cmake_test.cc → tests/cmake_build_test.cc

@ -15,7 +15,7 @@ int main() {
auto functions_parameters=cmake.get_functions_parameters("project");
g_assert(functions_parameters.at(0).second.at(0)=="juci");
g_assert(cmake.get_executable(tests_path/"cmake_test.cc").filename()=="cmake_test");
g_assert(cmake.get_executable(tests_path/"cmake_build_test.cc").filename()=="cmake_build_test");
auto build=Project::Build::create(tests_path);
g_assert(dynamic_cast<Project::CMakeBuild*>(build.get()));

16
tests/example_test.cc

@ -1,16 +0,0 @@
#include "terminal.h"
#include "info.h"
#include <gtkmm.h>
//In case one has to test functions that include Terminal::print or Info::print
//Requires display server to work
//However, it is possible to use the Broadway backend if the test is run in a pure terminal environment:
//broadwayd&
//make test
int main() {
auto app=Gtk::Application::create();
Terminal::get().print("some message");
Info::get().print("some message");
g_assert(true);
}

71
tests/lldb_test.cc

@ -0,0 +1,71 @@
#include <glib.h>
#include "debug_clang.h"
#include <thread>
#include <boost/filesystem.hpp>
#include <atomic>
int main() {
auto build_path=boost::filesystem::canonical(JUCI_BUILD_PATH);
auto exec_path=build_path/"tests"/"lldb_test_files"/"lldb_test_executable";
g_assert(boost::filesystem::exists(exec_path));
auto tests_path=boost::filesystem::canonical(JUCI_TESTS_PATH);
auto source_path=tests_path/"lldb_test_files"/"main.cpp";
g_assert(boost::filesystem::exists(source_path));
std::vector<std::pair<boost::filesystem::path, int> > breakpoints;
breakpoints.emplace_back(source_path, 2);
std::atomic<bool> exited(false);
int exit_status;
std::atomic<int> line_nr(0);
std::thread debug_thread([&] {
Debug::Clang::get().start(exec_path.string(), "", breakpoints, [&](int exit_status_){
exit_status=exit_status_;
exited=true;
}, [](const std::string &status) {
}, [&](const boost::filesystem::path &file_path, int line_nr_, int line_index) {
line_nr=line_nr_;
});
});
debug_thread.detach();
for(;;) {
if(exited) {
g_assert_cmpint(exit_status, ==, 0);
break;
}
else if(line_nr>0) {
for(;;) {
if(Debug::Clang::get().is_stopped())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
g_assert_cmpint(line_nr, ==, 2);
g_assert(Debug::Clang::get().get_backtrace().size()>0);
auto variables=Debug::Clang::get().get_variables();
g_assert_cmpstr(variables.at(0).name.c_str(), ==, "an_int");
line_nr=0;
Debug::Clang::get().step_over();
for(;;) {
if(line_nr>0 && Debug::Clang::get().is_stopped())
break;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
g_assert_cmpint(line_nr, ==, 3);
g_assert(Debug::Clang::get().get_backtrace().size()>0);
variables=Debug::Clang::get().get_variables();
g_assert_cmpstr(variables.at(0).name.c_str(), ==, "an_int");
auto value=Debug::Clang::get().get_value("an_int", source_path, 2, 7);
g_assert_cmpuint(value.size(), >, 16);
auto value_substr=value.substr(0, 16);
g_assert_cmpstr(value_substr.c_str(), ==, "(int) an_int = 1");
line_nr=0;
Debug::Clang::get().continue_debug();
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
Debug::Clang::get().cancel();
}

5
tests/lldb_test_files/CMakeLists.txt

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "-g")
add_executable(lldb_test_executable main.cpp)

4
tests/lldb_test_files/main.cpp

@ -0,0 +1,4 @@
int main() {
int an_int=1;
an_int++;
}

50
tests/process_test.cc

@ -0,0 +1,50 @@
#include <glib.h>
#include "process.hpp"
int main() {
auto output=std::make_shared<std::string>();
auto error=std::make_shared<std::string>();
{
Process process("echo Test", "", [output](const char *bytes, size_t n) {
*output+=std::string(bytes, n);
});
g_assert(process.get_exit_status()==0);
g_assert(output->substr(0, 4)=="Test");
output->clear();
}
{
Process process("echo Test && ls an_incorrect_path", "", [output](const char *bytes, size_t n) {
*output+=std::string(bytes, n);
}, [error](const char *bytes, size_t n) {
*error+=std::string(bytes, n);
});
g_assert(process.get_exit_status()>0);
g_assert(output->substr(0, 4)=="Test");
g_assert(!error->empty());
output->clear();
error->clear();
}
{
Process process("bash", "", [output](const char *bytes, size_t n) {
*output+=std::string(bytes, n);
}, nullptr, true);
process.write("echo Test\n");
process.write("exit\n");
g_assert(process.get_exit_status()==0);
g_assert(output->substr(0, 4)=="Test");
output->clear();
}
{
Process process("cat", "", [output](const char *bytes, size_t n) {
*output+=std::string(bytes, n);
}, nullptr, true);
process.write("Test\n");
process.close_stdin();
g_assert(process.get_exit_status()==0);
g_assert(output->substr(0, 4)=="Test");
output->clear();
}
}

81
tests/source_clang_test.cc

@ -0,0 +1,81 @@
#include <glib.h>
#include "source_clang.h"
#include "config.h"
#include "filesystem.h"
std::string main_error=R"(int main() {
int number=2;
number=3
}
)";
//Requires display server to work
//However, it is possible to use the Broadway backend if the test is run in a pure terminal environment:
//broadwayd&
//make test
void flush_events() {
while(Gtk::Main::events_pending())
Gtk::Main::iteration(false);
}
int main() {
auto app=Gtk::Application::create();
Gsv::init();
Config::get().project.default_build_path="./build";
Source::ClangView *clang_view=new Source::ClangView(boost::filesystem::canonical(std::string(JUCI_TESTS_PATH)+"/source_clang_test_files/main.cpp"),
Gsv::LanguageManager::get_default()->get_language("cpp"));
while(!clang_view->parsed)
flush_events();
g_assert_cmpuint(clang_view->diagnostics.size(), ==, 0);
//test get_declaration and get_implementation
clang_view->place_cursor_at_line_index(14-1, 8-1);
auto location=clang_view->get_declaration_location({clang_view});
g_assert_cmpuint(location.line, ==, 5);
clang_view->place_cursor_at_line_index(location.line-1, location.index-1);
location=clang_view->get_implementation_location({clang_view});
g_assert_cmpuint(location.line, ==, 10);
clang_view->place_cursor_at_line_index(location.line-1, location.index-1);
location=clang_view->get_declaration_location({clang_view});
g_assert_cmpuint(location.line, ==, 5);
//test get_usages and get_methods
auto locations=clang_view->get_usages({clang_view});
g_assert_cmpuint(locations.size(), >, 0);
locations=clang_view->get_methods();
g_assert_cmpuint(locations.size(), >, 0);
//Test rename class (error if not constructor and destructor is renamed as well)
auto saved_main=clang_view->get_buffer()->get_text();
clang_view->place_cursor_at_line_index(1-1, 7-1);
auto token=clang_view->get_token(clang_view->get_buffer()->get_insert()->get_iter());
g_assert_cmpstr(token.c_str(), ==, "TestClass");
location=clang_view->get_declaration_location({clang_view});
g_assert_cmpuint(location.line, ==, 1);
clang_view->rename_similar_tokens({clang_view}, "RenamedTestClass");
while(!clang_view->parsed)
flush_events();
auto iter=clang_view->get_buffer()->get_insert()->get_iter();
iter.backward_char();
token=clang_view->get_token(iter);
g_assert_cmpstr(token.c_str(), ==, "RenamedTestClass");
g_assert_cmpuint(clang_view->diagnostics.size(), ==, 0);
clang_view->get_buffer()->set_text(saved_main);
clang_view->save({clang_view});
//test error
clang_view->get_buffer()->set_text(main_error);
while(!clang_view->parsed)
flush_events();
g_assert_cmpuint(clang_view->diagnostics.size(), >, 0);
g_assert_cmpuint(clang_view->get_fix_its().size(), >, 0);
clang_view->async_delete();
clang_view->delete_thread.join();
flush_events();
}

1
tests/source_clang_test_files/CMakeLists.txt

@ -0,0 +1 @@
project(test)

7
tests/source_clang_test_files/build/compile_commands.json

@ -0,0 +1,7 @@
[
{
"directory": "build",
"command": "c++ -std=c++1y -Wall -Wextra -Wno-unused-parameter main.cpp",
"file": "main.cpp"
}
]

15
tests/source_clang_test_files/main.cpp

@ -0,0 +1,15 @@
class TestClass {
public:
TestClass();
~TestClass() {}
void function();
};
TestClass::TestClass() {}
void TestClass::function() {}
int main() {
TestClass test;
test.function();
}

43
tests/source_test.cc

@ -0,0 +1,43 @@
#include <glib.h>
#include "source.h"
#include "filesystem.h"
std::string hello_world=R"(#include <iostream>
int main() {
std::cout << "hello world\n";
})";
std::string hello_world_cleaned=R"(#include <iostream>
int main() {
std::cout << "hello world\n";
}
)";
//Requires display server to work
//However, it is possible to use the Broadway backend if the test is run in a pure terminal environment:
//broadwayd&
//make test
int main() {
auto app=Gtk::Application::create();
Gsv::init();
auto tests_path=boost::filesystem::canonical(JUCI_TESTS_PATH);
auto source_file=tests_path/"tmp"/"source_file.cpp";
{
Source::View source_view(source_file, Glib::RefPtr<Gsv::Language>());
source_view.get_buffer()->set_text(hello_world);
g_assert(source_view.save({&source_view}));
}
Source::View source_view(source_file, Glib::RefPtr<Gsv::Language>());
g_assert(source_view.get_buffer()->get_text()==hello_world);
source_view.cleanup_whitespace_characters();
g_assert(source_view.get_buffer()->get_text()==hello_world_cleaned);
g_assert(boost::filesystem::remove(source_file));
g_assert(!boost::filesystem::exists(source_file));
}

5
tests/stubs/dispatcher.cc

@ -1,5 +0,0 @@
#include "dispatcher.h"
Dispatcher::Dispatcher() {}
Dispatcher::~Dispatcher() {}

26
tests/stubs/selectiondialog.cc

@ -0,0 +1,26 @@
#include "selectiondialog.h"
ListViewText::ListViewText(bool use_markup) {}
SelectionDialogBase::SelectionDialogBase(Gtk::TextView& text_view, Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark, bool show_search_entry, bool use_markup):
text_view(text_view), list_view_text(use_markup) {}
void SelectionDialogBase::show() {}
void SelectionDialogBase::hide() {}
void SelectionDialogBase::add_row(const std::string& row) {}
SelectionDialog::SelectionDialog(Gtk::TextView& text_view, Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark, bool show_search_entry, bool use_markup) :
SelectionDialogBase(text_view, start_mark, show_search_entry, use_markup) {}
SelectionDialogBase::~SelectionDialogBase() {}
bool SelectionDialog::on_key_press(GdkEventKey* key) { return true; }
CompletionDialog::CompletionDialog(Gtk::TextView &text_view, Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark):
SelectionDialogBase(text_view, start_mark, false, false) {}
bool CompletionDialog::on_key_press(GdkEventKey* key) { return true;}
bool CompletionDialog::on_key_release(GdkEventKey* key) {return true;}

18
tests/stubs/terminal.cc

@ -1,5 +1,17 @@
#include "terminal.h"
Terminal::InProgress::InProgress(const std::string& start_msg): stop(false) {}
Terminal::InProgress::~InProgress() {}
std::shared_ptr<Terminal::InProgress> Terminal::print_in_progress(std::string start_msg) {
return std::make_shared<Terminal::InProgress>("");
}
void Terminal::InProgress::done(const std::string& msg) {}
void Terminal::InProgress::cancel(const std::string &msg) {}
Terminal::Terminal() {}
bool Terminal::on_motion_notify_event(GdkEventMotion* motion_event) {return false;}
@ -10,6 +22,12 @@ int Terminal::process(const std::string &command, const boost::filesystem::path
return 0;
}
int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path) {
return 0;
}
size_t Terminal::print(const std::string &message, bool bold) {
return 0;
}
void Terminal::async_print(const std::string &message, bool bold) {}

16
tests/stubs/tooltips.cc

@ -0,0 +1,16 @@
#include "tooltips.h"
Gdk::Rectangle Tooltips::drawn_tooltips_rectangle=Gdk::Rectangle();
Tooltip::Tooltip(std::function<Glib::RefPtr<Gtk::TextBuffer>()> create_tooltip_buffer,
Gtk::TextView& text_view,
Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark,
Glib::RefPtr<Gtk::TextBuffer::Mark> end_mark): text_view(text_view) {}
Tooltip::~Tooltip() {}
void Tooltips::show(Gdk::Rectangle const&, bool) {}
void Tooltips::show(bool) {}
void Tooltips::hide() {}

0
tests/tmp/.keep

2
tiny-process-library

@ -1 +1 @@
Subproject commit 245e36b83670c4bcf19b36c245d0e175d57be178
Subproject commit 48dd51030c7a539af802195a8da478a950247afe
Loading…
Cancel
Save