From b83b428c5cc48043cb625844b87e94acbc194ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Helleu?= Date: Tue, 7 Nov 2023 07:22:01 +0100 Subject: [PATCH] core: add incremental search in commands history (issue #2040) Changes: - move key ctrl+r to ctrl+s - add key ctrl+r to search in commands history - add option `search_history` in command `/input` - add key context "histsearch" - add option weechat.look.buffer_search_history - add buffer variables "text_search_direction", "text_search_history" and "text_search_ptr_history" --- ChangeLog.adoc | 1 + doc/de/weechat_user.de.adoc | 75 +++++- doc/en/weechat_plugin_api.en.adoc | 19 +- doc/en/weechat_relay_protocol.en.adoc | 3 + doc/en/weechat_user.en.adoc | 58 ++++- doc/fr/weechat_plugin_api.fr.adoc | 19 +- doc/fr/weechat_relay_protocol.fr.adoc | 3 + doc/fr/weechat_user.fr.adoc | 59 ++++- doc/it/weechat_plugin_api.it.adoc | 32 ++- doc/it/weechat_user.it.adoc | 73 +++++- doc/ja/weechat_plugin_api.ja.adoc | 32 ++- doc/ja/weechat_relay_protocol.ja.adoc | 3 + doc/ja/weechat_user.ja.adoc | 74 +++++- doc/pl/weechat_user.pl.adoc | 74 +++++- doc/sr/weechat_plugin_api.sr.adoc | 32 ++- doc/sr/weechat_relay_protocol.sr.adoc | 3 + doc/sr/weechat_user.sr.adoc | 73 +++++- src/core/wee-command.c | 9 +- src/core/wee-config.c | 11 +- src/core/wee-config.h | 7 + src/core/wee-upgrade.c | 11 +- src/gui/curses/gui-curses-chat.c | 10 +- src/gui/curses/gui-curses-key.c | 25 +- src/gui/curses/gui-curses-mouse.c | 3 +- src/gui/gui-bar-item.c | 86 +++++-- src/gui/gui-buffer.c | 31 ++- src/gui/gui-buffer.h | 55 +++- src/gui/gui-history.c | 255 +++++++++++++----- src/gui/gui-history.h | 2 + src/gui/gui-input.c | 148 ++++++++--- src/gui/gui-input.h | 2 + src/gui/gui-key.c | 22 +- src/gui/gui-key.h | 1 + src/gui/gui-line.c | 4 +- src/gui/gui-window.c | 358 +++++++++++++++----------- src/gui/gui-window.h | 4 +- tests/unit/gui/test-gui-buffer.cpp | 8 +- tests/unit/gui/test-gui-key.cpp | 12 +- 38 files changed, 1311 insertions(+), 386 deletions(-) diff --git a/ChangeLog.adoc b/ChangeLog.adoc index 28565e352..31f8eae1b 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -15,6 +15,7 @@ For a list of important changes that require manual actions, please look at rele New features:: + * core: move key kbd:[Ctrl+r] to kbd:[Ctrl+s], add key kbd:[Ctrl+r] to search in commands history, add option `search_history` in command `/input`, add key context "histsearch", add option weechat.look.buffer_search_history, add buffer variables "text_search_direction", "text_search_history" and "text_search_ptr_history" (issue #2040) * core: display only version with command `/version`, add options `-o` and `-ol` in command `/upgrade` * core: add number of processes in command `/sys waitpid` * core, alias, trigger: allow wildcard in commands `/bar`, `/item`, `/proxy`, `/alias` and `/trigger` (issue #1956) diff --git a/doc/de/weechat_user.de.adoc b/doc/de/weechat_user.de.adoc index a30396ac1..05c6220d7 100644 --- a/doc/de/weechat_user.de.adoc +++ b/doc/de/weechat_user.de.adoc @@ -920,11 +920,37 @@ In der _input_ Bar lautet die Standardeinstellung: | Item | Beispiel | Beschreibung | input_prompt | `[@Flashy(i)]` | Input prompt, für irc: Nick und Modi (Modus "+i" bedeutet auf libera, unsichtbar). | away | `(away)` | Abwesenheitsanzeige. -| input_search | `[Search (~ str,msg)]` | Suchindikatoren ("`~`": Groß-und Kleinschreibung ignorieren, "`==`": Groß-und Kleinschreibung berücksichtigen, "`str`": einfache Textsuche, "`regex`": suche mit regulären Ausdrücken, "`msg`": Suche in Nachrichten, "`pre`": Suche in Präfix, "`pre\|msg`": Suche in Präfix und Nachrichten). +// TRANSLATION MISSING +| input_search | `[Search lines (~ str,msg)]` | Suchindikatoren ("`~`": Groß-und Kleinschreibung ignorieren, "`==`": Groß-und Kleinschreibung berücksichtigen, "`str`": einfache Textsuche, "`regex`": suche mit regulären Ausdrücken, "`msg`": Suche in Nachrichten, "`pre`": Suche in Präfix, "`pre\|msg`": Suche in Präfix und Nachrichten). +// TRANSLATION MISSING | input_paste | `[Paste 7 lines ? [ctrl-y] Ja [ctrl-n] Nein]` | Nachfrage ob sieben Zeilen eingefügt werden sollen. | input_text | `hi peter!` | Text der eingegeben wird. |=== +// TRANSLATION MISSING +There are two search modes: + +// TRANSLATION MISSING +* search in lines, for example `[Search lines (~ str,msg)]`, with the following info: +** `~`: Groß-und Kleinschreibung ignorieren +** `==`: Groß-und Kleinschreibung berücksichtigen +** `str`: einfache Textsuche +** `regex`: suche mit regulären Ausdrücken +** `msg`: Suche in Nachrichten +** `pre`: Suche in Präfix +** `pre\|msg`: Suche in Präfix und Nachrichten +// TRANSLATION MISSING +* search in commands history, for example `[Search command (~ str,local)]`, + with the following info: +** `~`: Groß-und Kleinschreibung ignorieren +** `==`: Groß-und Kleinschreibung berücksichtigen +** `str`: einfache Textsuche +** `regex`: suche mit regulären Ausdrücken +// TRANSLATION MISSING +** `local`: search in buffer local history +// TRANSLATION MISSING +** `global`: search in global history. + In der _nicklist_ Bar lautet die Standardeinstellung: [width="100%",cols="^3,^3,9",options="header"] @@ -1630,7 +1656,10 @@ Sie können mit dem Befehl <> geändert und neue hinzu [width="100%",cols="^.^3,.^8,.^5",options="header"] |=== | Taste | Beschreibung | Befehl -| kbd:[Ctrl+r] | Textsuche im Verlaufsspeicher des Buffers (siehe <>). | `+/input search_text_here+` +// TRANSLATION MISSING +| kbd:[Ctrl+r] | Search for text in commands history (see <>). | `+/input search_history+` +// TRANSLATION MISSING +| kbd:[Ctrl+s] | Search for text in buffer lines (see <>). | `+/input search_text_here+` | kbd:[Ctrl+s], kbd:[Ctrl+u] | setzt für alle Buffer die Markierung für ungelesene Nachrichten. | `+/allbuf /buffer set unread+` | kbd:[Ctrl+x] | Wechseln Sie den aktuellen Buffer, wenn diese zusammengefügt worden sind, z.B. zwischen IRC-Serverbuffer wechseln. | `+/buffer switch+` | kbd:[Alt+x] | Zoom eines zusammengefügten Buffers (kbd:[Alt+x] ein zweites mal: alle zusammengefügten Buffer werden angezeigt). | `+/buffer zoom+` @@ -1733,23 +1762,55 @@ Sie können mit dem Befehl <> geändert und neue hinzu [[key_bindings_search_context]] === Suchkontext -Diese Tasten werden im Kontext "search" verwendet (wenn kbd:[Ctrl+r] genutzt wird um -in einem Buffer nach einem Text zu suchen). +// TRANSLATION MISSING +These keys are used in context "search" (when kbd:[Ctrl+s] is pressed to search +text in buffer lines). [width="100%",cols="^.^3,.^8,.^5",options="header"] |=== | Taste | Beschreibung | Befehl -| kbd:[Ctrl+r] | Wechsel des Suchmodus: einfache Textsuche (Standard), reguläre Ausdrücke. | `+/input search_switch_regex+` +| kbd:[Ctrl+x] | Wechsel des Suchmodus: einfache Textsuche (Standard), reguläre Ausdrücke. | `+/input search_switch_regex+` | kbd:[Alt+c] | auf Groß-/Kleinschreibung umschalten. | `+/input search_switch_case+` | kbd:[Tab] | wechselt Suche in: Nachricht (Standard), im Präfix, Präfix + Nachricht. | `+/input search_switch_where+` -| kbd:[↑] | sucht vorheriger Zeile. | `+/input search_previous+` -| kbd:[↓] | sucht nächste Zeile . | `+/input search_next+` +| kbd:[Ctrl+r] + + kbd:[↑] | sucht vorheriger Zeile. | `+/input search_previous+` +| kbd:[Ctrl+s] + + kbd:[↓] | sucht nächste Zeile . | `+/input search_next+` | kbd:[Enter] + kbd:[Ctrl+j] + kbd:[Ctrl+m] | beendet Suche ab aktueller Position. | `+/input search_stop_here+` | kbd:[Ctrl+q] | Suche wird abgebrochen und der Bildlauf wird auf die Vortextsuche zurückgesetzt. | `+/input search_stop+` |=== +// TRANSLATION MISSING +[[key_bindings_histsearch_context]] +=== History search context + +// TRANSLATION MISSING +These keys are used in context "histsearch" (when kbd:[Ctrl+r] is pressed to +search text in commands history). + +[width="100%",cols="^.^3,.^8,.^5",options="header"] +|=== +| Taste | Beschreibung | Befehl +| kbd:[Ctrl+x] | Wechsel des Suchmodus: einfache Textsuche (Standard), reguläre Ausdrücke. | `+/input search_switch_regex+` +| kbd:[Alt+c] | auf Groß-/Kleinschreibung umschalten. | `+/input search_switch_case+` +// TRANSLATION MISSING +| kbd:[Tab] | Switch search in: buffer local history (default), global history. | `+/input search_switch_where+` +// TRANSLATION MISSING +| kbd:[Ctrl+r] + + kbd:[↑] | Search in previous (older) history entries. | `+/input search_previous+` +// TRANSLATION MISSING +| kbd:[Ctrl+s] + + kbd:[↓] | Search in next (newer) history entries. | `+/input search_next+` +// TRANSLATION MISSING +| kbd:[Enter] + + kbd:[Ctrl+j] + + kbd:[Ctrl+m] | Stop search and use matching input. | `+/input search_stop_here+` +// TRANSLATION MISSING +| kbd:[Ctrl+q] | Stop search and restore input to its initial value. | `+/input search_stop+` +|=== + [[key_bindings_cursor_context]] === Cursor-Kontext diff --git a/doc/en/weechat_plugin_api.en.adoc b/doc/en/weechat_plugin_api.en.adoc index bbd2ec40a..fb2d2dec3 100644 --- a/doc/en/weechat_plugin_api.en.adoc +++ b/doc/en/weechat_plugin_api.en.adoc @@ -14120,9 +14120,22 @@ Arguments: ** _num_history_: number of commands in history ** _text_search_: text search type: *** 0: no search at this moment -*** 1: backward search (direction: oldest messages) -*** 2: forward search (direction: newest messages) +*** 1: search in buffer lines +*** 2: search in commands history +** _text_search_direction_: direction for search: +*** 0: backward search (direction: oldest messages/commands) +*** 1: forward search (direction: newest messages/commands) ** _text_search_exact_: 1 if text search is case sensitive +** _text_search_regex_: 1 if searching with a regular expression +** _text_search_where_: +*** 0: no search at this moment +*** 1: search in message +*** 2: search in prefix +*** 3: search in prefix and message +** _text_search_history_: +*** 0: no search at this moment +*** 1: search in buffer local history +*** 2: search in global history ** _text_search_found_: 1 if text found, otherwise 0 Return value: @@ -14227,6 +14240,8 @@ Arguments: * _property_: property name: ** _plugin_: pointer to plugin which created this buffer (NULL for WeeChat main buffer) +** _text_search_regex_compiled_: compiled regular expression +** _text_search_ptr_history_: history found ** _highlight_disable_regex_compiled_: regular expression _highlight_disable_regex_ compiled ** _highlight_regex_compiled_: regular expression _highlight_regex_ compiled diff --git a/doc/en/weechat_relay_protocol.en.adoc b/doc/en/weechat_relay_protocol.en.adoc index 498815638..864953760 100644 --- a/doc/en/weechat_relay_protocol.en.adoc +++ b/doc/en/weechat_relay_protocol.en.adoc @@ -712,11 +712,14 @@ inl: input_buffer_1st_display: 0 num_history: 0 text_search: 0 + text_search_direction: 0 text_search_exact: 0 text_search_regex: 0 text_search_regex_compiled: '0x0' text_search_where: 0 + text_search_history: 0 text_search_found: 0 + text_search_ptr_history: '0x0' text_search_input: None highlight_words: None highlight_disable_regex: None diff --git a/doc/en/weechat_user.en.adoc b/doc/en/weechat_user.en.adoc index 41dc69b73..a6f4a506c 100644 --- a/doc/en/weechat_user.en.adoc +++ b/doc/en/weechat_user.en.adoc @@ -914,11 +914,30 @@ Bar _input_ has following default items: | Item | Example | Description | input_prompt | `[@Flashy(i)]` | Input prompt, for irc: nick and modes (mode "+i" means invisible on libera). | away | `(away)` | Away indicator. -| input_search | `[Search (~ str,msg)]` | Search indicator ("`~`": case insensitive, "`==`": case sensitive, "`str`": search string, "`regex`": search regular expression, "`msg`": search in messages, "`pre`": search in prefixes, "`pre\|msg`": search in prefixes and messages). +| input_search | `[Search lines (~ str,msg)]` | Search indicator (see below) | input_paste | `[Paste 7 lines ? [ctrl-y] Yes [ctrl-n] No]` | Question to user for pasting lines. | input_text | `hi peter!` | Input text. |=== +There are two search modes: + +* search in lines, for example `[Search lines (~ str,msg)]`, with the following info: +** `~`: case insensitive +** `==`: case sensitive +** `str`: search string +** `regex`: search regular expression +** `msg`: search in messages +** `pre`: search in prefixes +** `pre\|msg`: search in prefixes and messages. +* search in commands history, for example `[Search command (~ str,local)]`, + with the following info: +** `~`: case insensitive +** `==`: case sensitive +** `str`: search string +** `regex`: search regular expression +** `local`: search in buffer local history +** `global`: search in global history. + Bar _nicklist_ has following default items: [width="100%",cols="^3,^3,9",options="header"] @@ -1613,7 +1632,8 @@ They can be changed and new ones can be added with the <>). | `+/input search_text_here+` +| kbd:[Ctrl+r] | Search for text in commands history (see <>). | `+/input search_history+` +| kbd:[Ctrl+s] | Search for text in buffer lines (see <>). | `+/input search_text_here+` | kbd:[Ctrl+s], kbd:[Ctrl+u] | Set unread marker on all buffers. | `+/allbuf /buffer set unread+` | kbd:[Ctrl+x] | Switch current buffer if buffers are merged with same number, for example switch to another IRC server buffer. | `+/buffer switch+` | kbd:[Alt+x] | Zoom on merged buffer (kbd:[Alt+x] again: display all merged buffers). | `+/buffer zoom+` @@ -1716,23 +1736,47 @@ They can be changed and new ones can be added with the <>). | `+/input search_text_here+` +| kbd:[Ctrl+r] | Chercher du texte dans l'historique de commandes (voir <>). | `+/input search_history+` +| kbd:[Ctrl+s] | Chercher du texte dans les lignes du tampon (voir <>). | `+/input search_text_here+` | kbd:[Ctrl+s], kbd:[Ctrl+u] | Positionner le marqueur de données non lues sur tous les tampons. | `+/allbuf /buffer set unread+` | kbd:[Ctrl+x] | Changer de tampon courant si plusieurs tampons sont mélangés avec le même numéro, par exemple basculer vers un autre tampon serveur IRC. | `+/buffer switch+` | kbd:[Alt+x] | Zoomer sur le tampon mélangé (kbd:[Alt+x] de nouveau : afficher tous les tampons mélangés). | `+/buffer zoom+` @@ -1751,23 +1772,47 @@ Ils peuvent être modifiés et de nouveaux peuvent être ajoutés avec la comman [[key_bindings_search_context]] === Contexte de recherche -Ces touches sont utilisées dans le contexte "search" (lorsque kbd:[Ctrl+r] est -pressé pour chercher du texte dans le tampon). +Ces touches sont utilisées dans le contexte "search" (lorsque kbd:[Ctrl+s] est +pressé pour chercher du texte dans les lignes du tampon). [width="100%",cols="^.^3,.^8,.^5",options="header"] |=== | Touche | Description | Commande -| kbd:[Ctrl+r] | Basculer le type de recherche : chaîne (par défaut), expression régulière. | `+/input search_switch_regex+` +| kbd:[Ctrl+x] | Basculer le type de recherche : chaîne (par défaut), expression régulière. | `+/input search_switch_regex+` | kbd:[Alt+c] | Basculer la casse exacte pour la recherche. | `+/input search_switch_case+` | kbd:[Tab] | Basculer la recherche dans : les messages (par défaut), les préfixes, les préfixes + messages. | `+/input search_switch_where+` -| kbd:[↑] | Chercher la ligne précédente. | `+/input search_previous+` -| kbd:[↓] | Chercher la ligne suivante. | `+/input search_next+` +| kbd:[Ctrl+r] + + kbd:[↑] | Chercher la ligne précédente. | `+/input search_previous+` +| kbd:[Ctrl+s] + + kbd:[↓] | Chercher la ligne suivante. | `+/input search_next+` | kbd:[Enter] + kbd:[Ctrl+j] + kbd:[Ctrl+m] | Arrêter la recherche à la position courante. | `+/input search_stop_here+` | kbd:[Ctrl+q] | Arrêter la recherche et réinitialiser le défilement à l'état antérieur à la recherche de texte. | `+/input search_stop+` |=== +[[key_bindings_histsearch_context]] +=== Contexte de recherche dans l'historique + +Ces touches sont utilisées dans le contexte "histsearch" (lorsque kbd:[Ctrl+r] +est pressé pour chercher du texte dans l'historique des commandes). + +[width="100%",cols="^.^3,.^8,.^5",options="header"] +|=== +| Touche | Description | Commande +| kbd:[Ctrl+x] | Basculer le type de recherche : chaîne (par défaut), expression régulière. | `+/input search_switch_regex+` +| kbd:[Alt+c] | Basculer la casse exacte pour la recherche. | `+/input search_switch_case+` +| kbd:[Tab] | Basculer la recherche dans : l'historique local du tampon (par défaut), l'historique global. | `+/input search_switch_where+` +| kbd:[Ctrl+r] + + kbd:[↑] | Chercher dans les entrées précédentes (plus anciennes) de l'historique. | `+/input search_previous+` +| kbd:[Ctrl+s] + + kbd:[↓] | Chercher dans les entrées suivantes (plus récentes) de l'historique. | `+/input search_next+` +| kbd:[Enter] + + kbd:[Ctrl+j] + + kbd:[Ctrl+m] | Arrêter la recherche et utiliser la commande trouvée. | `+/input search_stop_here+` +| kbd:[Ctrl+q] | Arrêter la recherche et restaurer la ligne de commande à sa valeur initiale. | `+/input search_stop+` +|=== + [[key_bindings_cursor_context]] === Contexte curseur diff --git a/doc/it/weechat_plugin_api.it.adoc b/doc/it/weechat_plugin_api.it.adoc index c8330e7fc..4c2a28d0c 100644 --- a/doc/it/weechat_plugin_api.it.adoc +++ b/doc/it/weechat_plugin_api.it.adoc @@ -14767,9 +14767,33 @@ Argomenti: ** _num_history_: numero di comandi nella cronologia ** _text_search_: tipo di ricerca nel testo: *** 0: nessuna ricerca in questo momento -*** 1: ricerca all'indietro (direzione: messaggi più vecchi) -*** 2: ricerca in avanti (direzione: messaggi più nuovi) +// TRANSLATION MISSING +*** 1: search in buffer lines +// TRANSLATION MISSING +*** 2: search in commands history +// TRANSLATION MISSING +** _text_search_direction_: direction for search: +// TRANSLATION MISSING +*** 0: backward search (direction: oldest messages/commands) +// TRANSLATION MISSING +*** 1: forward search (direction: newest messages/commands) ** _text_search_exact_: 1 se la ricerca testo è esatta +// TRANSLATION MISSING +** _text_search_regex_: 1 if searching with a regular expression +** _text_search_where_: +*** 0: nessuna ricerca in questo momento +// TRANSLATION MISSING +*** 1: search in message +// TRANSLATION MISSING +*** 2: search in prefix +// TRANSLATION MISSING +*** 3: search in prefix and message +** _text_search_history_: +*** 0: nessuna ricerca in questo momento +// TRANSLATION MISSING +*** 1: search in buffer local history +// TRANSLATION MISSING +*** 2: search in global history ** _text_search_found_: 1 se il testo viene trovato, altrimenti 0 Valore restituito: @@ -14878,6 +14902,10 @@ Argomenti: * _property_: nome proprietà: ** _plugin_: puntatore al plugin che ha creato questo buffer (NULL per il buffer principale di WeeChat) +// TRANSLATION MISSING +** _text_search_regex_compiled_: compiled regular expression +// TRANSLATION MISSING +** _text_search_ptr_history_: history found ** _highlight_disable_regex_compiled_: espressione regolare _highlight_disable_regex_ compilata ** _highlight_regex_compiled_: espressione regolare _highlight_regex_ compilata diff --git a/doc/it/weechat_user.it.adoc b/doc/it/weechat_user.it.adoc index 5a0b426b5..fae58e055 100644 --- a/doc/it/weechat_user.it.adoc +++ b/doc/it/weechat_user.it.adoc @@ -1003,11 +1003,33 @@ La barra _input_ ha i seguenti elementi predefiniti: | input_prompt | `[@Flashy(i)]` | Prompt per l'input, for irc: nick and modes (mode "+i" means invisible on libera). | away | `(assente)` | Indicatore di assenza. // TRANSLATION MISSING -| input_search | `[Search (~ str,msg)]` | Search indicator ("`~`": case insensitive, "`==`": case sensitive, "`str`": search string, "`regex`": search regular expression, "`msg`": search in messages, "`pre`": search in prefixes, "`pre\|msg`": search in prefixes and messages). +| input_search | `[Search lines (~ str,msg)]` | Search indicator (see below). | input_paste | `[Incollare 7 righe ? [ctrl-y] Sì [ctrl-n] No]` | Chiede all'utente se incollare le righe. | input_text | `ciao peter!` | Testo in input. |=== +// TRANSLATION MISSING +There are two search modes: + +// TRANSLATION MISSING +* search in lines, for example `[Search lines (~ str,msg)]`, with the following info: +** `~`: case insensitive +** `==`: case sensitive +** `str`: search string +** `regex`: search regular expression +** `msg`: search in messages +** `pre`: search in prefixes +** `pre\|msg`: search in prefixes and messages. +* search in commands history, for example `[Search command (~ str,local)]`, + with the following info: +** `~`: case insensitive +** `==`: case sensitive +** `str`: search string +** `regex`: search regular expression +** `local`: search in buffer local history +** `global`: search in global history. + + La barra _nicklist_ ha i seguenti elementi predefiniti: [width="100%",cols="^3,^3,9",options="header"] @@ -1766,7 +1788,10 @@ They can be changed and new ones can be added with the <>). | `+/input search_text_here+` +// TRANSLATION MISSING +| kbd:[Ctrl+r] | Search for text in commands history (see <>). | `+/input search_history+` +// TRANSLATION MISSING +| kbd:[Ctrl+s] | Search for text in buffer lines (see <>). | `+/input search_text_here+` | kbd:[Ctrl+s], kbd:[Ctrl+u] | Imposta l'evidenziatore dei messaggi non letti su tutti i buffer. | `+/allbuf /buffer set unread+` // TRANSLATION MISSING | kbd:[Ctrl+x] | Switch current buffer if buffers are merged with same number, for example switch to another IRC server buffer. | `+/buffer switch+` @@ -1888,19 +1913,22 @@ They can be changed and new ones can be added with the <>を参照) | `+/input search_text_here+` +// TRANSLATION MISSING +| kbd:[Ctrl+r] | Search for text in commands history (see <>). | `+/input search_history+` +// TRANSLATION MISSING +| kbd:[Ctrl+s] | Search for text in buffer lines (see <>). | `+/input search_text_here+` | kbd:[Ctrl+s], kbd:[Ctrl+u] | すべてのバッファに未読マークをセット | `+/allbuf /buffer set unread+` // TRANSLATION MISSING | kbd:[Ctrl+x] | Switch current buffer if buffers are merged with same number, for example switch to another IRC server buffer. | `+/buffer switch+` @@ -1842,17 +1870,20 @@ They can be changed and new ones can be added with the <>). | `+/input search_text_here+` +// TRANSLATION MISSING +| kbd:[Ctrl+r] | Search for text in commands history (see <>). | `+/input search_history+` +// TRANSLATION MISSING +| kbd:[Ctrl+s] | Search for text in buffer lines (see <>). | `+/input search_text_here+` | kbd:[Ctrl+s], kbd:[Ctrl+u] | Ustaw znacznik nieprzeczytania we wszystkich buforach. | `+/allbuf /buffer set unread+` | kbd:[Ctrl+x] | Przełącz obecny bufor jeśli bufory są połączone pod tym samym numerem, na przykład przełącz na bufor innego serwera IRC. | `+/buffer switch+` | kbd:[Alt+x] | Pokaż wybrany z połączonych buforów (naciśnij kbd:[Alt+x] ponownie: wyświetl wszystkie połączone bufory). | `+/buffer zoom+` @@ -1737,23 +1765,55 @@ Można je zmienić oraz dodać nowe za pomocą komendy <>). | `+/input search_text_here+` +// TRANSLATION MISSING +| kbd:[Ctrl+r] | Search for text in commands history (see <>). | `+/input search_history+` +// TRANSLATION MISSING +| kbd:[Ctrl+s] | Search for text in buffer lines (see <>). | `+/input search_text_here+` | kbd:[Ctrl+s], kbd:[Ctrl+u] | Поставља маркер непрочитано за све бафере. | `+/allbuf /buffer set unread+` | kbd:[Ctrl+x] | Мења текући бафер ако су бафери спојени са истим бројем, на пример, прелазак на други IRC сервер бафер. | `+/buffer switch+` | kbd:[Alt+x] | Зум на спојени бафер (kbd:[Alt+x] поново: приказује све спојене бафере). | `+/buffer zoom+` @@ -1642,22 +1670,55 @@ WeeChat нуди доста подразумеваних тастерских п [[key_bindings_search_context]] === Контекст претраге -Следећи тастери се користе у „search” контексту (када се притисне kbd:[Ctrl+r] за претрагу текста у баферу). +// TRANSLATION MISSING +These keys are used in context "search" (when kbd:[Ctrl+s] is pressed to search +text in buffer lines). [width="100%", cols="^.^3,.^8,.^5", options="header"] |=== | Тастер | Опис | Команда -| kbd:[Ctrl+r] | Пребацивање типа претраге: стринг (подраз.), регуларни израз. | `+/input search_switch_regex+` +| kbd:[Ctrl+x] | Пребацивање типа претраге: стринг (подраз.), регуларни израз. | `+/input search_switch_regex+` | kbd:[Alt+c] | Пребацивање разликовања величине слова у претраци. | `+/input search_switch_case+` | kbd:[Tab] | Пребацивање претраге у: порукама (подраз.), префиксима, префиксима + порукама. | `+/input search_switch_where+` -| kbd:[↑] | Претрага претходне линије. | `+/input search_previous+` -| kbd:[↓] | Претрага наредне линије. | `+/input search_next+` +| kbd:[Ctrl+r] + + kbd:[↑] | Претрага претходне линије. | `+/input search_previous+` +| kbd:[Ctrl+s] + + kbd:[↓] | Претрага наредне линије. | `+/input search_next+` | kbd:[Enter] + kbd:[Ctrl+j] + kbd:[Ctrl+m] | Заустављање претраге на текућој позицији. | `+/input search_stop_here+` | kbd:[Ctrl+q] | Заустављање претраге и ресетовање скрола на стање пре почетка претраге текста. | `+/input search_stop+` |=== +// TRANSLATION MISSING +[[key_bindings_histsearch_context]] +=== History search context + +// TRANSLATION MISSING +These keys are used in context "histsearch" (when kbd:[Ctrl+r] is pressed to +search text in commands history). + +[width="100%",cols="^.^3,.^8,.^5",options="header"] +|=== +| Тастер | Опис | Команда +| kbd:[Ctrl+x] | Пребацивање типа претраге: стринг (подраз.), регуларни израз. | `+/input search_switch_regex+` +| kbd:[Alt+c] | Пребацивање разликовања величине слова у претраци. | `+/input search_switch_case+` +// TRANSLATION MISSING +| kbd:[Tab] | Switch search in: buffer local history (default), global history. | `+/input search_switch_where+` +// TRANSLATION MISSING +| kbd:[Ctrl+r] + + kbd:[↑] | Search in previous (older) history entries. | `+/input search_previous+` +// TRANSLATION MISSING +| kbd:[Ctrl+s] + + kbd:[↓] | Search in next (newer) history entries. | `+/input search_next+` +// TRANSLATION MISSING +| kbd:[Enter] + + kbd:[Ctrl+j] + + kbd:[Ctrl+m] | Stop search and use matching input. | `+/input search_stop_here+` +// TRANSLATION MISSING +| kbd:[Ctrl+q] | Stop search and restore input to its initial value. | `+/input search_stop+` +|=== + [[key_bindings_cursor_context]] === Контекст курсора diff --git a/src/core/wee-command.c b/src/core/wee-command.c index 80a053e3e..02d0da641 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -3525,6 +3525,8 @@ COMMAND_CALLBACK(input) gui_input_search_text_here (buffer); else if (string_strcmp (argv[1], "search_text") == 0) gui_input_search_text (buffer); + else if (string_strcmp (argv[1], "search_history") == 0) + gui_input_search_history (buffer); else if (string_strcmp (argv[1], "search_previous") == 0) gui_input_search_previous (buffer); else if (string_strcmp (argv[1], "search_next") == 0) @@ -8481,6 +8483,7 @@ command_init () N_("> raw[complete_previous]: complete word with previous completion"), N_("> raw[search_text_here]: search text in buffer at current position"), N_("> raw[search_text]: search text in buffer"), + N_("> raw[search_history]: search text in command line history"), N_("> raw[search_switch_case]: switch exact case for search"), N_("> raw[search_switch_regex]: switch search type: string/regular expression"), N_("> raw[search_switch_where]: switch search in messages/prefixes"), @@ -8535,9 +8538,9 @@ command_init () N_("This command is used by key bindings or plugins.")), "return || split_return || " "complete_next || complete_previous || search_text_here || " - "search_text || search_switch_case || search_switch_regex || " - "search_switch_where || search_previous || search_next || " - "search_stop_here || search_stop || " + "search_text || search_history || search_switch_case || " + "search_switch_regex || search_switch_where || search_previous || " + "search_next || search_stop_here || search_stop || " "delete_previous_char || delete_next_char || delete_previous_word || " "delete_previous_word_whitespace || delete_next_word || " "delete_beginning_of_line || delete_beginning_of_input || " diff --git a/src/core/wee-config.c b/src/core/wee-config.c index 65644d324..ebf058958 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -89,7 +89,7 @@ struct t_config_section *weechat_config_section_buffer = NULL; struct t_config_section *weechat_config_section_notify = NULL; struct t_config_section *weechat_config_section_filter = NULL; struct t_config_section *weechat_config_section_key[GUI_KEY_NUM_CONTEXTS] = { - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, }; /* config, startup section */ @@ -114,6 +114,7 @@ struct t_config_option *config_look_buffer_auto_renumber = NULL; struct t_config_option *config_look_buffer_notify_default = NULL; struct t_config_option *config_look_buffer_position = NULL; struct t_config_option *config_look_buffer_search_case_sensitive = NULL; +struct t_config_option *config_look_buffer_search_history = NULL; struct t_config_option *config_look_buffer_search_force_default = NULL; struct t_config_option *config_look_buffer_search_regex = NULL; struct t_config_option *config_look_buffer_search_where = NULL; @@ -3167,6 +3168,14 @@ config_weechat_init_options () N_("default text search in buffer: case sensitive or not"), NULL, 0, 0, "off", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + config_look_buffer_search_history = config_file_new_option ( + weechat_config_file, weechat_config_section_look, + "buffer_search_history", "enum", + N_("default text search command line history: local (buffer) or " + "global history"), + "local|global", 0, 0, "local", + NULL, 0, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); config_look_buffer_search_force_default = config_file_new_option ( weechat_config_file, weechat_config_section_look, "buffer_search_force_default", "boolean", diff --git a/src/core/wee-config.h b/src/core/wee-config.h index 286a02c8b..a191505f1 100644 --- a/src/core/wee-config.h +++ b/src/core/wee-config.h @@ -50,6 +50,12 @@ enum t_config_look_buffer_position CONFIG_LOOK_BUFFER_POSITION_FIRST_GAP, }; +enum t_config_look_buffer_search_history +{ + CONFIG_LOOK_BUFFER_SEARCH_HISTORY_LOCAL = 0, + CONFIG_LOOK_BUFFER_SEARCH_HISTORY_GLOBAL, +}; + enum t_config_look_buffer_search_where { CONFIG_LOOK_BUFFER_SEARCH_PREFIX = 0, @@ -165,6 +171,7 @@ extern struct t_config_option *config_look_buffer_auto_renumber; extern struct t_config_option *config_look_buffer_notify_default; extern struct t_config_option *config_look_buffer_position; extern struct t_config_option *config_look_buffer_search_case_sensitive; +extern struct t_config_option *config_look_buffer_search_history; extern struct t_config_option *config_look_buffer_search_force_default; extern struct t_config_option *config_look_buffer_search_regex; extern struct t_config_option *config_look_buffer_search_where; diff --git a/src/core/wee-upgrade.c b/src/core/wee-upgrade.c index dc04e33df..266cde9b3 100644 --- a/src/core/wee-upgrade.c +++ b/src/core/wee-upgrade.c @@ -546,16 +546,7 @@ upgrade_weechat_read_buffer (struct t_infolist *infolist) } } - /* text search */ - ptr_buffer->text_search = infolist_integer (infolist, "text_search"); - ptr_buffer->text_search_exact = infolist_integer (infolist, - "text_search_exact"); - ptr_buffer->text_search_found = infolist_integer (infolist, - "text_search_found"); - if (ptr_buffer->text_search_input) - free (ptr_buffer->text_search_input); - str = infolist_string (infolist, "text_search_input"); - ptr_buffer->text_search_input = (str) ? strdup (str) : NULL; + /* text search is disabled after upgrade */ /* highlight options */ gui_buffer_set_highlight_words ( diff --git a/src/gui/curses/gui-curses-chat.c b/src/gui/curses/gui-curses-chat.c index bc2fb99c6..cfdfd2f9b 100644 --- a/src/gui/curses/gui-curses-chat.c +++ b/src/gui/curses/gui-curses-chat.c @@ -1505,8 +1505,8 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, ptr_data = (message_with_tags) ? message_with_tags : line->data->message; message_with_search = NULL; - if ((window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED) - && (window->buffer->text_search_where & GUI_TEXT_SEARCH_IN_MESSAGE) + if ((window->buffer->text_search == GUI_BUFFER_SEARCH_LINES) + && (window->buffer->text_search_where & GUI_BUFFER_SEARCH_IN_MESSAGE) && (!window->buffer->text_search_regex || window->buffer->text_search_regex_compiled)) { @@ -1695,7 +1695,7 @@ gui_chat_display_line (struct t_gui_window *window, struct t_gui_line *line, else { /* display marker if line is matching user search */ - if (window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED) + if (window->buffer->text_search == GUI_BUFFER_SEARCH_LINES) { if (gui_line_search_text (window->buffer, line)) { @@ -1765,8 +1765,8 @@ gui_chat_display_line_y (struct t_gui_window *window, struct t_gui_line *line, } /* emphasize text (if searching text) */ - if ((window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED) - && (window->buffer->text_search_where & GUI_TEXT_SEARCH_IN_MESSAGE) + if ((window->buffer->text_search == GUI_BUFFER_SEARCH_LINES) + && (window->buffer->text_search_where & GUI_BUFFER_SEARCH_IN_MESSAGE) && (!window->buffer->text_search_regex || window->buffer->text_search_regex_compiled)) { diff --git a/src/gui/curses/gui-curses-key.c b/src/gui/curses/gui-curses-key.c index cb5279ff0..397605d49 100644 --- a/src/gui/curses/gui-curses-key.c +++ b/src/gui/curses/gui-curses-key.c @@ -83,7 +83,8 @@ gui_key_default_bindings (int context, int create_option) BIND("meta-return", "/input insert \\n"); BIND("tab", "/input complete_next"); BIND("shift-tab", "/input complete_previous"); - BIND("ctrl-r", "/input search_text_here"); + BIND("ctrl-r", "/input search_history"); + BIND("ctrl-s", "/input search_text_here"); BIND("backspace", "/input delete_previous_char"); BIND("ctrl-_", "/input undo"); BIND("meta-_", "/input redo"); @@ -206,14 +207,17 @@ gui_key_default_bindings (int context, int create_option) BIND(key_str, command); } } - else if (context == GUI_KEY_CONTEXT_SEARCH) + else if ((context == GUI_KEY_CONTEXT_SEARCH) + || (context == GUI_KEY_CONTEXT_HISTSEARCH)) { BIND("return", "/input search_stop_here"); BIND("ctrl-q", "/input search_stop"); BIND("meta-c", "/input search_switch_case"); - BIND("ctrl-r", "/input search_switch_regex"); + BIND("ctrl-x", "/input search_switch_regex"); BIND("tab", "/input search_switch_where"); + BIND("ctrl-r", "/input search_previous"); BIND("up", "/input search_previous"); + BIND("ctrl-s", "/input search_next"); BIND("down", "/input search_next"); } else if (context == GUI_KEY_CONTEXT_CURSOR) @@ -414,7 +418,7 @@ gui_key_flush (int paste) gui_key_last_key_pressed_sent = i; } - if (gui_current_window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED) + if (gui_current_window->buffer->text_search != GUI_BUFFER_SEARCH_DISABLED) input_old = (gui_current_window->buffer->input_buffer) ? strdup (gui_current_window->buffer->input_buffer) : strdup (""); else @@ -434,17 +438,17 @@ gui_key_flush (int paste) undo_done = 1; } - /* incremental text search in buffer */ + /* incremental text search in buffer lines or command line history */ if ((old_buffer == gui_current_window->buffer) - && (gui_current_window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED) + && ((gui_current_window->buffer->text_search == GUI_BUFFER_SEARCH_LINES) + || (gui_current_window->buffer->text_search == GUI_BUFFER_SEARCH_HISTORY)) && ((input_old == NULL) || (gui_current_window->buffer->input_buffer == NULL) || (strcmp (input_old, gui_current_window->buffer->input_buffer) != 0))) { /* * if following conditions are all true, then do not search - * again (search will not find any result and can take some time - * on a buffer with many lines): + * again (search will not find any result and can take some time): * - old search was not successful * - searching a string (not a regex) * - current input is longer than old input @@ -460,10 +464,7 @@ gui_key_flush (int paste) && (strncmp (gui_current_window->buffer->input_buffer, input_old, strlen (input_old)) == 0)) { - /* - * do not search text in buffer, just alert about text not - * found - */ + /* do not search text, just alert about text not found */ if (CONFIG_BOOLEAN(config_look_search_text_not_found_alert)) { fprintf (stderr, "\a"); diff --git a/src/gui/curses/gui-curses-mouse.c b/src/gui/curses/gui-curses-mouse.c index d463ec9ee..c0c82e47d 100644 --- a/src/gui/curses/gui-curses-mouse.c +++ b/src/gui/curses/gui-curses-mouse.c @@ -461,8 +461,7 @@ gui_mouse_event_end () else if (!gui_key_debug) { /* execute command (if found) */ - (void) gui_key_focus (mouse_key, - GUI_KEY_CONTEXT_MOUSE); + (void) gui_key_focus (mouse_key, GUI_KEY_CONTEXT_MOUSE); } if (!bare_event) gui_mouse_event_reset (); diff --git a/src/gui/gui-bar-item.c b/src/gui/gui-bar-item.c index d0db26683..23d512818 100644 --- a/src/gui/gui-bar-item.c +++ b/src/gui/gui-bar-item.c @@ -49,6 +49,7 @@ #include "gui-completion.h" #include "gui-cursor.h" #include "gui-filter.h" +#include "gui-history.h" #include "gui-hotlist.h" #include "gui-key.h" #include "gui-line.h" @@ -847,7 +848,8 @@ gui_bar_item_input_search_cb (const void *pointer, void *data, struct t_gui_buffer *buffer, struct t_hashtable *extra_info) { - char str_search[1024]; + char str_search[1024], str_where[256]; + int text_found; /* make C compiler happy */ (void) pointer; @@ -856,25 +858,52 @@ gui_bar_item_input_search_cb (const void *pointer, void *data, (void) window; (void) extra_info; - if (!buffer) + if (!buffer || (buffer->text_search == GUI_BUFFER_SEARCH_DISABLED)) return NULL; - if (buffer->text_search == GUI_TEXT_SEARCH_DISABLED) - return NULL; + str_where[0] = '\0'; - snprintf (str_search, sizeof (str_search), "%s%s (%s %s,%s%s%s)", - (buffer->text_search_found - || !buffer->input_buffer - || !buffer->input_buffer[0]) ? - GUI_COLOR_CUSTOM_BAR_FG : - gui_color_get_custom (gui_color_get_name (CONFIG_COLOR(config_color_input_text_not_found))), - _("Search"), - (buffer->text_search_exact) ? "==" : "~", - (buffer->text_search_regex) ? "regex" : "str", - (buffer->text_search_where & GUI_TEXT_SEARCH_IN_PREFIX) ? "pre" : "", - ((buffer->text_search_where & GUI_TEXT_SEARCH_IN_PREFIX) - && (buffer->text_search_where & GUI_TEXT_SEARCH_IN_MESSAGE)) ? "|" : "", - (buffer->text_search_where & GUI_TEXT_SEARCH_IN_MESSAGE) ? "msg" : ""); + switch (buffer->text_search) + { + case GUI_BUFFER_SEARCH_DISABLED: + return NULL; + case GUI_BUFFER_SEARCH_LINES: + snprintf ( + str_where, sizeof (str_where), + "%s%s%s", + (buffer->text_search_where & GUI_BUFFER_SEARCH_IN_PREFIX) ? "pre" : "", + ((buffer->text_search_where & GUI_BUFFER_SEARCH_IN_PREFIX) + && (buffer->text_search_where & GUI_BUFFER_SEARCH_IN_MESSAGE)) ? "|" : "", + (buffer->text_search_where & GUI_BUFFER_SEARCH_IN_MESSAGE) ? "msg" : ""); + break; + case GUI_BUFFER_SEARCH_HISTORY: + snprintf (str_where, sizeof (str_where), + "%s", + (buffer->text_search_history == GUI_BUFFER_SEARCH_HISTORY_LOCAL) ? + /* TRANSLATORS: search in "local" history */ + _("local") : + /* TRANSLATORS: search in "global" history */ + _("global")); + break; + case GUI_BUFFER_NUM_SEARCH: + return NULL; + } + + text_found = (buffer->text_search_found + || !buffer->input_buffer + || !buffer->input_buffer[0]); + + snprintf ( + str_search, sizeof (str_search), + "%s%s (%s %s,%s)", + (text_found) ? + GUI_COLOR_CUSTOM_BAR_FG : + gui_color_get_custom (gui_color_get_name (CONFIG_COLOR(config_color_input_text_not_found))), + (buffer->text_search == GUI_BUFFER_SEARCH_LINES) ? + _("Search lines") : _("Search command"), + (buffer->text_search_exact) ? "==" : "~", + (buffer->text_search_regex) ? "regex" : "str", + str_where); return strdup (str_search); } @@ -993,6 +1022,26 @@ gui_bar_item_input_text_cb (const void *pointer, void *data, ptr_input = ptr_input2; } + /* add matching text found in history (in history search mode) */ + if ((buffer->text_search == GUI_BUFFER_SEARCH_HISTORY) + && buffer->text_search_ptr_history) + { + length = strlen (ptr_input) + 16 + + ((buffer->text_search_ptr_history->text) ? + strlen (buffer->text_search_ptr_history->text) : 0); + buf = malloc (length); + if (buf) + { + snprintf (buf, length, + "%s => %s", + ptr_input, + (buffer->text_search_ptr_history->text) ? + buffer->text_search_ptr_history->text : ""); + free (ptr_input); + ptr_input = buf; + } + } + /* * transform '\n' to '\r' so the newlines are displayed as real new lines * instead of spaces @@ -2275,7 +2324,8 @@ gui_bar_item_init () gui_bar_item_new (NULL, gui_bar_item_names[GUI_BAR_ITEM_INPUT_TEXT], &gui_bar_item_input_text_cb, NULL, NULL); - gui_bar_item_hook_signal ("window_switch;buffer_switch;input_text_*", + gui_bar_item_hook_signal ("window_switch;buffer_switch;input_search;" + "input_text_*", gui_bar_item_names[GUI_BAR_ITEM_INPUT_TEXT]); /* time */ diff --git a/src/gui/gui-buffer.c b/src/gui/gui-buffer.c index f89b553f2..598d72bae 100644 --- a/src/gui/gui-buffer.c +++ b/src/gui/gui-buffer.c @@ -101,8 +101,8 @@ char *gui_buffer_properties_get_integer[] = "input", "input_get_unknown_commands", "input_get_empty", "input_multiline", "input_size", "input_length", "input_pos", "input_1st_display", "num_history", "text_search", - "text_search_exact", "text_search_regex", "text_search_where", - "text_search_found", + "text_search_direction", "text_search_exact", "text_search_regex", + "text_search_where", "text_search_history", "text_search_found", NULL }; char *gui_buffer_properties_get_string[] = @@ -113,8 +113,8 @@ char *gui_buffer_properties_get_string[] = NULL }; char *gui_buffer_properties_get_pointer[] = -{ "plugin", "text_search_regex_compiled", "highlight_disable_regex_compiled", - "highlight_regex_compiled", +{ "plugin", "text_search_regex_compiled", "text_search_ptr_history", + "highlight_disable_regex_compiled", "highlight_regex_compiled", NULL }; char *gui_buffer_properties_set[] = @@ -871,12 +871,15 @@ gui_buffer_new_props (struct t_weechat_plugin *plugin, new_buffer->num_history = 0; /* text search */ - new_buffer->text_search = GUI_TEXT_SEARCH_DISABLED; + new_buffer->text_search = GUI_BUFFER_SEARCH_DISABLED; + new_buffer->text_search_direction = GUI_BUFFER_SEARCH_DIR_BACKWARD; new_buffer->text_search_exact = 0; new_buffer->text_search_regex = 0; new_buffer->text_search_regex_compiled = NULL; new_buffer->text_search_where = 0; + new_buffer->text_search_history = GUI_BUFFER_SEARCH_HISTORY_NONE; new_buffer->text_search_found = 0; + new_buffer->text_search_ptr_history = NULL; new_buffer->text_search_input = NULL; /* highlight */ @@ -1391,12 +1394,16 @@ gui_buffer_get_integer (struct t_gui_buffer *buffer, const char *property) return buffer->num_history; else if (strcmp (property, "text_search") == 0) return buffer->text_search; + else if (strcmp (property, "text_search_direction") == 0) + return buffer->text_search_direction; else if (strcmp (property, "text_search_exact") == 0) return buffer->text_search_exact; else if (strcmp (property, "text_search_regex") == 0) return buffer->text_search_regex; else if (strcmp (property, "text_search_where") == 0) return buffer->text_search_where; + else if (strcmp (property, "text_search_history") == 0) + return buffer->text_search_history; else if (strcmp (property, "text_search_found") == 0) return buffer->text_search_found; @@ -1468,6 +1475,8 @@ gui_buffer_get_pointer (struct t_gui_buffer *buffer, const char *property) return buffer->plugin; else if (strcmp (property, "text_search_regex_compiled") == 0) return buffer->text_search_regex_compiled; + else if (strcmp (property, "text_search_ptr_history") == 0) + return buffer->text_search_ptr_history; else if (strcmp (property, "highlight_disable_regex_compiled") == 0) return buffer->highlight_disable_regex_compiled; else if (strcmp (property, "highlight_regex_compiled") == 0) @@ -4981,11 +4990,14 @@ gui_buffer_hdata_buffer_cb (const void *pointer, void *data, HDATA_VAR(struct t_gui_buffer, ptr_history, POINTER, 0, NULL, "history"); HDATA_VAR(struct t_gui_buffer, num_history, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, text_search, INTEGER, 0, NULL, NULL); + HDATA_VAR(struct t_gui_buffer, text_search_direction, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, text_search_exact, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, text_search_regex, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, text_search_regex_compiled, POINTER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, text_search_where, INTEGER, 0, NULL, NULL); + HDATA_VAR(struct t_gui_buffer, text_search_history, INTEGER, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, text_search_found, INTEGER, 0, NULL, NULL); + HDATA_VAR(struct t_gui_buffer, text_search_ptr_history, POINTER, 0, NULL, "history"); HDATA_VAR(struct t_gui_buffer, text_search_input, STRING, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, highlight_words, STRING, 0, NULL, NULL); HDATA_VAR(struct t_gui_buffer, highlight_disable_regex, STRING, 0, NULL, NULL); @@ -5190,6 +5202,8 @@ gui_buffer_add_to_infolist (struct t_infolist *infolist, return 0; if (!infolist_new_var_integer (ptr_item, "text_search", buffer->text_search)) return 0; + if (!infolist_new_var_integer (ptr_item, "text_search_direction", buffer->text_search_direction)) + return 0; if (!infolist_new_var_integer (ptr_item, "text_search_exact", buffer->text_search_exact)) return 0; if (!infolist_new_var_integer (ptr_item, "text_search_regex", buffer->text_search_regex)) @@ -5198,8 +5212,12 @@ gui_buffer_add_to_infolist (struct t_infolist *infolist, return 0; if (!infolist_new_var_integer (ptr_item, "text_search_where", buffer->text_search_where)) return 0; + if (!infolist_new_var_integer (ptr_item, "text_search_history", buffer->text_search_history)) + return 0; if (!infolist_new_var_integer (ptr_item, "text_search_found", buffer->text_search_found)) return 0; + if (!infolist_new_var_pointer (ptr_item, "text_search_ptr_history", buffer->text_search_ptr_history)) + return 0; if (!infolist_new_var_string (ptr_item, "text_search_input", buffer->text_search_input)) return 0; if (!infolist_new_var_string (ptr_item, "highlight_words", buffer->highlight_words)) @@ -5424,11 +5442,14 @@ gui_buffer_print_log () log_printf (" ptr_history . . . . . . : 0x%lx", ptr_buffer->ptr_history); log_printf (" num_history . . . . . . : %d", ptr_buffer->num_history); log_printf (" text_search . . . . . . . . . . : %d", ptr_buffer->text_search); + log_printf (" text_search_direction . . . . . : %d", ptr_buffer->text_search_direction); log_printf (" text_search_exact . . . . . . . : %d", ptr_buffer->text_search_exact); log_printf (" text_search_regex . . . . . . . : %d", ptr_buffer->text_search_regex); log_printf (" text_search_regex_compiled. . . : 0x%lx", ptr_buffer->text_search_regex_compiled); log_printf (" text_search_where . . . . . . . : %d", ptr_buffer->text_search_where); + log_printf (" text_search_history . . . . . . : %d", ptr_buffer->text_search_history); log_printf (" text_search_found . . . . . . . : %d", ptr_buffer->text_search_found); + log_printf (" text_search_ptr_history . . . . : 0x%lx", ptr_buffer->text_search_ptr_history); log_printf (" text_search_input . . . . . . . : '%s'", ptr_buffer->text_search_input); log_printf (" highlight_words . . . . . . . . : '%s'", ptr_buffer->highlight_words); log_printf (" highlight_disable_regex . . . . : '%s'", ptr_buffer->highlight_disable_regex); diff --git a/src/gui/gui-buffer.h b/src/gui/gui-buffer.h index 6b3357ab9..969e25a4d 100644 --- a/src/gui/gui-buffer.h +++ b/src/gui/gui-buffer.h @@ -46,6 +46,32 @@ enum t_gui_buffer_notify GUI_BUFFER_NUM_NOTIFY, }; +enum t_gui_buffer_search +{ + GUI_BUFFER_SEARCH_DISABLED = 0, + GUI_BUFFER_SEARCH_LINES, /* search in buffer lines */ + GUI_BUFFER_SEARCH_HISTORY, /* search in buffer command line history */ + /* number of search modes */ + GUI_BUFFER_NUM_SEARCH, +}; + +enum t_gui_buffer_search_dir +{ + GUI_BUFFER_SEARCH_DIR_BACKWARD = 0, + GUI_BUFFER_SEARCH_DIR_FORWARD, + /* number of search directions */ + GUI_BUFFER_NUM_SEARCH_DIR, +}; + +enum t_gui_buffer_search_history +{ + GUI_BUFFER_SEARCH_HISTORY_NONE = 0, + GUI_BUFFER_SEARCH_HISTORY_LOCAL, + GUI_BUFFER_SEARCH_HISTORY_GLOBAL, + /* number of search history */ + GUI_BUFFER_NUM_SEARCH_HISTORY, +}; + #define GUI_BUFFER_TYPE_DEFAULT GUI_BUFFER_TYPE_FORMATTED #define GUI_BUFFER_MAIN "weechat" @@ -54,12 +80,9 @@ enum t_gui_buffer_notify #define GUI_BUFFER_NUMBER_MAX (INT_MAX - 10000) -#define GUI_TEXT_SEARCH_DISABLED 0 -#define GUI_TEXT_SEARCH_BACKWARD 1 -#define GUI_TEXT_SEARCH_FORWARD 2 - -#define GUI_TEXT_SEARCH_IN_MESSAGE 1 -#define GUI_TEXT_SEARCH_IN_PREFIX 2 +/* search where in buffer lines? */ +#define GUI_BUFFER_SEARCH_IN_MESSAGE (1 << 0) +#define GUI_BUFFER_SEARCH_IN_PREFIX (1 << 1) #define GUI_BUFFER_INPUT_BLOCK_SIZE 256 @@ -189,14 +212,18 @@ struct t_gui_buffer struct t_gui_history *ptr_history; /* current command in history */ int num_history; /* number of commands in history */ - /* text search */ - int text_search; /* text search type */ - int text_search_exact; /* exact search (case sensitive) ? */ - int text_search_regex; /* search with a regex */ - regex_t *text_search_regex_compiled; /* regex used to search */ - int text_search_where; /* search where? prefix and/or msg */ - int text_search_found; /* 1 if text found, otherwise 0 */ - char *text_search_input; /* input saved before text search */ + /* text search (in buffer lines or command line history) */ + enum t_gui_buffer_search text_search; /* text search type */ + enum t_gui_buffer_search_dir text_search_direction; + /* search dir.: backward/forward */ + int text_search_exact; /* case sensitive search? */ + int text_search_regex; /* search with a regex */ + regex_t *text_search_regex_compiled; /* regex used to search */ + int text_search_where; /* prefix and/or msg */ + enum t_gui_buffer_search_history text_search_history; /* local/global */ + int text_search_found; /* 1 if text found, otherwise 0 */ + struct t_gui_history *text_search_ptr_history; /* ptr to history found */ + char *text_search_input; /* input saved before text search */ /* highlight settings for buffer */ char *highlight_words; /* list of words to highlight */ diff --git a/src/gui/gui-history.c b/src/gui/gui-history.c index ba4c1022f..399973849 100644 --- a/src/gui/gui-history.c +++ b/src/gui/gui-history.c @@ -39,6 +39,7 @@ #include "../plugins/plugin.h" #include "gui-history.h" #include "gui-buffer.h" +#include "gui-input.h" struct t_gui_history *gui_history = NULL; @@ -47,6 +48,34 @@ struct t_gui_history *gui_history_ptr = NULL; int num_gui_history = 0; +/* + * Removes oldest history entry in a buffer. + */ + +void +gui_history_buffer_remove_oldest (struct t_gui_buffer *buffer) +{ + struct t_gui_history *ptr_history; + + if (buffer->text_search_ptr_history == buffer->last_history) + { + buffer->text_search_ptr_history = NULL; + buffer->text_search_found = 0; + gui_input_search_signal (buffer); + } + + ptr_history = buffer->last_history->prev_history; + if (buffer->ptr_history == buffer->last_history) + buffer->ptr_history = ptr_history; + ((buffer->last_history)->prev_history)->next_history = NULL; + if (buffer->last_history->text) + free (buffer->last_history->text); + free (buffer->last_history); + buffer->last_history = ptr_history; + + buffer->num_history--; +} + /* * Adds a text/command to buffer's history. */ @@ -54,46 +83,71 @@ int num_gui_history = 0; void gui_history_buffer_add (struct t_gui_buffer *buffer, const char *string) { - struct t_gui_history *new_history, *ptr_history; + struct t_gui_history *new_history; if (!string) return; - if (!buffer->history - || (buffer->history - && (strcmp (buffer->history->text, string) != 0))) - { - new_history = malloc (sizeof (*new_history)); - if (new_history) - { - new_history->text = strdup (string); - if (buffer->history) - buffer->history->prev_history = new_history; - else - buffer->last_history = new_history; - new_history->next_history = buffer->history; - new_history->prev_history = NULL; - buffer->history = new_history; - buffer->num_history++; + if (buffer->history && buffer->history->text + && (strcmp (buffer->history->text, string) == 0)) + return; - /* remove one command if necessary */ - if ((CONFIG_INTEGER(config_history_max_commands) > 0) - && (buffer->num_history > CONFIG_INTEGER(config_history_max_commands))) - { - ptr_history = buffer->last_history->prev_history; - if (buffer->ptr_history == buffer->last_history) - buffer->ptr_history = ptr_history; - ((buffer->last_history)->prev_history)->next_history = NULL; - if (buffer->last_history->text) - free (buffer->last_history->text); - free (buffer->last_history); - buffer->last_history = ptr_history; - buffer->num_history--; - } + new_history = malloc (sizeof (*new_history)); + if (new_history) + { + new_history->text = strdup (string); + if (buffer->history) + buffer->history->prev_history = new_history; + else + buffer->last_history = new_history; + new_history->next_history = buffer->history; + new_history->prev_history = NULL; + buffer->history = new_history; + buffer->num_history++; + + /* remove one command if necessary */ + if ((CONFIG_INTEGER(config_history_max_commands) > 0) + && (buffer->num_history > CONFIG_INTEGER(config_history_max_commands))) + { + gui_history_buffer_remove_oldest (buffer); } } } +/* + * Removes oldest global history entry. + */ + +void +gui_history_global_remove_oldest () +{ + struct t_gui_buffer *ptr_buffer; + struct t_gui_history *ptr_history; + + /* ensure no buffer is using the last global history entry */ + for (ptr_buffer = gui_buffers; ptr_buffer; + ptr_buffer = ptr_buffer->next_buffer) + { + if (ptr_buffer->text_search_ptr_history == last_gui_history) + { + ptr_buffer->text_search_ptr_history = NULL; + ptr_buffer->text_search_found = 0; + gui_input_search_signal (ptr_buffer); + } + } + + ptr_history = last_gui_history->prev_history; + if (gui_history_ptr == last_gui_history) + gui_history_ptr = ptr_history; + (last_gui_history->prev_history)->next_history = NULL; + if (last_gui_history->text) + free (last_gui_history->text); + free (last_gui_history); + last_gui_history = ptr_history; + + num_gui_history--; +} + /* * Adds a text/command to global history. */ @@ -101,42 +155,32 @@ gui_history_buffer_add (struct t_gui_buffer *buffer, const char *string) void gui_history_global_add (const char *string) { - struct t_gui_history *new_history, *ptr_history; + struct t_gui_history *new_history; if (!string) return; - if (!gui_history - || (gui_history - && (strcmp (gui_history->text, string) != 0))) - { - new_history = malloc (sizeof (*new_history)); - if (new_history) - { - new_history->text = strdup (string); - if (gui_history) - gui_history->prev_history = new_history; - else - last_gui_history = new_history; - new_history->next_history = gui_history; - new_history->prev_history = NULL; - gui_history = new_history; - num_gui_history++; + if (gui_history && (strcmp (gui_history->text, string) == 0)) + return; - /* remove one command if necessary */ - if ((CONFIG_INTEGER(config_history_max_commands) > 0) - && (num_gui_history > CONFIG_INTEGER(config_history_max_commands))) - { - ptr_history = last_gui_history->prev_history; - if (gui_history_ptr == last_gui_history) - gui_history_ptr = ptr_history; - (last_gui_history->prev_history)->next_history = NULL; - if (last_gui_history->text) - free (last_gui_history->text); - free (last_gui_history); - last_gui_history = ptr_history; - num_gui_history--; - } + new_history = malloc (sizeof (*new_history)); + if (new_history) + { + new_history->text = strdup (string); + if (gui_history) + gui_history->prev_history = new_history; + else + last_gui_history = new_history; + new_history->next_history = gui_history; + new_history->prev_history = NULL; + gui_history = new_history; + num_gui_history++; + + /* remove one command if necessary */ + if ((CONFIG_INTEGER(config_history_max_commands) > 0) + && (num_gui_history > CONFIG_INTEGER(config_history_max_commands))) + { + gui_history_global_remove_oldest (); } } } @@ -168,6 +212,93 @@ gui_history_add (struct t_gui_buffer *buffer, const char *string) free (string2); } +/* + * Searches for text in a history entry. + * + * Returns: + * 1: text found in line + * 0: text not found in line + */ + +int +gui_history_search_text (struct t_gui_buffer *buffer, + struct t_gui_history *history) +{ + int rc; + + if (!history || !history->text + || !buffer->input_buffer || !buffer->input_buffer[0]) + { + return 0; + } + + rc = 0; + + if (buffer->text_search_regex) + { + if (buffer->text_search_regex_compiled + && (regexec (buffer->text_search_regex_compiled, + history->text, 0, NULL, 0) == 0)) + { + rc = 1; + } + } + else if ((buffer->text_search_exact + && (strstr (history->text, buffer->input_buffer))) + || (!buffer->text_search_exact + && (string_strcasestr (history->text, buffer->input_buffer)))) + { + rc = 1; + } + + return rc; +} + +/* + * Searches in history using string in buffer input. + * + * Returns: + * 1: an history was found + * 0: text not found + */ + +int +gui_history_search (struct t_gui_buffer *buffer, + struct t_gui_history *history) +{ + struct t_gui_history *ptr_history; + int direction; + + if (!buffer->input_buffer || !buffer->input_buffer[0]) + return 0; + + direction = (buffer->text_search_direction == GUI_BUFFER_SEARCH_DIR_BACKWARD) ? + 1 : -1; + + if (buffer->text_search_ptr_history) + { + ptr_history = (direction > 0) ? + buffer->text_search_ptr_history->next_history : + buffer->text_search_ptr_history->prev_history; + } + else + { + ptr_history = history; + } + + while (ptr_history) + { + if (gui_history_search_text (buffer, ptr_history)) + { + buffer->text_search_ptr_history = ptr_history; + return 1; + } + ptr_history = (direction > 0) ? + ptr_history->next_history : ptr_history->prev_history; + } + return 0; +} + /* * Frees global history. */ diff --git a/src/gui/gui-history.h b/src/gui/gui-history.h index edbb1acd8..f0915268b 100644 --- a/src/gui/gui-history.h +++ b/src/gui/gui-history.h @@ -37,6 +37,8 @@ extern void gui_history_buffer_add (struct t_gui_buffer *buffer, const char *string); extern void gui_history_global_add (const char *string); extern void gui_history_add (struct t_gui_buffer *buffer, const char *string); +extern int gui_history_search (struct t_gui_buffer *buffer, + struct t_gui_history *history); extern void gui_history_global_free (); extern void gui_history_buffer_free (struct t_gui_buffer *buffer); extern struct t_hdata *gui_history_hdata_history_cb (const void *pointer, diff --git a/src/gui/gui-input.c b/src/gui/gui-input.c index e4658b872..0eb3d5986 100644 --- a/src/gui/gui-input.c +++ b/src/gui/gui-input.c @@ -214,7 +214,6 @@ gui_input_search_signal (struct t_gui_buffer *buffer) { gui_window_bare_display_toggle (NULL); } - (void) hook_signal_send ("input_search", WEECHAT_HOOK_SIGNAL_POINTER, buffer); } @@ -498,7 +497,7 @@ gui_input_complete (struct t_gui_buffer *buffer) void gui_input_complete_next (struct t_gui_buffer *buffer) { - if (!buffer->input ||(buffer->text_search != GUI_TEXT_SEARCH_DISABLED)) + if (!buffer->input || (buffer->text_search != GUI_BUFFER_SEARCH_DISABLED)) return; gui_buffer_undo_snap (buffer); @@ -522,7 +521,7 @@ gui_input_complete_next (struct t_gui_buffer *buffer) void gui_input_complete_previous (struct t_gui_buffer *buffer) { - if (!buffer->input || (buffer->text_search != GUI_TEXT_SEARCH_DISABLED)) + if (!buffer->input || (buffer->text_search != GUI_BUFFER_SEARCH_DISABLED)) return; gui_buffer_undo_snap (buffer); @@ -549,9 +548,10 @@ gui_input_search_text_here (struct t_gui_buffer *buffer) struct t_gui_window *window; window = gui_window_search_with_buffer (buffer); - if (window && (window->buffer->text_search == GUI_TEXT_SEARCH_DISABLED)) + if (window && (window->buffer->text_search == GUI_BUFFER_SEARCH_DISABLED)) { - gui_window_search_start (window, window->scroll->start_line); + gui_window_search_start (window, GUI_BUFFER_SEARCH_LINES, + window->scroll->start_line); gui_input_search_signal (buffer); } } @@ -566,9 +566,26 @@ gui_input_search_text (struct t_gui_buffer *buffer) struct t_gui_window *window; window = gui_window_search_with_buffer (buffer); - if (window && (window->buffer->text_search == GUI_TEXT_SEARCH_DISABLED)) + if (window && (window->buffer->text_search == GUI_BUFFER_SEARCH_DISABLED)) { - gui_window_search_start (window, NULL); + gui_window_search_start (window, GUI_BUFFER_SEARCH_LINES, NULL); + gui_input_search_signal (buffer); + } +} + +/* + * Searches for text in buffer/global command line history. + */ + +void +gui_input_search_history (struct t_gui_buffer *buffer) +{ + struct t_gui_window *window; + + window = gui_window_search_with_buffer (buffer); + if (window && (window->buffer->text_search == GUI_BUFFER_SEARCH_DISABLED)) + { + gui_window_search_start (window, GUI_BUFFER_SEARCH_HISTORY, NULL); gui_input_search_signal (buffer); } } @@ -619,7 +636,7 @@ gui_input_search_switch_case (struct t_gui_buffer *buffer) struct t_gui_window *window; window = gui_window_search_with_buffer (buffer); - if (window && (window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED)) + if (window && (window->buffer->text_search != GUI_BUFFER_SEARCH_DISABLED)) { window->buffer->text_search_exact ^= 1; gui_window_search_restart (window); @@ -638,7 +655,7 @@ gui_input_search_switch_regex (struct t_gui_buffer *buffer) struct t_gui_window *window; window = gui_window_search_with_buffer (buffer); - if (window && (window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED)) + if (window && (window->buffer->text_search != GUI_BUFFER_SEARCH_DISABLED)) { window->buffer->text_search_regex ^= 1; gui_window_search_restart (window); @@ -656,20 +673,35 @@ gui_input_search_switch_where (struct t_gui_buffer *buffer) struct t_gui_window *window; window = gui_window_search_with_buffer (buffer); - if (window && (window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED)) - { - /* it's not possible to change that in a buffer not "formatted" */ - if (window->buffer->type != GUI_BUFFER_TYPE_FORMATTED) - return; + if (!window) + return; - if (window->buffer->text_search_where == GUI_TEXT_SEARCH_IN_MESSAGE) - window->buffer->text_search_where = GUI_TEXT_SEARCH_IN_PREFIX; - else if (window->buffer->text_search_where == GUI_TEXT_SEARCH_IN_PREFIX) - window->buffer->text_search_where = GUI_TEXT_SEARCH_IN_MESSAGE | GUI_TEXT_SEARCH_IN_PREFIX; - else - window->buffer->text_search_where = GUI_TEXT_SEARCH_IN_MESSAGE; - gui_window_search_restart (window); - gui_input_search_signal (buffer); + switch (window->buffer->text_search) + { + case GUI_BUFFER_SEARCH_DISABLED: + break; + case GUI_BUFFER_SEARCH_LINES: + /* it's not possible to change that in a buffer not "formatted" */ + if (window->buffer->type != GUI_BUFFER_TYPE_FORMATTED) + return; + if (window->buffer->text_search_where == GUI_BUFFER_SEARCH_IN_MESSAGE) + window->buffer->text_search_where = GUI_BUFFER_SEARCH_IN_PREFIX; + else if (window->buffer->text_search_where == GUI_BUFFER_SEARCH_IN_PREFIX) + window->buffer->text_search_where = GUI_BUFFER_SEARCH_IN_MESSAGE | GUI_BUFFER_SEARCH_IN_PREFIX; + else + window->buffer->text_search_where = GUI_BUFFER_SEARCH_IN_MESSAGE; + gui_window_search_restart (window); + gui_input_search_signal (buffer); + break; + case GUI_BUFFER_SEARCH_HISTORY: + window->buffer->text_search_history = + (window->buffer->text_search_history == GUI_BUFFER_SEARCH_HISTORY_LOCAL) ? + GUI_BUFFER_SEARCH_HISTORY_GLOBAL : GUI_BUFFER_SEARCH_HISTORY_LOCAL; + gui_window_search_restart (window); + gui_input_search_signal (buffer); + break; + case GUI_BUFFER_NUM_SEARCH: + break; } } @@ -683,10 +715,24 @@ gui_input_search_previous (struct t_gui_buffer *buffer) struct t_gui_window *window; window = gui_window_search_with_buffer (buffer); - if (window && (window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED)) + if (!window) + return; + + switch (window->buffer->text_search) { - window->buffer->text_search = GUI_TEXT_SEARCH_BACKWARD; - (void) gui_window_search_text (window); + case GUI_BUFFER_SEARCH_DISABLED: + break; + case GUI_BUFFER_SEARCH_LINES: + window->buffer->text_search_direction = GUI_BUFFER_SEARCH_DIR_BACKWARD; + (void) gui_window_search_text (window); + break; + case GUI_BUFFER_SEARCH_HISTORY: + window->buffer->text_search_direction = GUI_BUFFER_SEARCH_DIR_BACKWARD; + if (gui_window_search_text (window)) + gui_input_search_signal (buffer); + break; + case GUI_BUFFER_NUM_SEARCH: + break; } } @@ -700,10 +746,24 @@ gui_input_search_next (struct t_gui_buffer *buffer) struct t_gui_window *window; window = gui_window_search_with_buffer (buffer); - if (window && (window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED)) + if (!window) + return; + + switch (window->buffer->text_search) { - window->buffer->text_search = GUI_TEXT_SEARCH_FORWARD; - (void) gui_window_search_text (window); + case GUI_BUFFER_SEARCH_DISABLED: + break; + case GUI_BUFFER_SEARCH_LINES: + window->buffer->text_search_direction = GUI_BUFFER_SEARCH_DIR_FORWARD; + (void) gui_window_search_text (window); + break; + case GUI_BUFFER_SEARCH_HISTORY: + window->buffer->text_search_direction = GUI_BUFFER_SEARCH_DIR_FORWARD; + if (gui_window_search_text (window)) + gui_input_search_signal (buffer); + break; + case GUI_BUFFER_NUM_SEARCH: + break; } } @@ -717,10 +777,20 @@ gui_input_search_stop_here (struct t_gui_buffer *buffer) struct t_gui_window *window; window = gui_window_search_with_buffer (buffer); - if (window && (window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED)) + if (!window) + return; + + switch (window->buffer->text_search) { - gui_window_search_stop_here (window); - gui_input_search_signal (buffer); + case GUI_BUFFER_SEARCH_DISABLED: + break; + case GUI_BUFFER_SEARCH_LINES: + case GUI_BUFFER_SEARCH_HISTORY: + gui_window_search_stop (window, 1); + gui_input_search_signal (buffer); + break; + case GUI_BUFFER_NUM_SEARCH: + break; } } @@ -734,10 +804,20 @@ gui_input_search_stop (struct t_gui_buffer *buffer) struct t_gui_window *window; window = gui_window_search_with_buffer (buffer); - if (window && (window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED)) + if (!window) + return; + + switch (window->buffer->text_search) { - gui_window_search_stop (window); - gui_input_search_signal (buffer); + case GUI_BUFFER_SEARCH_DISABLED: + break; + case GUI_BUFFER_SEARCH_LINES: + case GUI_BUFFER_SEARCH_HISTORY: + gui_window_search_stop (window, 0); + gui_input_search_signal (buffer); + break; + case GUI_BUFFER_NUM_SEARCH: + break; } } diff --git a/src/gui/gui-input.h b/src/gui/gui-input.h index b176ea424..9fa754122 100644 --- a/src/gui/gui-input.h +++ b/src/gui/gui-input.h @@ -34,6 +34,7 @@ extern void gui_input_paste_pending_signal (); extern void gui_input_text_changed_modifier_and_signal (struct t_gui_buffer *buffer, int save_undo, int stop_completion); +extern void gui_input_search_signal (struct t_gui_buffer *buffer); extern void gui_input_set_pos (struct t_gui_buffer *buffer, int pos); extern void gui_input_insert_string (struct t_gui_buffer *buffer, const char *string); @@ -44,6 +45,7 @@ extern void gui_input_complete_next (struct t_gui_buffer *buffer); extern void gui_input_complete_previous (struct t_gui_buffer *buffer); extern void gui_input_search_text_here (struct t_gui_buffer *buffer); extern void gui_input_search_text (struct t_gui_buffer *buffer); +extern void gui_input_search_history (struct t_gui_buffer *buffer); extern void gui_input_search_compile_regex (struct t_gui_buffer *buffer); extern void gui_input_search_switch_case (struct t_gui_buffer *buffer); extern void gui_input_search_switch_regex (struct t_gui_buffer *buffer); diff --git a/src/gui/gui-key.c b/src/gui/gui-key.c index 90da58642..cfcbff3ba 100644 --- a/src/gui/gui-key.c +++ b/src/gui/gui-key.c @@ -66,7 +66,7 @@ int gui_keys_count[GUI_KEY_NUM_CONTEXTS]; /* keys number */ int gui_default_keys_count[GUI_KEY_NUM_CONTEXTS]; /* default keys number */ char *gui_key_context_string[GUI_KEY_NUM_CONTEXTS] = -{ "default", "search", "cursor", "mouse" }; +{ "default", "search", "histsearch", "cursor", "mouse" }; char *gui_key_focus_string[GUI_KEY_NUM_FOCUS] = { "*", "chat", "bar", "item" }; @@ -173,9 +173,13 @@ gui_key_get_current_context () if (gui_cursor_mode) return GUI_KEY_CONTEXT_CURSOR; - if (gui_current_window - && (gui_current_window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED)) - return GUI_KEY_CONTEXT_SEARCH; + if (gui_current_window) + { + if (gui_current_window->buffer->text_search == GUI_BUFFER_SEARCH_LINES) + return GUI_KEY_CONTEXT_SEARCH; + if (gui_current_window->buffer->text_search == GUI_BUFFER_SEARCH_HISTORY) + return GUI_KEY_CONTEXT_HISTSEARCH; + } return GUI_KEY_CONTEXT_DEFAULT; } @@ -2437,7 +2441,7 @@ gui_key_pressed (const char *key_str) /* look for key combo in key table for current buffer */ ptr_key = gui_key_search_part ( gui_current_window->buffer, - GUI_KEY_CONTEXT_DEFAULT, + context, (const char **)chunks1, chunks1_count, (const char **)chunks2, chunks2_count, &exact_match); @@ -2446,21 +2450,23 @@ gui_key_pressed (const char *key_str) { ptr_key = gui_key_search_part ( NULL, - GUI_KEY_CONTEXT_DEFAULT, + context, (const char **)chunks1, chunks1_count, (const char **)chunks2, chunks2_count, &exact_match); } break; case GUI_KEY_CONTEXT_SEARCH: + case GUI_KEY_CONTEXT_HISTSEARCH: ptr_key = gui_key_search_part ( NULL, - GUI_KEY_CONTEXT_SEARCH, + context, (const char **)chunks1, chunks1_count, (const char **)chunks2, chunks2_count, &exact_match); if (!ptr_key) { + /* fallback to default context */ ptr_key = gui_key_search_part ( NULL, GUI_KEY_CONTEXT_DEFAULT, @@ -2472,7 +2478,7 @@ gui_key_pressed (const char *key_str) case GUI_KEY_CONTEXT_CURSOR: ptr_key = gui_key_search_part ( NULL, - GUI_KEY_CONTEXT_CURSOR, + context, (const char **)chunks1, chunks1_count, (const char **)chunks2, chunks2_count, &exact_match); diff --git a/src/gui/gui-key.h b/src/gui/gui-key.h index cbc600c2f..5d0170f44 100644 --- a/src/gui/gui-key.h +++ b/src/gui/gui-key.h @@ -34,6 +34,7 @@ enum t_gui_key_context { GUI_KEY_CONTEXT_DEFAULT = 0, GUI_KEY_CONTEXT_SEARCH, + GUI_KEY_CONTEXT_HISTSEARCH, GUI_KEY_CONTEXT_CURSOR, GUI_KEY_CONTEXT_MOUSE, /* number of key contexts */ diff --git a/src/gui/gui-line.c b/src/gui/gui-line.c index efef30959..adfee35b5 100644 --- a/src/gui/gui-line.c +++ b/src/gui/gui-line.c @@ -593,7 +593,7 @@ gui_line_search_text (struct t_gui_buffer *buffer, struct t_gui_line *line) rc = 0; - if ((buffer->text_search_where & GUI_TEXT_SEARCH_IN_PREFIX) + if ((buffer->text_search_where & GUI_BUFFER_SEARCH_IN_PREFIX) && line->data->prefix) { prefix = gui_color_decode (line->data->prefix, NULL); @@ -621,7 +621,7 @@ gui_line_search_text (struct t_gui_buffer *buffer, struct t_gui_line *line) } } - if (!rc && (buffer->text_search_where & GUI_TEXT_SEARCH_IN_MESSAGE)) + if (!rc && (buffer->text_search_where & GUI_BUFFER_SEARCH_IN_MESSAGE)) { if (gui_chat_display_tags) { diff --git a/src/gui/gui-window.c b/src/gui/gui-window.c index 76a585f1d..ae9a48713 100644 --- a/src/gui/gui-window.c +++ b/src/gui/gui-window.c @@ -50,6 +50,7 @@ #include "gui-color.h" #include "gui-filter.h" #include "gui-input.h" +#include "gui-history.h" #include "gui-hotlist.h" #include "gui-layout.h" #include "gui-line.h" @@ -1501,8 +1502,7 @@ gui_window_scroll_previous_highlight (struct t_gui_window *window) if (!window) return; - if ((window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) - && (window->buffer->text_search == GUI_TEXT_SEARCH_DISABLED)) + if (window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) { if (window->buffer->lines->first_line) { @@ -1539,8 +1539,7 @@ gui_window_scroll_next_highlight (struct t_gui_window *window) if (!window) return; - if ((window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) - && (window->buffer->text_search == GUI_TEXT_SEARCH_DISABLED)) + if (window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) { if (window->buffer->lines->first_line) { @@ -1575,38 +1574,35 @@ gui_window_scroll_unread (struct t_gui_window *window) if (!window) return; - if (window->buffer->text_search == GUI_TEXT_SEARCH_DISABLED) + if (CONFIG_STRING(config_look_read_marker) && + CONFIG_STRING(config_look_read_marker)[0] && + (window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) && + (window->buffer->lines->first_line_not_read || + (window->buffer->lines->last_read_line && + window->buffer->lines->last_read_line != window->buffer->lines->last_line))) { - if (CONFIG_STRING(config_look_read_marker) && - CONFIG_STRING(config_look_read_marker)[0] && - (window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) && - (window->buffer->lines->first_line_not_read || - (window->buffer->lines->last_read_line && - window->buffer->lines->last_read_line != window->buffer->lines->last_line))) + if (window->buffer->lines->first_line_not_read) + window->scroll->start_line = window->buffer->lines->first_line; + else + window->scroll->start_line = window->buffer->lines->last_read_line->next_line; + if (window->scroll->start_line) { - if (window->buffer->lines->first_line_not_read) - window->scroll->start_line = window->buffer->lines->first_line; - else - window->scroll->start_line = window->buffer->lines->last_read_line->next_line; - if (window->scroll->start_line) - { - if (!gui_line_is_displayed (window->scroll->start_line)) - window->scroll->start_line = gui_line_get_next_displayed (window->scroll->start_line); - } - window->scroll->start_line_pos = 0; - window->scroll->first_line_displayed = - (window->scroll->start_line == gui_line_get_first_displayed (window->buffer)); - gui_buffer_ask_chat_refresh (window->buffer, 2); + if (!gui_line_is_displayed (window->scroll->start_line)) + window->scroll->start_line = gui_line_get_next_displayed (window->scroll->start_line); } + window->scroll->start_line_pos = 0; + window->scroll->first_line_displayed = + (window->scroll->start_line == gui_line_get_first_displayed (window->buffer)); + gui_buffer_ask_chat_refresh (window->buffer, 2); } } /* - * Searches for text in a buffer. + * Searches for text in buffer lines or commands history. * * Returns: - * 1: line has been found with text - * 0: no line found with text + * 1: successful search + * 0: no results found */ int @@ -1617,51 +1613,66 @@ gui_window_search_text (struct t_gui_window *window) if (!window) return 0; - if (window->buffer->text_search == GUI_TEXT_SEARCH_BACKWARD) + switch (window->buffer->text_search) { - if (window->buffer->lines->first_line - && window->buffer->input_buffer && window->buffer->input_buffer[0]) - { - ptr_line = (window->scroll->start_line) ? - gui_line_get_prev_displayed (window->scroll->start_line) : - gui_line_get_last_displayed (window->buffer); - while (ptr_line) + case GUI_BUFFER_SEARCH_DISABLED: + break; + case GUI_BUFFER_SEARCH_LINES: + if (window->buffer->text_search_direction == GUI_BUFFER_SEARCH_DIR_BACKWARD) { - if (gui_line_search_text (window->buffer, ptr_line)) + if (window->buffer->lines->first_line + && window->buffer->input_buffer && window->buffer->input_buffer[0]) { - window->scroll->start_line = ptr_line; - window->scroll->start_line_pos = 0; - window->scroll->first_line_displayed = - (window->scroll->start_line == gui_line_get_first_displayed (window->buffer)); - gui_buffer_ask_chat_refresh (window->buffer, 2); - return 1; + ptr_line = (window->scroll->start_line) ? + gui_line_get_prev_displayed (window->scroll->start_line) : + gui_line_get_last_displayed (window->buffer); + while (ptr_line) + { + if (gui_line_search_text (window->buffer, ptr_line)) + { + window->scroll->start_line = ptr_line; + window->scroll->start_line_pos = 0; + window->scroll->first_line_displayed = + (window->scroll->start_line == gui_line_get_first_displayed (window->buffer)); + gui_buffer_ask_chat_refresh (window->buffer, 2); + return 1; + } + ptr_line = gui_line_get_prev_displayed (ptr_line); + } } - ptr_line = gui_line_get_prev_displayed (ptr_line); } - } - } - else if (window->buffer->text_search == GUI_TEXT_SEARCH_FORWARD) - { - if (window->buffer->lines->first_line - && window->buffer->input_buffer && window->buffer->input_buffer[0]) - { - ptr_line = (window->scroll->start_line) ? - gui_line_get_next_displayed (window->scroll->start_line) : - gui_line_get_first_displayed (window->buffer); - while (ptr_line) + else if (window->buffer->text_search_direction == GUI_BUFFER_SEARCH_DIR_FORWARD) { - if (gui_line_search_text (window->buffer, ptr_line)) + if (window->buffer->lines->first_line + && window->buffer->input_buffer && window->buffer->input_buffer[0]) { - window->scroll->start_line = ptr_line; - window->scroll->start_line_pos = 0; - window->scroll->first_line_displayed = - (window->scroll->start_line == window->buffer->lines->first_line); - gui_buffer_ask_chat_refresh (window->buffer, 2); - return 1; + ptr_line = (window->scroll->start_line) ? + gui_line_get_next_displayed (window->scroll->start_line) : + gui_line_get_first_displayed (window->buffer); + while (ptr_line) + { + if (gui_line_search_text (window->buffer, ptr_line)) + { + window->scroll->start_line = ptr_line; + window->scroll->start_line_pos = 0; + window->scroll->first_line_displayed = + (window->scroll->start_line == window->buffer->lines->first_line); + gui_buffer_ask_chat_refresh (window->buffer, 2); + return 1; + } + ptr_line = gui_line_get_next_displayed (ptr_line); + } } - ptr_line = gui_line_get_next_displayed (ptr_line); } - } + break; + case GUI_BUFFER_SEARCH_HISTORY: + return gui_history_search ( + window->buffer, + (window->buffer->text_search_history == GUI_BUFFER_SEARCH_HISTORY_LOCAL) ? + window->buffer->history : gui_history); + break; + case GUI_BUFFER_NUM_SEARCH: + break; } return 0; } @@ -1672,45 +1683,75 @@ gui_window_search_text (struct t_gui_window *window) */ void -gui_window_search_start (struct t_gui_window *window, +gui_window_search_start (struct t_gui_window *window, int search, struct t_gui_line *text_search_start_line) { if (!window) return; - window->scroll->text_search_start_line = text_search_start_line; - window->buffer->text_search = - (window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) ? - GUI_TEXT_SEARCH_BACKWARD : GUI_TEXT_SEARCH_FORWARD; + window->buffer->text_search = search; - if ((window->buffer->text_search_where == 0) - || CONFIG_BOOLEAN(config_look_buffer_search_force_default)) + switch (window->buffer->text_search) { - /* set default search values */ - window->buffer->text_search_exact = CONFIG_BOOLEAN(config_look_buffer_search_case_sensitive); - window->buffer->text_search_regex = CONFIG_BOOLEAN(config_look_buffer_search_regex); - if (window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) - { - switch (CONFIG_ENUM(config_look_buffer_search_where)) + case GUI_BUFFER_SEARCH_DISABLED: + break; + case GUI_BUFFER_SEARCH_LINES: + window->buffer->text_search_direction = (window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) ? + GUI_BUFFER_SEARCH_DIR_BACKWARD : GUI_BUFFER_SEARCH_DIR_FORWARD; + window->scroll->text_search_start_line = text_search_start_line; + if ((window->buffer->text_search_where == 0) + || CONFIG_BOOLEAN(config_look_buffer_search_force_default)) { - case CONFIG_LOOK_BUFFER_SEARCH_PREFIX: - window->buffer->text_search_where = GUI_TEXT_SEARCH_IN_PREFIX; - break; - case CONFIG_LOOK_BUFFER_SEARCH_MESSAGE: - window->buffer->text_search_where = GUI_TEXT_SEARCH_IN_MESSAGE; - break; - case CONFIG_LOOK_BUFFER_SEARCH_PREFIX_MESSAGE: - window->buffer->text_search_where = GUI_TEXT_SEARCH_IN_PREFIX | GUI_TEXT_SEARCH_IN_MESSAGE; - break; - default: - window->buffer->text_search_where = GUI_TEXT_SEARCH_IN_MESSAGE; - break; - } + if (window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) + { + switch (CONFIG_ENUM(config_look_buffer_search_where)) + { + case CONFIG_LOOK_BUFFER_SEARCH_PREFIX: + window->buffer->text_search_where = GUI_BUFFER_SEARCH_IN_PREFIX; + break; + case CONFIG_LOOK_BUFFER_SEARCH_MESSAGE: + window->buffer->text_search_where = GUI_BUFFER_SEARCH_IN_MESSAGE; + break; + case CONFIG_LOOK_BUFFER_SEARCH_PREFIX_MESSAGE: + window->buffer->text_search_where = GUI_BUFFER_SEARCH_IN_PREFIX + | GUI_BUFFER_SEARCH_IN_MESSAGE; + break; + default: + window->buffer->text_search_where = GUI_BUFFER_SEARCH_IN_MESSAGE; + break; + } + } + else + { + window->buffer->text_search_where = GUI_BUFFER_SEARCH_IN_MESSAGE; + } + break; + case GUI_BUFFER_SEARCH_HISTORY: + window->buffer->text_search_direction = GUI_BUFFER_SEARCH_DIR_BACKWARD; + if ((window->buffer->text_search_history == GUI_BUFFER_SEARCH_HISTORY_NONE) + || CONFIG_BOOLEAN(config_look_buffer_search_force_default)) + { + switch (CONFIG_ENUM(config_look_buffer_search_history)) + { + case CONFIG_LOOK_BUFFER_SEARCH_HISTORY_LOCAL: + window->buffer->text_search_history = GUI_BUFFER_SEARCH_HISTORY_LOCAL; + break; + case CONFIG_LOOK_BUFFER_SEARCH_HISTORY_GLOBAL: + window->buffer->text_search_history = GUI_BUFFER_SEARCH_HISTORY_GLOBAL; + break; + default: + window->buffer->text_search_history = GUI_BUFFER_SEARCH_HISTORY_LOCAL; + break; + } + } + break; + case GUI_BUFFER_NUM_SEARCH: + break; } - else - window->buffer->text_search_where = GUI_TEXT_SEARCH_IN_MESSAGE; } + window->buffer->text_search_exact = CONFIG_BOOLEAN(config_look_buffer_search_case_sensitive); + window->buffer->text_search_regex = CONFIG_BOOLEAN(config_look_buffer_search_regex); window->buffer->text_search_found = 0; gui_input_search_compile_regex (window->buffer); if (window->buffer->text_search_input) @@ -1734,39 +1775,80 @@ gui_window_search_restart (struct t_gui_window *window) if (!window) return; - window->scroll->start_line = window->scroll->text_search_start_line; - window->scroll->start_line_pos = 0; - window->buffer->text_search = - (window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) ? - GUI_TEXT_SEARCH_BACKWARD : GUI_TEXT_SEARCH_FORWARD; - window->buffer->text_search_found = 0; - gui_input_search_compile_regex (window->buffer); - if (gui_window_search_text (window)) - window->buffer->text_search_found = 1; - else + switch (window->buffer->text_search) { - if (CONFIG_BOOLEAN(config_look_search_text_not_found_alert) - && window->buffer->input_buffer && window->buffer->input_buffer[0]) - { - fprintf (stderr, "\a"); - fflush (stderr); - } - gui_buffer_ask_chat_refresh (window->buffer, 2); + case GUI_BUFFER_SEARCH_DISABLED: + break; + case GUI_BUFFER_SEARCH_LINES: + window->scroll->start_line = window->scroll->text_search_start_line; + window->scroll->start_line_pos = 0; + window->buffer->text_search_direction = + (window->buffer->type == GUI_BUFFER_TYPE_FORMATTED) ? + GUI_BUFFER_SEARCH_DIR_BACKWARD : GUI_BUFFER_SEARCH_DIR_FORWARD; + gui_input_search_compile_regex (window->buffer); + window->buffer->text_search_found = 0; + if (gui_window_search_text (window)) + { + window->buffer->text_search_found = 1; + } + else + { + if (CONFIG_BOOLEAN(config_look_search_text_not_found_alert) + && window->buffer->input_buffer && window->buffer->input_buffer[0]) + { + fprintf (stderr, "\a"); + fflush (stderr); + } + gui_buffer_ask_chat_refresh (window->buffer, 2); + } + break; + case GUI_BUFFER_SEARCH_HISTORY: + gui_input_search_compile_regex (window->buffer); + window->buffer->text_search_found = 0; + window->buffer->text_search_ptr_history = NULL; + if (gui_window_search_text (window)) + { + window->buffer->text_search_found = 1; + } + else + { + if (CONFIG_BOOLEAN(config_look_search_text_not_found_alert) + && window->buffer->input_buffer && window->buffer->input_buffer[0]) + { + fprintf (stderr, "\a"); + fflush (stderr); + } + } + break; + case GUI_BUFFER_NUM_SEARCH: + break; } } /* - * Ends search mode in a buffer (helper function). + * Stops search in a buffer, at current position if stop_here == 1 or reset + * scroll to the initial value if stop_here == 0. */ void -gui_window_search_end (struct t_gui_window *window) +gui_window_search_stop (struct t_gui_window *window, int stop_here) { + const char *ptr_new_input; + int search; + if (!window) return; - window->buffer->text_search = GUI_TEXT_SEARCH_DISABLED; - window->buffer->text_search = 0; + search = window->buffer->text_search; + + ptr_new_input = (stop_here + && (window->buffer->text_search == GUI_BUFFER_SEARCH_HISTORY) + && window->buffer->text_search_ptr_history + && window->buffer->text_search_ptr_history->text) ? + window->buffer->text_search_ptr_history->text : window->buffer->text_search_input; + + window->buffer->text_search = GUI_BUFFER_SEARCH_DISABLED; + window->buffer->text_search_direction = GUI_BUFFER_SEARCH_DIR_BACKWARD; if (window->buffer->text_search_regex_compiled) { regfree (window->buffer->text_search_regex_compiled); @@ -1774,49 +1856,31 @@ gui_window_search_end (struct t_gui_window *window) window->buffer->text_search_regex_compiled = NULL; } gui_input_delete_line (window->buffer); - if (window->buffer->text_search_input) + if (ptr_new_input) { - gui_input_insert_string (window->buffer, - window->buffer->text_search_input); + gui_input_insert_string (window->buffer, ptr_new_input); gui_input_text_changed_modifier_and_signal (window->buffer, 0, /* save undo */ 1); /* stop completion */ + } + if (window->buffer->text_search_input) + { free (window->buffer->text_search_input); window->buffer->text_search_input = NULL; } -} + window->buffer->text_search_ptr_history = NULL; -/* - * Stops search in a buffer at current position. - */ - -void -gui_window_search_stop_here (struct t_gui_window *window) -{ - if (!window) - return; - - gui_window_search_end (window); - window->scroll->text_search_start_line = NULL; - gui_buffer_ask_chat_refresh (window->buffer, 2); -} - -/* - * Stops search in a buffer. - */ - -void -gui_window_search_stop (struct t_gui_window *window) -{ - if (!window) - return; - - gui_window_search_end (window); - window->scroll->start_line = window->scroll->text_search_start_line; - window->scroll->start_line_pos = 0; - window->scroll->text_search_start_line = NULL; - gui_hotlist_remove_buffer (window->buffer, 0); - gui_buffer_ask_chat_refresh (window->buffer, 2); + if (search == GUI_BUFFER_SEARCH_LINES) + { + window->scroll->text_search_start_line = NULL; + if (!stop_here) + { + window->scroll->start_line = window->scroll->text_search_start_line; + window->scroll->start_line_pos = 0; + gui_hotlist_remove_buffer (window->buffer, 0); + } + gui_buffer_ask_chat_refresh (window->buffer, 2); + } } /* diff --git a/src/gui/gui-window.h b/src/gui/gui-window.h index 6e1b2eb76..2d697f406 100644 --- a/src/gui/gui-window.h +++ b/src/gui/gui-window.h @@ -188,10 +188,10 @@ extern void gui_window_scroll_previous_highlight (struct t_gui_window *window); extern void gui_window_scroll_next_highlight (struct t_gui_window *window); extern void gui_window_scroll_unread (struct t_gui_window *window); extern void gui_window_search_start (struct t_gui_window *window, + int search, struct t_gui_line *text_search_start_line); extern void gui_window_search_restart (struct t_gui_window *window); -extern void gui_window_search_stop_here (struct t_gui_window *window); -extern void gui_window_search_stop (struct t_gui_window *window); +extern void gui_window_search_stop (struct t_gui_window *window, int stop_here); extern int gui_window_search_text (struct t_gui_window *window); extern void gui_window_zoom (struct t_gui_window *window); extern struct t_hdata *gui_window_hdata_window_cb (const void *pointer, diff --git a/tests/unit/gui/test-gui-buffer.cpp b/tests/unit/gui/test-gui-buffer.cpp index 37fe80869..287114991 100644 --- a/tests/unit/gui/test-gui-buffer.cpp +++ b/tests/unit/gui/test-gui-buffer.cpp @@ -583,12 +583,15 @@ TEST(GuiBuffer, NewProps) POINTERS_EQUAL(NULL, buffer->last_history); POINTERS_EQUAL(NULL, buffer->ptr_history); LONGS_EQUAL(0, buffer->num_history); - LONGS_EQUAL(GUI_TEXT_SEARCH_DISABLED, buffer->text_search); + LONGS_EQUAL(GUI_BUFFER_SEARCH_DISABLED, buffer->text_search); + LONGS_EQUAL(GUI_BUFFER_SEARCH_DIR_BACKWARD, buffer->text_search_direction); LONGS_EQUAL(0, buffer->text_search_exact); LONGS_EQUAL(0, buffer->text_search_regex); POINTERS_EQUAL(NULL, buffer->text_search_regex_compiled); LONGS_EQUAL(0, buffer->text_search_where); + LONGS_EQUAL(0, buffer->text_search_history); LONGS_EQUAL(0, buffer->text_search_found); + POINTERS_EQUAL(NULL, buffer->text_search_ptr_history); POINTERS_EQUAL(NULL, buffer->text_search_input); POINTERS_EQUAL(NULL, buffer->highlight_words); POINTERS_EQUAL(NULL, buffer->highlight_regex); @@ -885,9 +888,11 @@ TEST(GuiBuffer, GetInteger) LONGS_EQUAL(0, gui_buffer_get_integer (gui_buffers, "input_1st_display")); CHECK(gui_buffer_get_integer (gui_buffers, "num_history") >= 0); LONGS_EQUAL(0, gui_buffer_get_integer (gui_buffers, "text_search")); + LONGS_EQUAL(0, gui_buffer_get_integer (gui_buffers, "text_search_direction")); LONGS_EQUAL(0, gui_buffer_get_integer (gui_buffers, "text_search_exact")); LONGS_EQUAL(0, gui_buffer_get_integer (gui_buffers, "text_search_regex")); LONGS_EQUAL(0, gui_buffer_get_integer (gui_buffers, "text_search_where")); + LONGS_EQUAL(0, gui_buffer_get_integer (gui_buffers, "text_search_history")); LONGS_EQUAL(0, gui_buffer_get_integer (gui_buffers, "text_search_found")); } @@ -931,6 +936,7 @@ TEST(GuiBuffer, GetPointer) POINTERS_EQUAL(NULL, gui_buffer_get_pointer (gui_buffers, "plugin")); POINTERS_EQUAL(NULL, gui_buffer_get_pointer (gui_buffers, "text_search_regex_compiled")); + POINTERS_EQUAL(NULL, gui_buffer_get_pointer (gui_buffers, "text_search_ptr_history")); POINTERS_EQUAL(NULL, gui_buffer_get_pointer (gui_buffers, "highlight_disable_regex_compiled")); POINTERS_EQUAL(NULL, gui_buffer_get_pointer (gui_buffers, "highlight_regex_compiled")); } diff --git a/tests/unit/gui/test-gui-key.cpp b/tests/unit/gui/test-gui-key.cpp index 0ee2f76cf..90e685e9e 100644 --- a/tests/unit/gui/test-gui-key.cpp +++ b/tests/unit/gui/test-gui-key.cpp @@ -100,8 +100,9 @@ TEST(GuiKey, SearchContext) LONGS_EQUAL(0, gui_key_search_context ("default")); LONGS_EQUAL(1, gui_key_search_context ("search")); - LONGS_EQUAL(2, gui_key_search_context ("cursor")); - LONGS_EQUAL(3, gui_key_search_context ("mouse")); + LONGS_EQUAL(2, gui_key_search_context ("histsearch")); + LONGS_EQUAL(3, gui_key_search_context ("cursor")); + LONGS_EQUAL(4, gui_key_search_context ("mouse")); } /* @@ -125,7 +126,14 @@ TEST(GuiKey, GetCurrentContext) input_data (gui_buffers, "/input search_stop", NULL, 0); LONGS_EQUAL(GUI_KEY_CONTEXT_DEFAULT, gui_key_get_current_context ()); + input_data (gui_buffers, "/input search_history", NULL, 0); + LONGS_EQUAL(GUI_KEY_CONTEXT_HISTSEARCH, gui_key_get_current_context ()); + + input_data (gui_buffers, "/input search_stop", NULL, 0); + LONGS_EQUAL(GUI_KEY_CONTEXT_DEFAULT, gui_key_get_current_context ()); + gui_buffers->text_search_where = 0; + gui_buffers->text_search_history = GUI_BUFFER_SEARCH_HISTORY_NONE; } /*