typing: add typing plugin

This commit is contained in:
Sébastien Helleu 2021-06-28 20:27:08 +02:00
parent b585ec09f8
commit dccf605e66
24 changed files with 972 additions and 20 deletions

View File

@ -115,6 +115,7 @@ option(ENABLE_PHP "Enable PHP scripting language" ON)
option(ENABLE_SPELL "Enable Spell checker plugin" ON)
option(ENABLE_ENCHANT "Enable Enchant lib for Spell checker plugin" OFF)
option(ENABLE_TRIGGER "Enable Trigger plugin" ON)
option(ENABLE_TYPING "Enable Tryping plugin" ON)
option(ENABLE_XFER "Enable Xfer plugin" ON)
option(ENABLE_MAN "Enable build of man page" OFF)
option(ENABLE_DOC "Enable build of documentation" OFF)

View File

@ -130,6 +130,7 @@ AH_VERBATIM([PLUGIN_GUILE], [#undef PLUGIN_GUILE])
AH_VERBATIM([PLUGIN_JAVASCRIPT], [#undef PLUGIN_JAVASCRIPT])
AH_VERBATIM([PLUGIN_SPELL], [#undef PLUGIN_SPELL])
AH_VERBATIM([PLUGIN_TRIGGER], [#undef PLUGIN_TRIGGER])
AH_VERBATIM([PLUGIN_TYPING], [#undef PLUGIN_TYPING])
AH_VERBATIM([PLUGIN_XFER], [#undef PLUGIN_XFER])
AH_VERBATIM([TESTS], [#undef TESTS])
AH_VERBATIM([MAN], [#undef MAN])
@ -164,6 +165,7 @@ AC_ARG_ENABLE(php, [ --disable-php turn off PHP script plugi
AC_ARG_ENABLE(spell, [ --disable-spell turn off Spell checker plugin (default=compiled)],enable_spell=$enableval,enable_spell=yes)
AC_ARG_ENABLE(enchant, [ --enable-enchant turn on Enchant lib for Spell checker plugin (default=off)],enable_enchant=$enableval,enable_enchant=no)
AC_ARG_ENABLE(trigger, [ --disable-trigger turn off Trigger plugin (default=compiled)],enable_trigger=$enableval,enable_trigger=yes)
AC_ARG_ENABLE(typing, [ --disable-typing turn off Typing plugin (default=compiled)],enable_trigger=$enableval,enable_typing=yes)
AC_ARG_ENABLE(xfer, [ --disable-xfer turn off Xfer (file transfer) plugin (default=compiled)],enable_xfer=$enableval,enable_xfer=yes)
AC_ARG_WITH(tclconfig, [ --with-tclconfig=DIR directory containing tcl configuration (tclConfig.sh)],tclconfig=$withval,tclconfig='')
AC_ARG_WITH(debug, [ --with-debug debugging: 0=no debug, 1=debug compilation (default=0)],debug=$withval,debug=0)
@ -1013,6 +1015,18 @@ else
not_asked="$not_asked trigger"
fi
# ---------------------------------- typing ------------------------------------
if test "x$enable_typing" = "xyes" ; then
TYPING_CFLAGS=""
TYPING_LFLAGS=""
AC_SUBST(TYPING_CFLAGS)
AC_SUBST(TYPING_LFLAGS)
AC_DEFINE(PLUGIN_TYPING)
else
not_asked="$not_asked typing"
fi
# ---------------------------------- xfer --------------------------------------
if test "x$enable_xfer" = "xyes" ; then
@ -1365,6 +1379,7 @@ AM_CONDITIONAL(PLUGIN_JAVASCRIPT, test "$enable_javascript" = "yes")
AM_CONDITIONAL(PLUGIN_PHP, test "$enable_php" = "yes")
AM_CONDITIONAL(PLUGIN_SPELL, test "$enable_spell" = "yes")
AM_CONDITIONAL(PLUGIN_TRIGGER, test "$enable_trigger" = "yes")
AM_CONDITIONAL(PLUGIN_TYPING, test "$enable_typing" = "yes")
AM_CONDITIONAL(PLUGIN_XFER, test "$enable_xfer" = "yes")
AM_CONDITIONAL(TESTS, test "$enable_tests" = "yes")
AM_CONDITIONAL(MAN, test "$enable_man" = "yes")
@ -1406,6 +1421,7 @@ AC_OUTPUT([Makefile
src/plugins/php/Makefile
src/plugins/spell/Makefile
src/plugins/trigger/Makefile
src/plugins/typing/Makefile
src/plugins/xfer/Makefile
src/gui/Makefile
src/gui/curses/Makefile
@ -1494,6 +1510,9 @@ fi
if test "x$enable_trigger" = "xyes"; then
listplugins="$listplugins trigger"
fi
if test "x$enable_typing" = "xyes"; then
listplugins="$listplugins typing"
fi
if test "x$enable_xfer" = "xyes"; then
listplugins="$listplugins xfer"
fi

View File

@ -115,6 +115,7 @@ PLUGIN_LIST = {
'spell': 'o',
'trigger': 'o',
'xfer': 'co',
'typing': 'o',
}
# options to ignore

View File

@ -3538,10 +3538,6 @@ string_input_for_buffer (const char *string)
if (!string)
return NULL;
/* a single "/" is not a command */
if (strcmp (string, "/") == 0)
return string;
/* "/ " is not a command */
if (strncmp (string, "/ ", 2) == 0)
return string;
@ -3575,10 +3571,6 @@ string_input_for_buffer (const char *string)
next_char = utf8_next_char (string);
/* there's no next char, then it's a not command */
if (!next_char || !next_char[0])
return string;
/* next char is a space, then it's not a command */
if (next_char[0] == ' ')
return string;

View File

@ -184,6 +184,10 @@ if(ENABLE_TRIGGER)
add_subdirectory(trigger)
endif()
if(ENABLE_TYPING)
add_subdirectory(typing)
endif()
if(ENABLE_XFER)
add_subdirectory(xfer)
endif()

View File

@ -121,6 +121,10 @@ if PLUGIN_TRIGGER
trigger_dir = trigger
endif
if PLUGIN_TYPING
typing_dir = typing
endif
if PLUGIN_XFER
xfer_dir = xfer
endif
@ -146,6 +150,7 @@ SUBDIRS = . \
$(php_dir) \
$(spell_dir) \
$(trigger_dir) \
$(typing_dir) \
$(xfer_dir)
EXTRA_DIST = CMakeLists.txt

View File

@ -36,7 +36,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Alias commands"));
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
WEECHAT_PLUGIN_PRIORITY(10000);
WEECHAT_PLUGIN_PRIORITY(11000);
#define ALIAS_IS_ARG_NUMBER(number) ((number >= '1') && (number <= '9'))

View File

@ -38,7 +38,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Buffers list"));
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
WEECHAT_PLUGIN_PRIORITY(9000);
WEECHAT_PLUGIN_PRIORITY(10000);
struct t_weechat_plugin *weechat_buflist_plugin = NULL;

View File

@ -37,7 +37,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Charset conversions"));
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
WEECHAT_PLUGIN_PRIORITY(15000);
WEECHAT_PLUGIN_PRIORITY(16000);
#define CHARSET_CONFIG_NAME "charset"

View File

@ -37,7 +37,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Execution of external commands in WeeChat"));
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
WEECHAT_PLUGIN_PRIORITY(13000);
WEECHAT_PLUGIN_PRIORITY(14000);
struct t_weechat_plugin *weechat_exec_plugin = NULL;

View File

@ -42,7 +42,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("FIFO pipe for remote control"));
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
WEECHAT_PLUGIN_PRIORITY(8000);
WEECHAT_PLUGIN_PRIORITY(9000);
struct t_weechat_plugin *weechat_fifo_plugin = NULL;
#define weechat_plugin weechat_fifo_plugin

View File

@ -46,7 +46,7 @@ extern struct t_logger_buffer *logger_buffers;
extern struct t_logger_buffer *last_logger_buffer;
extern int logger_buffer_valid (struct t_logger_buffer *logger_buffer);
extern struct t_logger_buffer *logger_buffer_add (struct t_gui_buffer *,
extern struct t_logger_buffer *logger_buffer_add (struct t_gui_buffer *buffer,
int log_level);
extern struct t_logger_buffer *logger_buffer_search_buffer (struct t_gui_buffer *buffer);
extern struct t_logger_buffer *logger_buffer_search_log_filename (const char *log_filename);

View File

@ -47,7 +47,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Log buffers to files"));
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
WEECHAT_PLUGIN_PRIORITY(14000);
WEECHAT_PLUGIN_PRIORITY(15000);
struct t_weechat_plugin *weechat_logger_plugin = NULL;

View File

@ -48,7 +48,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Spell checker for input"));
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
WEECHAT_PLUGIN_PRIORITY(11000);
WEECHAT_PLUGIN_PRIORITY(12000);
struct t_weechat_plugin *weechat_spell_plugin = NULL;

View File

@ -38,7 +38,7 @@ WEECHAT_PLUGIN_DESCRIPTION(N_("Text replacement and command execution on events
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
WEECHAT_PLUGIN_PRIORITY(12000);
WEECHAT_PLUGIN_PRIORITY(13000);
struct t_weechat_plugin *weechat_trigger_plugin = NULL;

View File

@ -0,0 +1,29 @@
#
# Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
#
# This file is part of WeeChat, the extensible chat client.
#
# WeeChat is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# WeeChat is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
#
add_library(typing MODULE
typing.c typing.h
typing-buffer.c typing-buffer.h
typing-config.c typing-config.h
)
set_target_properties(typing PROPERTIES PREFIX "")
target_link_libraries(typing coverage_config)
install(TARGETS typing LIBRARY DESTINATION ${WEECHAT_LIBDIR}/plugins)

View File

@ -0,0 +1,35 @@
#
# Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
#
# This file is part of WeeChat, the extensible chat client.
#
# WeeChat is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# WeeChat is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
#
AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(TYPING_CFLAGS)
libdir = ${weechat_libdir}/plugins
lib_LTLIBRARIES = typing.la
typing_la_SOURCES = typing.c \
typing.h \
typing-buffer.c \
typing-buffer.h \
typing-config.c \
typing-config.h
typing_la_LDFLAGS = -module -no-undefined
typing_la_LIBADD = $(TYPING_LFLAGS)
EXTRA_DIST = CMakeLists.txt

View File

@ -0,0 +1,198 @@
/*
* typing-buffer.c - typing buffer list management
*
* Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "../weechat-plugin.h"
#include "typing.h"
#include "typing-buffer.h"
struct t_typing_buffer *typing_buffers = NULL;
struct t_typing_buffer *last_typing_buffer = NULL;
/*
* Checks if a typing buffer pointer is valid.
*
* Returns:
* 1: typing buffer exists
* 0: typing buffer does not exist
*/
int
typing_buffer_valid (struct t_typing_buffer *typing_buffer)
{
struct t_typing_buffer *ptr_typing_buffer;
if (!typing_buffer)
return 0;
for (ptr_typing_buffer = typing_buffers; ptr_typing_buffer;
ptr_typing_buffer = ptr_typing_buffer->next_buffer)
{
if (ptr_typing_buffer == typing_buffer)
return 1;
}
/* typing_buffer not found */
return 0;
}
/*
* Adds a new buffer for typing status.
*
* Returns pointer to new typing buffer, NULL if error.
*/
struct t_typing_buffer *
typing_buffer_add (struct t_gui_buffer *buffer)
{
struct t_typing_buffer *new_typing_buffer;
if (!buffer)
return NULL;
if (weechat_typing_plugin->debug)
{
weechat_printf_date_tags (NULL, 0, "no_log",
"%s: start typing for buffer \"%s\"",
TYPING_PLUGIN_NAME,
weechat_buffer_get_string (buffer, "name"));
}
new_typing_buffer = malloc (sizeof (*new_typing_buffer));
if (new_typing_buffer)
{
new_typing_buffer->buffer = buffer;
new_typing_buffer->status = TYPING_BUFFER_STATUS_OFF;
new_typing_buffer->last_typed = 0;
new_typing_buffer->last_signal_sent = 0;
new_typing_buffer->prev_buffer = last_typing_buffer;
new_typing_buffer->next_buffer = NULL;
if (last_typing_buffer)
last_typing_buffer->next_buffer = new_typing_buffer;
else
typing_buffers = new_typing_buffer;
last_typing_buffer = new_typing_buffer;
}
return new_typing_buffer;
}
/*
* Searches for typing buffer by buffer pointer.
*
* Returns pointer to typing buffer found, NULL if not found.
*/
struct t_typing_buffer *
typing_buffer_search_buffer (struct t_gui_buffer *buffer)
{
struct t_typing_buffer *ptr_typing_buffer;
for (ptr_typing_buffer = typing_buffers; ptr_typing_buffer;
ptr_typing_buffer = ptr_typing_buffer->next_buffer)
{
if (ptr_typing_buffer->buffer == buffer)
return ptr_typing_buffer;
}
/* typing buffer not found */
return NULL;
}
/*
* Removes a typing buffer from list.
*/
void
typing_buffer_free (struct t_typing_buffer *typing_buffer)
{
struct t_typing_buffer *new_typing_buffers;
struct t_gui_buffer *ptr_buffer;
if (!typing_buffer)
return;
ptr_buffer = typing_buffer->buffer;
/* remove typing buffer */
if (last_typing_buffer == typing_buffer)
last_typing_buffer = typing_buffer->prev_buffer;
if (typing_buffer->prev_buffer)
{
(typing_buffer->prev_buffer)->next_buffer = typing_buffer->next_buffer;
new_typing_buffers = typing_buffers;
}
else
new_typing_buffers = typing_buffer->next_buffer;
if (typing_buffer->next_buffer)
(typing_buffer->next_buffer)->prev_buffer = typing_buffer->prev_buffer;
free (typing_buffer);
typing_buffers = new_typing_buffers;
if (weechat_typing_plugin->debug)
{
weechat_printf_date_tags (
NULL, 0, "no_log",
"%s: stop typing for buffer \"%s\"",
TYPING_PLUGIN_NAME,
weechat_buffer_get_string (ptr_buffer, "name"));
}
}
/*
* Adds a typing buffer in an infolist.
*
* Returns:
* 1: OK
* 0: error
*/
int
typing_buffer_add_to_infolist (struct t_infolist *infolist,
struct t_typing_buffer *typing_buffer)
{
struct t_infolist_item *ptr_item;
if (!infolist || !typing_buffer)
return 0;
ptr_item = weechat_infolist_new_item (infolist);
if (!ptr_item)
return 0;
if (!weechat_infolist_new_var_pointer (ptr_item, "buffer", typing_buffer->buffer))
return 0;
return 1;
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef WEECHAT_PLUGIN_TYPING_BUFFER_H
#define WEECHAT_PLUGIN_TYPING_BUFFER_H
#include <stdio.h>
#include <time.h>
struct t_infolist;
enum t_typing_buffer_status
{
TYPING_BUFFER_STATUS_OFF = 0,
TYPING_BUFFER_STATUS_TYPING,
TYPING_BUFFER_STATUS_PAUSED,
TYPING_BUFFER_STATUS_CLEARED,
/* number of typing buffer statuses */
TYPING_BUFFER_NUM_STATUSES,
};
/* own typing status */
struct t_typing_buffer
{
struct t_gui_buffer *buffer; /* pointer to buffer */
int status; /* status */
time_t last_typed; /* last char typed */
time_t last_signal_sent; /* last signal sent */
struct t_typing_buffer *prev_buffer; /* link to previous buffer */
struct t_typing_buffer *next_buffer; /* link to next buffer */
};
extern struct t_typing_buffer *typing_buffers;
extern struct t_typing_buffer *last_typing_buffer;
extern int typing_buffer_valid (struct t_typing_buffer *typing_buffer);
extern struct t_typing_buffer *typing_buffer_add (struct t_gui_buffer *buffer);
extern struct t_typing_buffer *typing_buffer_search_buffer (struct t_gui_buffer *buffer);
extern void typing_buffer_free (struct t_typing_buffer *typing_buffer);
extern int typing_buffer_add_to_infolist (struct t_infolist *infolist,
struct t_typing_buffer *typing_buffer);
#endif /* WEECHAT_PLUGIN_TYPING_BUFFER_H */

View File

@ -0,0 +1,159 @@
/*
* typing-config.c - typing configuration options (file typing.conf)
*
* Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../weechat-plugin.h"
#include "typing.h"
#include "typing-config.h"
struct t_config_file *typing_config_file = NULL;
struct t_config_section *typing_config_section_cmd = NULL;
struct t_config_section *typing_config_section_completion = NULL;
/* typing config, look section */
struct t_config_option *typing_config_look_enabled;
struct t_config_option *typing_config_look_delay_pause;
/*
* Reloads typing configuration file.
*/
int
typing_config_reload (const void *pointer, void *data,
struct t_config_file *config_file)
{
int rc;
/* make C compiler happy */
(void) pointer;
(void) data;
rc = weechat_config_reload (config_file);
typing_setup_hooks ();
return rc;
}
/*
* Callback for changes on option "typing.look.enabled".
*/
void
typing_config_change_enabled (const void *pointer, void *data,
struct t_config_option *option)
{
/* make C compiler happy */
(void) pointer;
(void) data;
(void) option;
typing_setup_hooks ();
}
/*
* Initializes typing configuration file.
*
* Returns:
* 1: OK
* 0: error
*/
int
typing_config_init ()
{
struct t_config_section *ptr_section;
typing_config_file = weechat_config_new (
TYPING_CONFIG_NAME,
&typing_config_reload, NULL, NULL);
if (!typing_config_file)
return 0;
/* look */
ptr_section = weechat_config_new_section (typing_config_file, "look",
0, 0,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL);
if (!ptr_section)
{
weechat_config_free (typing_config_file);
typing_config_file = NULL;
return 0;
}
typing_config_look_enabled = weechat_config_new_option (
typing_config_file, ptr_section,
"enabled", "boolean",
N_("typing enabled"),
NULL, 0, 0, "on", NULL, 0,
NULL, NULL, NULL,
&typing_config_change_enabled, NULL, NULL,
NULL, NULL, NULL);
typing_config_look_delay_pause = weechat_config_new_option (
typing_config_file, ptr_section,
"delay_pause", "integer",
N_("number of seconds after typing last char: if reached, the typing "
"status becomes \"paused\" and no more typing signals are sent"),
NULL, 1, 3600, "10", NULL, 0,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
return 1;
}
/*
* Reads typing configuration file.
*/
int
typing_config_read ()
{
return weechat_config_read (typing_config_file);
}
/*
* Writes typing configuration file.
*/
int
typing_config_write ()
{
return weechat_config_write (typing_config_file);
}
/*
* Frees typing configuration.
*/
void
typing_config_free ()
{
weechat_config_free (typing_config_file);
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef WEECHAT_PLUGIN_TYPING_CONFIG_H
#define WEECHAT_PLUGIN_TYPING_CONFIG_H
#define TYPING_CONFIG_NAME "typing"
extern struct t_config_option *typing_config_look_enabled;
extern struct t_config_option *typing_config_look_delay_pause;
extern int typing_config_init ();
extern int typing_config_read ();
extern int typing_config_write ();
extern void typing_config_free ();
#endif /* WEECHAT_PLUGIN_TYPING_CONFIG_H */

373
src/plugins/typing/typing.c Normal file
View File

@ -0,0 +1,373 @@
/*
* typing.c - manage typing status of users
*
* Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "../weechat-plugin.h"
#include "typing.h"
#include "typing-buffer.h"
#include "typing-config.h"
WEECHAT_PLUGIN_NAME(TYPING_PLUGIN_NAME);
WEECHAT_PLUGIN_DESCRIPTION(N_("Typing status of users"));
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
WEECHAT_PLUGIN_PRIORITY(8000);
struct t_weechat_plugin *weechat_typing_plugin = NULL;
struct t_hook *typing_signal_buffer_closing = NULL;
struct t_hook *typing_signal_input_text_changed = NULL;
struct t_hook *typing_modifier_input_text_for_buffer = NULL;
struct t_hook *typing_timer = NULL;
/*
* Sends a "typing" signal.
*
* Returns code of last callback executed.
*/
int
typing_send_signal (struct t_typing_buffer *typing_buffer,
const char *signal_name)
{
if (weechat_typing_plugin->debug)
{
weechat_printf (NULL, "%s: sending signal \"%s\" for buffer %s",
TYPING_PLUGIN_NAME,
signal_name,
weechat_buffer_get_string (typing_buffer->buffer,
"full_name"));
}
typing_buffer->last_signal_sent = time (NULL);
return weechat_hook_signal_send (signal_name,
WEECHAT_HOOK_SIGNAL_POINTER,
typing_buffer->buffer);
}
/*
* Gets typing buffer, creates it if not existing.
*/
struct t_typing_buffer *
typing_get_typing_buffer (struct t_gui_buffer *buffer)
{
struct t_typing_buffer *ptr_typing_buffer;
ptr_typing_buffer = typing_buffer_search_buffer (buffer);
if (ptr_typing_buffer)
return ptr_typing_buffer;
return typing_buffer_add (buffer);
}
/*
* Callback for signal "buffer_closing".
*/
int
typing_buffer_closing_signal_cb (const void *pointer, void *data,
const char *signal,
const char *type_data, void *signal_data)
{
struct t_typing_buffer *ptr_typing_buffer;
/* make C compiler happy */
(void) pointer;
(void) data;
(void) signal;
(void) type_data;
ptr_typing_buffer = typing_buffer_search_buffer (signal_data);
if (ptr_typing_buffer)
typing_buffer_free (ptr_typing_buffer);
return WEECHAT_RC_OK;
}
/*
* Callback for signal "buffer_closing".
*/
int
typing_input_text_changed_signal_cb (const void *pointer, void *data,
const char *signal,
const char *type_data, void *signal_data)
{
int text_search;
const char *ptr_input, *ptr_input_for_buffer;
struct t_gui_buffer *ptr_buffer;
struct t_typing_buffer *ptr_typing_buffer;
/* make C compiler happy */
(void) pointer;
(void) data;
(void) signal;
(void) type_data;
ptr_buffer = (struct t_gui_buffer *)signal_data;
/* ignore any change in input if the user is searching text in the buffer */
text_search = weechat_buffer_get_integer (ptr_buffer, "text_search");
if (text_search != 0)
return WEECHAT_RC_OK;
ptr_input = weechat_buffer_get_string (ptr_buffer, "input");
if (ptr_input && ptr_input[0])
{
/* input is a command? ignore it */
ptr_input_for_buffer = weechat_string_input_for_buffer (ptr_input);
if (!ptr_input_for_buffer)
return WEECHAT_RC_OK;
ptr_typing_buffer = typing_buffer_search_buffer (ptr_buffer);
if (!ptr_typing_buffer)
ptr_typing_buffer = typing_buffer_add (ptr_buffer);
if (!ptr_typing_buffer)
return WEECHAT_RC_OK;
ptr_typing_buffer->status = TYPING_BUFFER_STATUS_TYPING;
ptr_typing_buffer->last_typed = time (NULL);
}
else
{
/* user was typing something? */
ptr_typing_buffer = typing_buffer_search_buffer (ptr_buffer);
if (ptr_typing_buffer
&& ((ptr_typing_buffer->status == TYPING_BUFFER_STATUS_TYPING)
|| (ptr_typing_buffer->status == TYPING_BUFFER_STATUS_PAUSED)))
{
/*
* input cleared: maybe something was sent, not sure, so we just
* set the status to "cleared", a signal can be sent later
* in timer
*/
ptr_typing_buffer->status = TYPING_BUFFER_STATUS_CLEARED;
}
}
return WEECHAT_RC_OK;
}
/*
* Callback for modifier "input_text_for_buffer".
*/
char *
typing_input_text_for_buffer_modifier_cb (const void *pointer,
void *data,
const char *modifier,
const char *modifier_data,
const char *string)
{
int rc, text_search;
unsigned long value;
const char *ptr_input_for_buffer;
struct t_gui_buffer *ptr_buffer;
struct t_typing_buffer *ptr_typing_buffer;
/* make C compiler happy */
(void) pointer;
(void) data;
(void) modifier;
(void) string;
rc = sscanf (modifier_data, "%lx", &value);
if ((rc == EOF) || (rc == 0))
return NULL;
ptr_buffer = (struct t_gui_buffer *)value;
/* ignore any change in input if the user is searching text in the buffer */
text_search = weechat_buffer_get_integer (ptr_buffer, "text_search");
if (text_search != 0)
return WEECHAT_RC_OK;
/* string is a command? ignore it */
ptr_input_for_buffer = weechat_string_input_for_buffer (string);
if (!ptr_input_for_buffer)
return NULL;
ptr_typing_buffer = typing_buffer_search_buffer (ptr_buffer);
if (!ptr_typing_buffer)
ptr_typing_buffer = typing_buffer_add (ptr_buffer);
if (!ptr_typing_buffer)
return NULL;
typing_send_signal (ptr_typing_buffer, "typing_sent");
typing_buffer_free (ptr_typing_buffer);
return NULL;
}
/*
* Callback for modifier "input_text_for_buffer".
*/
int
typing_timer_cb (const void *pointer,
void *data,
int remaining_calls)
{
time_t time_now;
int delay_pause;
const char *ptr_input, *ptr_input_for_buffer;
struct t_typing_buffer *ptr_typing_buffer, *ptr_next_typing_buffer;
/* make C compiler happy */
(void) pointer;
(void) data;
(void) remaining_calls;
delay_pause = weechat_config_integer (typing_config_look_delay_pause);
time_now = time (NULL);
ptr_typing_buffer = typing_buffers;
while (ptr_typing_buffer)
{
ptr_next_typing_buffer = ptr_typing_buffer->next_buffer;
if (ptr_typing_buffer->status == TYPING_BUFFER_STATUS_TYPING)
{
ptr_input = weechat_buffer_get_string (ptr_typing_buffer->buffer,
"input");
ptr_input_for_buffer = weechat_string_input_for_buffer (ptr_input);
if (ptr_input_for_buffer)
{
/* check if typing is paused */
if (ptr_typing_buffer->last_typed < time_now - delay_pause)
{
ptr_typing_buffer->status = TYPING_BUFFER_STATUS_PAUSED;
typing_send_signal (ptr_typing_buffer, "typing_paused");
typing_buffer_free (ptr_typing_buffer);
}
else
{
typing_send_signal (ptr_typing_buffer, "typing_active");
}
}
else
{
typing_send_signal (ptr_typing_buffer, "typing_cleared");
typing_buffer_free (ptr_typing_buffer);
}
}
else if (ptr_typing_buffer->status == TYPING_BUFFER_STATUS_CLEARED)
{
typing_send_signal (ptr_typing_buffer, "typing_cleared");
typing_buffer_free (ptr_typing_buffer);
}
ptr_typing_buffer = ptr_next_typing_buffer;
}
return WEECHAT_RC_OK;
}
/*
* Creates or removes hooks, according to option typing.look.enabled.
*/
void
typing_setup_hooks ()
{
if (weechat_config_boolean (typing_config_look_enabled))
{
if (!typing_signal_buffer_closing)
{
if (weechat_typing_plugin->debug >= 2)
weechat_printf (NULL, "%s: creating hooks", TYPING_PLUGIN_NAME);
typing_signal_buffer_closing = weechat_hook_signal (
"buffer_closing",
&typing_buffer_closing_signal_cb, NULL, NULL);
typing_signal_input_text_changed = weechat_hook_signal (
"input_text_changed",
&typing_input_text_changed_signal_cb, NULL, NULL);
typing_modifier_input_text_for_buffer = weechat_hook_modifier (
"input_text_for_buffer",
&typing_input_text_for_buffer_modifier_cb, NULL, NULL);
typing_timer = weechat_hook_timer (
1000, 0, 0,
&typing_timer_cb, NULL, NULL);
}
}
else
{
if (typing_signal_buffer_closing)
{
if (weechat_typing_plugin->debug >= 2)
weechat_printf (NULL, "%s: removing hooks", TYPING_PLUGIN_NAME);
weechat_unhook (typing_signal_buffer_closing);
typing_signal_buffer_closing = NULL;
weechat_unhook (typing_signal_input_text_changed);
typing_signal_input_text_changed = NULL;
weechat_unhook (typing_modifier_input_text_for_buffer);
typing_modifier_input_text_for_buffer = NULL;
weechat_unhook (typing_timer);
typing_timer = NULL;
}
}
}
/*
* Initializes typing plugin.
*/
int
weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
{
/* make C compiler happy */
(void) argc;
(void) argv;
weechat_plugin = plugin;
if (!typing_config_init ())
return WEECHAT_RC_ERROR;
typing_config_read ();
typing_setup_hooks ();
return WEECHAT_RC_OK;
}
/*
* Ends typing plugin.
*/
int
weechat_plugin_end (struct t_weechat_plugin *plugin)
{
/* make C compiler happy */
(void) plugin;
typing_config_write ();
typing_config_free ();
return WEECHAT_RC_OK;
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2021 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef WEECHAT_PLUGIN_TYPING_H
#define WEECHAT_PLUGIN_TYPING_H
#define weechat_plugin weechat_typing_plugin
#define TYPING_PLUGIN_NAME "typing"
struct t_typing
{
struct t_hook *hook; /* command hook */
char *name; /* typing name */
char *command; /* typing command */
char *completion; /* completion for typing (if not set,*/
/* uses completion of target cmd) */
int running; /* 1 if typing is running */
struct t_typing *prev_typing; /* link to previous typing */
struct t_typing *next_typing; /* link to next typing */
};
extern struct t_typing *typing_list;
extern struct t_weechat_plugin *weechat_typing_plugin;
extern void typing_setup_hooks ();
#endif /* WEECHAT_PLUGIN_TYPING_H */

View File

@ -2093,13 +2093,12 @@ TEST(CoreString, InputForBuffer)
char *str;
POINTERS_EQUAL(NULL, string_input_for_buffer (NULL));
POINTERS_EQUAL(NULL, string_input_for_buffer ("/"));
POINTERS_EQUAL(NULL, string_input_for_buffer ("/abc"));
str = strdup ("");
STRCMP_EQUAL(str, string_input_for_buffer (str));
free (str);
str = strdup ("/");
STRCMP_EQUAL(str, string_input_for_buffer (str));
free (str);
str = strdup ("/ ");
STRCMP_EQUAL(str, string_input_for_buffer (str));
free (str);