Add a querying tool for use in e.g. IRC bots
Now the tools don't get built on `make all' but instead have their own target called `tools'. It might be reasonable to move them into their own directory sometime, instead of cluttering `src'.
This commit is contained in:
parent
1955343857
commit
adce15243a
|
@ -110,10 +110,16 @@ add_executable (${CMAKE_PROJECT_NAME}
|
||||||
target_link_libraries (${CMAKE_PROJECT_NAME} ${project_common_libraries})
|
target_link_libraries (${CMAKE_PROJECT_NAME} ${project_common_libraries})
|
||||||
|
|
||||||
# Tools
|
# Tools
|
||||||
add_executable (add-pronunciation
|
add_executable (query-tool EXCLUDE_FROM_ALL
|
||||||
|
src/query-tool.c ${project_common_sources})
|
||||||
|
target_link_libraries (query-tool ${project_common_libraries})
|
||||||
|
|
||||||
|
add_executable (add-pronunciation EXCLUDE_FROM_ALL
|
||||||
src/add-pronunciation.c ${project_common_sources})
|
src/add-pronunciation.c ${project_common_sources})
|
||||||
target_link_libraries (add-pronunciation ${project_common_libraries})
|
target_link_libraries (add-pronunciation ${project_common_libraries})
|
||||||
|
|
||||||
|
add_custom_target (tools DEPENDS add-pronunciation query-tool)
|
||||||
|
|
||||||
# The files to be installed
|
# The files to be installed
|
||||||
include (GNUInstallDirs)
|
include (GNUInstallDirs)
|
||||||
install (TARGETS ${CMAKE_PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install (TARGETS ${CMAKE_PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
/*
|
||||||
|
* A tool to query multiple dictionaries for the specified word
|
||||||
|
*
|
||||||
|
* Intended for use in IRC bots and similar silly things---words go in, one
|
||||||
|
* on a line, and entries come out, one dictionary at a time, finalised with
|
||||||
|
* an empty line. Newlines are escaped with `\n', backslashes with `\\'.
|
||||||
|
*
|
||||||
|
* So far only the `m' field is supported. Feel free to extend the program
|
||||||
|
* according to your needs, it's not very complicated.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Přemysl Janouch <p.janouch@gmail.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "stardict.h"
|
||||||
|
#include "stardict-private.h"
|
||||||
|
#include "generator.h"
|
||||||
|
|
||||||
|
static guint
|
||||||
|
count_equal_chars (const gchar *a, const gchar *b)
|
||||||
|
{
|
||||||
|
guint count = 0;
|
||||||
|
while (*a && *b)
|
||||||
|
if (*a++ == *b++)
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_dictionary (StardictDict *dict, const gchar *word)
|
||||||
|
{
|
||||||
|
gboolean found;
|
||||||
|
StardictIterator *iter = stardict_dict_search (dict, word, &found);
|
||||||
|
if (!found)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
// Default Stardict ordering is ASCII case-insensitive.
|
||||||
|
// Try to find a better matching entry based on letter case:
|
||||||
|
|
||||||
|
gint64 best_offset = stardict_iterator_get_offset (iter);
|
||||||
|
guint best_score = count_equal_chars
|
||||||
|
(stardict_iterator_get_word (iter), word);
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
stardict_iterator_next (iter);
|
||||||
|
if (!stardict_iterator_is_valid (iter))
|
||||||
|
break;
|
||||||
|
|
||||||
|
const gchar *iter_word = stardict_iterator_get_word (iter);
|
||||||
|
if (g_ascii_strcasecmp (iter_word, word))
|
||||||
|
break;
|
||||||
|
|
||||||
|
guint score = count_equal_chars (iter_word, word);
|
||||||
|
if (score > best_score)
|
||||||
|
{
|
||||||
|
best_offset = stardict_iterator_get_offset (iter);
|
||||||
|
best_score = score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stardict_iterator_set_offset (iter, best_offset, FALSE);
|
||||||
|
|
||||||
|
StardictEntry *entry = stardict_iterator_get_entry (iter);
|
||||||
|
StardictInfo *info = stardict_dict_get_info (dict);
|
||||||
|
const GList *list = stardict_entry_get_fields (entry);
|
||||||
|
for (; list; list = list->next)
|
||||||
|
{
|
||||||
|
StardictEntryField *field = list->data;
|
||||||
|
if (field->type == STARDICT_FIELD_MEANING)
|
||||||
|
{
|
||||||
|
const gchar *desc = field->data;
|
||||||
|
printf ("%s:", info->book_name);
|
||||||
|
for (; *desc; desc++)
|
||||||
|
{
|
||||||
|
if (*desc == '\\')
|
||||||
|
printf ("\\\\");
|
||||||
|
else if (*desc == '\n')
|
||||||
|
printf ("\\n");
|
||||||
|
else
|
||||||
|
putchar (*desc);
|
||||||
|
}
|
||||||
|
putchar ('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_object_unref (entry);
|
||||||
|
out:
|
||||||
|
g_object_unref (iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||||
|
if (glib_check_version (2, 36, 0))
|
||||||
|
g_type_init ();
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||||
|
|
||||||
|
GError *error = NULL;
|
||||||
|
GOptionContext *ctx = g_option_context_new
|
||||||
|
("DICTIONARY.ifo... - query multiple dictionaries");
|
||||||
|
if (!g_option_context_parse (ctx, &argc, &argv, &error))
|
||||||
|
{
|
||||||
|
g_printerr ("Error: option parsing failed: %s\n", error->message);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
g_option_context_free (ctx);
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
g_printerr ("Error: no dictionaries given\n");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
guint n_dicts = argc - 1;
|
||||||
|
StardictDict **dicts = g_alloca (sizeof *dicts * n_dicts);
|
||||||
|
|
||||||
|
guint i;
|
||||||
|
for (i = 1; i <= n_dicts; i++)
|
||||||
|
{
|
||||||
|
dicts[i - 1] = stardict_dict_new (argv[i], &error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
g_printerr ("Error: opening dictionary `%s' failed: %s\n",
|
||||||
|
argv[i], error->message);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
GString *s = g_string_new (NULL);
|
||||||
|
|
||||||
|
gint c;
|
||||||
|
while ((c = getchar ()) != EOF && c != '\n')
|
||||||
|
if (c != '\r')
|
||||||
|
g_string_append_c (s, c);
|
||||||
|
|
||||||
|
if (s->len)
|
||||||
|
for (i = 0; i < n_dicts; i++)
|
||||||
|
do_dictionary (dicts[i], s->str);
|
||||||
|
|
||||||
|
printf ("\n");
|
||||||
|
fflush (NULL);
|
||||||
|
g_string_free (s, TRUE);
|
||||||
|
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n_dicts; i++)
|
||||||
|
g_object_unref (dicts[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue