Commit 516c0d49 authored by Yuanle Song's avatar Yuanle Song
Browse files

v0.2.0 zero-pinyin.el can input most character/words now.

get_candidates() implemented naively.

no jian pin support, no auto correction, no ambiguity pinyin support, but here
is a good foundation to work on.
parent dc92f53c
Loading
Loading
Loading
Loading
+97 −37
Original line number Diff line number Diff line
#include <gio/gio.h>
#include <glib-unix.h>
#include "zero-pinyin-service.h"
#include "../sqlite3_util.h"
#include <sqlite3.h>

struct _AppData
{
typedef struct {
	GApplication *app;
	GDBusNodeInfo *introspection_data;
	guint owner_id;
};

typedef struct _AppData AppData;
	sqlite3 *db;
	gboolean init_done;
} AppData;

static AppData appdata;

@@ -18,6 +19,7 @@ static const gchar introspection_xml[] =
  "  <interface name='com.emacsos.zero.ZeroPinyinService'>"
  "    <method name='GetCandidates'>"
  "      <arg type='s' name='preedit_str'/>"
  "      <arg type='u' name='fetch_size'/>"
  "      <arg type='as' name='candidates' direction='out'/>"
  "      <arg type='au' name='matched_preedit_str_lengths' direction='out'/>"
  "    </method>"
@@ -31,20 +33,33 @@ handle_method_get_candidates (GDBusMethodInvocation *invocation,
			      GVariant *parameters)
{
	gchar *preedit_str = NULL;
	guint fetch_size = 0;
	GVariant *result = NULL;
	GVariantBuilder *candidates_builder = NULL;
	GVariantBuilder *matched_lengths_builder = NULL;
	/* GVariant *candidates = NULL; */
	/* GVariant *matched_preedit_str_lengths = NULL; */

	g_variant_get (parameters, "(s)", &preedit_str);
	g_variant_get (parameters, "(su)", &preedit_str, &fetch_size);
	g_return_if_fail (preedit_str != NULL);
	g_return_if_fail (fetch_size > 0);
	if (preedit_str == NULL || fetch_size == 0) {
		g_dbus_method_invocation_return_dbus_error (
			invocation,
			"org.gtk.GDBus.Failed",
			"Bad param");
		if (preedit_str)
			g_free (preedit_str);
		return;
	}

	g_message ("get_candidates for preedit_str=%s fetch_size=%u",
		   preedit_str, fetch_size);

	candidates_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
	matched_lengths_builder = g_variant_builder_new (G_VARIANT_TYPE ("au"));

	/* test data */
	get_candidates_test (preedit_str, candidates_builder, matched_lengths_builder);
	/* get_candidates_test (preedit_str, fetch_size, candidates_builder, matched_lengths_builder); */
	get_candidates (appdata->db, preedit_str, fetch_size, candidates_builder, matched_lengths_builder);

	result = g_variant_new ("(asau)", candidates_builder, matched_lengths_builder);
	g_assert_nonnull (result);
@@ -176,7 +191,7 @@ config_dbus_service (AppData *appdata)
	g_assert (appdata->introspection_data != NULL);
	appdata->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
					    "com.emacsos.zero.ZeroPinyinService",
					    G_BUS_NAME_OWNER_FLAGS_NONE,
					    G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT|G_BUS_NAME_OWNER_FLAGS_REPLACE,
					    on_bus_acquired,
					    on_name_acquired,
					    on_name_lost,
@@ -197,37 +212,43 @@ on_sigterm_received (gpointer user_data)
}

static void
activate (GApplication *app,
	  AppData *appdata)
config_db (AppData* appdata)
{
	/* no-op */
	g_message ("zero-pinyin-service activate()");
	gint ri = 0;
	gboolean r = FALSE;
	static const char* SQLITE3_MEMORY_DB = ":memory:";
	sqlite3* db = NULL;
	gchar* sql = NULL;
	ri = sqlite3_open (SQLITE3_MEMORY_DB, &db);
	g_assert_cmpint (ri, ==, SQLITE_OK);
	g_assert_nonnull (db);

	/* TODO make db path configurable */
	/* TODO remove user name in db path */
	sql = sqlite3_mprintf ("ATTACH %Q AS maindb", "/home/sylecn/.cache/ibus/pinyin/main.db");
	r = sqlite3_exec_simple (db, sql);
	g_assert (r);
	sqlite3_free (sql);

	/* TODO make db path configurable */
	sql = sqlite3_mprintf ("ATTACH %Q AS userdb", "/home/sylecn/.cache/ibus/pinyin/user-1.0.db");
	r = sqlite3_exec_simple (db, sql);
	g_assert (r);
	sqlite3_free (sql);

	appdata->db = db;
}

