Browse Source

Added spellcheck using aspell to comments and strings. Please install (lib)aspell(-dev) and rm ~/.juci to test.

merge-requests/365/head
eidheim 10 years ago
parent
commit
4eb85d90c6
  1. 6
      docs/install.md
  2. 6
      src/CMakeLists.txt
  3. 2
      src/config.cc
  4. 1
      src/files.h
  5. 76
      src/source.cc
  6. 6
      src/source.h

6
docs/install.md

@ -4,7 +4,7 @@ Before installation, please install libclangmm, see [installation guide](http://
## Debian/Ubuntu
```sh
sudo apt-get install pkg-config libboost-system-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libgtkmm-3.0-dev libgtksourceviewmm-3.0-dev
sudo apt-get install pkg-config libboost-system-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libgtkmm-3.0-dev libgtksourceviewmm-3.0-dev libaspell-dev
```
```sh
git clone http://github.com/cppit/jucipp.git
@ -16,7 +16,7 @@ sudo make install
## OS X with Homebrew (http://brew.sh/)
```sh
brew install pkg-config boost gtkmm3 gtksourceviewmm3
brew install pkg-config boost gtkmm3 gtksourceviewmm3 aspell
```
```sh
@ -36,7 +36,7 @@ Please wait until the following TODOs are resolved:
Install dependencies(replace [arch] with i686 or x86_64 depending on your MSYS2 install):
```sh
pacman -S patch autoconf automake-wrapper mingw-w64-[arch]-gtkmm3 mingw-w64-[arch]-boost
pacman -S patch autoconf automake-wrapper mingw-w64-[arch]-gtkmm3 mingw-w64-[arch]-boost mingw-w64-[arch]-aspell
```
Get juCi++ source:

6
src/CMakeLists.txt

@ -56,6 +56,8 @@ validate(${GTKMM_FOUND} "gtkmm" "libgtkmm-dev" "gtkmm")
pkg_check_modules(GTKSVMM gtksourceviewmm-3.0)
validate(${GTKSVMM_FOUND} "gtksvmm" "libgtksvmm-dev" "gtkmmsv")
find_package(ASPELL REQUIRED)
set(source_files juci.h
juci.cc
menu.h
@ -105,7 +107,8 @@ if(${validation})
${GTKMM_INCLUDE_DIRS}
${GTKSVMM_INCLUDE_DIRS}
${LCL_INCLUDE_DIRS}
${LIBCLANG_INCLUDE_DIRS})
${LIBCLANG_INCLUDE_DIRS}
${ASPELL_INCLUDE_DIR})
link_directories(
${GTKMM_LIBRARY_DIRS}
@ -128,6 +131,7 @@ if(${validation})
${GTKMM_LIBRARIES}
${GTKSVMM_LIBRARIES}
${Boost_LIBRARIES}
${ASPELL_LIBRARIES}
# ${PYTHON_LIBRARIES}
)

2
src/config.cc