static void
startup (GApplication *app,
zero_pinyin_service_init (GApplication *app,
			  AppData *appdata)
{
	g_message ("zero-pinyin-service startup()");
	appdata->introspection_data = NULL;
	appdata->owner_id = 0;
	appdata->db = NULL;
	config_dbus_service (appdata);
	g_application_hold (app);
}

static void
shutdown (GApplication *app,
	  AppData *appdata)
{
	g_message ("zero-pinyin-service shutdown()");
	if (appdata->owner_id > 0) {
		g_bus_unown_name (appdata->owner_id);
		appdata->owner_id = 0;
	}
	if (appdata->introspection_data != NULL) {
		g_dbus_node_info_unref (appdata->introspection_data);
		appdata->introspection_data = NULL;
	}
	config_db (appdata);
	appdata->init_done = TRUE;
}

/**
@@ -248,6 +269,45 @@ setup_sigint_sigterm_handler (AppData *appdata)
	g_source_unref (source);
}

static void
startup (GApplication* app,
	 AppData* appdata)
{
	g_message ("zero-pinyin-service startup()");
	setup_sigint_sigterm_handler (appdata);

	g_assert_false (appdata->init_done);
	zero_pinyin_service_init (app, appdata);
	g_application_hold (app);
}

static void
activate (GApplication *app,
	  AppData *appdata)
{
	g_message ("zero-pinyin-service activate()");
	/* as a pure service, activate is a no-op. */
}

static void
shutdown (GApplication *app,
	  AppData *appdata)
{
	g_message ("zero-pinyin-service shutdown()");
	if (appdata->owner_id > 0) {
		g_bus_unown_name (appdata->owner_id);
		appdata->owner_id = 0;
	}
	if (appdata->introspection_data != NULL) {
		g_dbus_node_info_unref (appdata->introspection_data);
		appdata->introspection_data = NULL;
	}
	if (appdata->db != NULL) {
		sqlite3_close (appdata->db);
		appdata->db = NULL;
	}
}

/**
 * provide zero-pinyin-service dbus service.
 * it's a console app based on glib and gio.
@@ -258,15 +318,15 @@ main (int argc, char *argv[])
	GApplication *app = NULL;
	int status = 0;

	app = g_application_new ("com.emacsos.zero.App.ZeroPinyinService",
	app = g_application_new ("com.emacsos.zero.ZeroPinyinServiceApp",
				 G_APPLICATION_FLAGS_NONE);
	g_assert_nonnull (app);
	appdata.app = app;
	appdata.init_done = FALSE;

	g_signal_connect (app, "activate", G_CALLBACK (activate), &appdata);
	g_signal_connect (app, "startup", G_CALLBACK (startup), &appdata);
	g_signal_connect (app, "activate", G_CALLBACK (activate), &appdata);
	g_signal_connect (app, "shutdown", G_CALLBACK (shutdown), &appdata);
	setup_sigint_sigterm_handler (&appdata);

	status = g_application_run (G_APPLICATION (app), argc, argv);
	g_object_unref (app);
+14 −4
Original line number Diff line number Diff line
# -*- mode: conf -*-
project('zero-pinyin-service', ['c', 'cpp'],
  version: '0.1.0',
  version: '0.2.0',
  license: 'GPL',
  default_options: [
    'warning_level=2',
@@ -33,12 +33,22 @@ endif
glib = dependency('glib-2.0')
gio = dependency('gio-unix-2.0')
uuid = dependency('uuid')
shared_dep = [glib, gio, uuid]
sqlite3 = dependency('sqlite3')
shared_dep = [glib, gio, uuid, sqlite3]

src = ['../PinyinParser.cc', 'parse-pinyin.cpp', 'zero-pinyin-service.cc', 'main.c']
src = [
  '../PinyinParser.cc',
  '../sqlite3_util.c',
  'parse-pinyin.cpp',
  'zero-pinyin-service.c',
  'main.c']
executable('main', src, dependencies: shared_dep)

test('zero-pinyin-service',
test('parse-pinyin',
  executable('parse-pinyin',
    ['../PinyinParser.cc', 'parse-pinyin.cpp', 'parse-pinyin-test.cpp'],
    dependencies: shared_dep))
test('zero-pinyin-service-test',
  executable('zero-pinyin-service-test',
    ['zero-pinyin-service-test.c'],
    dependencies: shared_dep))
+32 −4
Original line number Diff line number Diff line
#include "parse-pinyin.hpp"
#include "parse-pinyin.h"
#include <iostream>
#include <glib.h>

static void
test_parse_pinyin ()
test_parse_pinyin_cpp ()
{
	std::vector<Pinyin*>* result = parse_pinyin ("liyifeng");
	std::vector<Pinyin*>* result = parse_pinyin_cpp ("liyifeng");
	g_assert_cmpint (result->size (), ==, 3);

	g_assert_cmpint (result->at(0)->shengmu_i, ==, 10);
@@ -26,10 +25,39 @@ test_parse_pinyin ()
	delete result;
}

static void
test_parse_pinyin ()
{
	GList* result = NULL;
	Pinyin* thispy = NULL;

	result = parse_pinyin ("liyifeng", 15);
	g_assert_cmpint (g_list_length (result), ==, 3);

	thispy = (Pinyin*) g_list_nth_data (result, 0);
	g_assert_cmpint (thispy->shengmu_i, ==, 10);
	g_assert_cmpint (thispy->yunmu_i, ==, 34);
	g_assert_cmpint (thispy->length, ==, 2);

	thispy = (Pinyin*) g_list_nth_data (result, 1);
	g_assert_cmpint (thispy->shengmu_i, ==, 21);
	g_assert_cmpint (thispy->yunmu_i, ==, 34);
	g_assert_cmpint (thispy->length, ==, 2);

	thispy = (Pinyin*) g_list_nth_data (result, 2);
	g_assert_cmpint (thispy->shengmu_i, ==, 5);
	g_assert_cmpint (thispy->yunmu_i, ==, 32);
	g_assert_cmpint (thispy->length, ==, 4);

	g_list_free_full (result, g_free);
}

int
main (int argc, char *argv[])
{
	g_test_init (&argc, &argv, NULL);
	g_test_add_func ("/zero/test_parse_pinyin_cpp",
			 test_parse_pinyin_cpp);
	g_test_add_func ("/zero/test_parse_pinyin",
			 test_parse_pinyin);

+20 −2
Original line number Diff line number Diff line
#include "parse-pinyin.hpp"
#include "parse-pinyin.h"
#include "../PinyinArray.h"
#include "../PinyinParser.h"

@@ -11,7 +11,7 @@
 * returns: a list of Pinyin
 */
std::vector<Pinyin*>*
parse_pinyin (const char* preedit_str, guint max_pinyin)
parse_pinyin_cpp (const char* preedit_str, const guint max_pinyin)
{
	std::vector<Pinyin*>* result = new std::vector<Pinyin*>();
	PyZy::PinyinArray pyar = {0};
@@ -25,3 +25,21 @@ parse_pinyin (const char* preedit_str, guint max_pinyin)
	}
	return result;
}

GList*
parse_pinyin (const char* preedit_str, const guint max_pinyin)
{
	GList* result = NULL;
	PyZy::PinyinArray pyar = {0};
	Pinyin* thispy = NULL;

	PyZy::PinyinParser::parse (preedit_str, strlen(preedit_str), 0, pyar, max_pinyin);
	for (guint i = 0; i < pyar.size(); ++i) {
		thispy = g_new (Pinyin, 1);
		thispy->shengmu_i = (int) pyar[i].pinyin->pinyin_id[0].sheng;
		thispy->yunmu_i = (int) pyar[i].pinyin->pinyin_id[0].yun;
		thispy->length = pyar[i].len;
		result = g_list_append (result, thispy);
	}
	return result;
}
+31 −0
Original line number Diff line number Diff line
#ifndef _PARSE_PINYIN_H_
#define _PARSE_PINYIN_H_

#include <vector>
#include <glib.h>
#include "zero-pinyin-service.h"

#ifdef __cplusplus

#include <vector>

/**
 * parse preedit_str to groups of pinyin.
 * caller should free each Pinyin and the vector after use.
 */
std::vector<Pinyin*>* parse_pinyin (const char* preedit_str, guint max_pinyin=15);
std::vector<Pinyin*>* parse_pinyin_cpp (const char* preedit_str, const guint max_pinyin=15);

extern "C"
{
#endif

/**
 * parse preedit_str to groups of pinyin.
 * caller should free each Pinyin and the GList after use.
 */
GList* parse_pinyin (const char* preedit_str, const guint max_pinyin);

#ifdef __cplusplus
}
#endif

#endif /* _PARSE_PINYIN_H_ */
Loading