@ -46,6 +46,8 @@ void MainConfig::GenerateSource() {
auto source_cfg = Singleton::Config::source();
auto source_json = cfg.get_child("source");
source_cfg->spellcheck_language = source_json.get<std::string>("spellcheck_language");
source_cfg->default_tab_char = source_json.get<char>("default_tab_char");
source_cfg->default_tab_size = source_json.get<unsigned>("default_tab_size");
source_cfg->auto_tab_char_and_size = source_json.get<bool>("auto_tab_char_and_size");

1
src/files.h

@ -17,6 +17,7 @@ const std::string configjson =
#endif
#endif
"//Use \"\" for default font, and for instance \"Monospace 12\" to also set size.\n"
" \"spellcheck_language\": \"en_US\", \n"
" \"clang_types\": {\n"
" \"8\": \"def:function\",\n"
" \"21\": \"def:function\",\n"

76
src/source.cc

@ -7,14 +7,16 @@
#include "singletons.h"
#include <gtksourceview/gtksource.h>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <iostream> //TODO: remove
using namespace std; //TODO: remove
namespace sigc {
SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
}
AspellConfig* spellcheck_config=NULL;
Glib::RefPtr<Gsv::Language> Source::guess_language(const boost::filesystem::path &file_path) {
auto language_manager=Gsv::LanguageManager::get_default();
bool result_uncertain = false;
@ -98,18 +100,43 @@ Source::View::View(const boost::filesystem::path &file_path): file_path(file_pat
tabs_regex=std::regex(std::string("^(")+tab_char+"*)(.*)$");
get_buffer()->signal_changed().connect([this](){
auto iter=get_buffer()->get_insert()->get_iter();
if(iter.backward_char()) {
auto context_iter=iter;
if(context_iter.backward_char()) {
if(get_source_buffer()->iter_has_context_class(context_iter, "comment")) {
//TODO: get word, and spellcheck
//cout << "comment: " << (char)*iter << endl;
if(spellcheck_config==NULL) {
spellcheck_config=new_aspell_config();
aspell_config_replace(spellcheck_config, "lang", Singleton::Config::source()->spellcheck_language.c_str());
}
spellcheck_possible_err=new_aspell_speller(spellcheck_config);
spellcheck_checker=NULL;
if (aspell_error_number(spellcheck_possible_err) != 0)
std::cerr << "Spell check error: " << aspell_error_message(spellcheck_possible_err) << std::endl;
else {
spellcheck_checker = to_aspell_speller(spellcheck_possible_err);
auto tag=get_buffer()->create_tag("spellcheck_error");
tag->property_underline()=Pango::Underline::UNDERLINE_ERROR;
get_buffer()->signal_changed().connect([this](){
auto iter=get_buffer()->get_insert()->get_iter();
if(iter.backward_char()) {
auto context_iter=iter;
if(context_iter.backward_char()) {
if(get_source_buffer()->iter_has_context_class(context_iter, "comment") || get_source_buffer()->iter_has_context_class(context_iter, "string")) {
if(*iter==32) { //Might have used space to split two words
auto first=iter;
auto second=iter;
if(first.backward_char() && second.forward_char()) {
get_buffer()->remove_tag_by_name("spellcheck_error", first, second);
spellcheck(first);
spellcheck(second);
}
}
else
spellcheck(iter);
}
}
}
}
});
});
}
}
void Source::View::search_occurrences_updated(GtkWidget* widget, GParamSpec* property, gpointer data) {
@ -121,6 +148,8 @@ void Source::View::search_occurrences_updated(GtkWidget* widget, GParamSpec* pro
Source::View::~View() {
g_clear_object(&search_context);
g_clear_object(&search_settings);
delete_aspell_speller(spellcheck_checker);
}
void Source::View::search_highlight(const std::string &text, bool case_sensitive, bool regex) {
@ -477,6 +506,31 @@ std::pair<char, unsigned> Source::View::find_tab_char_and_size() {
return {found_tab_char, found_tab_size};
}
void Source::View::spellcheck(Gtk::TextIter iter) {
auto start=iter;
auto end=iter;
while((*iter>=48 && *iter<=57) || (*iter>=65 && *iter<=90) || (*iter>=97 && *iter<=122) || *iter==95 || *iter>=128) {
start=iter;
if(!iter.backward_char())
break;
}
while((*end>=48 && *end<=57) || (*end>=65 && *end<=90) || (*end>=97 && *end<=122) || *end==95 || *end>=128) {
if(!end.forward_char())
break;
}
auto word=get_buffer()->get_text(start, end);
std::vector<Glib::ustring> words;
if(word.size()>0) {
auto correct = aspell_speller_check(spellcheck_checker, word.data(), word.bytes());
if(correct==0)
get_buffer()->apply_tag_by_name("spellcheck_error", start, end);
else
get_buffer()->remove_tag_by_name("spellcheck_error", start, end);
}
}
/////////////////////
//// GenericView ////
/////////////////////

6
src/source.h

@ -15,6 +15,7 @@
#include "selectiondialog.h"
#include <set>
#include <regex>
#include <aspell.h>
namespace Source {
Glib::RefPtr<Gsv::Language> guess_language(const boost::filesystem::path &file_path);
@ -23,6 +24,7 @@ namespace Source {
public:
std::string style;
std::string font;
std::string spellcheck_language;
bool auto_tab_char_and_size;
char default_tab_char;
unsigned default_tab_size;
@ -91,6 +93,10 @@ namespace Source {
GtkSourceSearchContext *search_context;
GtkSourceSearchSettings *search_settings;
static void search_occurrences_updated(GtkWidget* widget, GParamSpec* property, gpointer data);
AspellCanHaveError *spellcheck_possible_err;
AspellSpeller *spellcheck_checker;
void spellcheck(Gtk::TextIter iter);
}; // class View
class GenericView : public View {

Loading…
Cancel
Save