]> git.eshelyaron.com Git - emacs.git/commitdiff
Make the erc /ignore command prompt for a timeout
authorLars Ingebrigtsen <larsi@gnus.org>
Wed, 5 Aug 2020 08:27:40 +0000 (10:27 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Wed, 5 Aug 2020 08:27:40 +0000 (10:27 +0200)
* lisp/erc/erc.el (erc--unignore-user): Separate into own function
(bug#40137).
(erc-cmd-IGNORE): Ask if the user wants a timeout.
(erc--read-time-period): New function.

etc/NEWS
lisp/erc/erc.el
test/lisp/erc/erc-tests.el [new file with mode: 0644]

index c1879169dd639e4331a28c4989d75a763e3adfab..670e97f52cbc4fc4cebf7350ffc1ee53c6b4411c 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -590,6 +590,12 @@ Previously 'xml-print' would produce invalid XML when given a string
 with characters that are not valid in XML (see
 https://www.w3.org/TR/xml/#charsets).  Now it rejects such strings.
 
+** erc
+
+---
+*** The /ignore command will now ask for a timeout to stop ignoring the user.
+Allowed inputs are seconds or ISO8601-like periods like "1h" or "4h30m".
+
 ** Battery
 
 ---
index 8830dd4c45e46833cabf25f19e6a028168c6db5d..927546abc303a72e756031c7c1a07e2661145cbb 100644 (file)
@@ -63,6 +63,8 @@
 (require 'thingatpt)
 (require 'auth-source)
 (require 'erc-compat)
+(require 'time-date)
+(require 'iso8601)
 (eval-when-compile (require 'subr-x))
 
 (defvar erc-official-location
@@ -2905,6 +2907,44 @@ therefore has to contain the command itself as well."
   (erc-server-send (substring line 1))
   t)
 
+(defvar erc--read-time-period-history nil)
+
+(defun erc--read-time-period (prompt)
+  "Read a time period on the \"2h\" format.
+If there's no letter spec, the input is interpreted as a number of seconds.
+
+If input is blank, this function returns nil.  Otherwise it
+returns the time spec converted to a number of seconds."
+  (let ((period (string-trim
+                 (read-string prompt nil 'erc--read-time-period-history))))
+    (cond
+     ;; Blank input.
+     ((zerop (length period))
+      nil)
+     ;; All-number -- interpret as seconds.
+     ((string-match-p "\\`[0-9]+\\'" period)
+      (string-to-number period))
+     ;; Parse as a time spec.
+     (t
+      (let ((time (condition-case nil
+                      (iso8601-parse-duration
+                       (concat (cond
+                                ((string-match-p "\\`P" (upcase period))
+                                 ;; Somebody typed in a full ISO8601 period.
+                                 (upcase period))
+                                ((string-match-p "[YD]" (upcase period))
+                                 ;; If we have a year/day element,
+                                 ;; we have a full spec.
+                                 "P")
+                                (t
+                                 ;; Otherwise it's just a sub-day spec.
+                                 "PT"))
+                               (upcase period)))
+                    (wrong-type-argument nil))))
+        (unless time
+          (user-error "%s is not a valid time period" period))
+        (decoded-time-period time))))))
+
 (defun erc-cmd-IGNORE (&optional user)
   "Ignore USER.  This should be a regexp matching nick!user@host.
 If no USER argument is specified, list the contents of `erc-ignore-list'."
@@ -2914,10 +2954,18 @@ If no USER argument is specified, list the contents of `erc-ignore-list'."
                    (y-or-n-p (format "Use regexp-quoted form (%s) instead? "
                                      quoted)))
           (setq user quoted))
-        (erc-display-line
-         (erc-make-notice (format "Now ignoring %s" user))
-         'active)
-        (erc-with-server-buffer (add-to-list 'erc-ignore-list user)))
+        (let ((timeout
+               (erc--read-time-period
+                "Add a timeout? (Blank for no, or a time spec like 2h): "))
+              (buffer (current-buffer)))
+          (when timeout
+            (run-at-time timeout nil
+                         (lambda ()
+                           (erc--unignore-user user buffer))))
+          (erc-display-line
+           (erc-make-notice (format "Now ignoring %s" user))
+           'active)
+          (erc-with-server-buffer (add-to-list 'erc-ignore-list user))))
     (if (null (erc-with-server-buffer erc-ignore-list))
         (erc-display-line (erc-make-notice "Ignore list is empty") 'active)
       (erc-display-line (erc-make-notice "Ignore list:") 'active)
@@ -2941,12 +2989,17 @@ If no USER argument is specified, list the contents of `erc-ignore-list'."
          (erc-make-notice (format "%s is not currently ignored!" user))
          'active)))
     (when ignored-nick
+      (erc--unignore-user user (current-buffer))))
+  t)
+
+(defun erc--unignore-user (user buffer)
+  (when (buffer-live-p buffer)
+    (with-current-buffer buffer
       (erc-display-line
        (erc-make-notice (format "No longer ignoring %s" user))
        'active)
       (erc-with-server-buffer
-        (setq erc-ignore-list (delete ignored-nick erc-ignore-list)))))
-  t)
+        (setq erc-ignore-list (delete user erc-ignore-list))))))
 
 (defun erc-cmd-CLEAR ()
   "Clear the window content."
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
new file mode 100644 (file)
index 0000000..27f48fa
--- /dev/null
@@ -0,0 +1,47 @@
+;;; erc-tests.el --- Tests for erc.  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;; Author: Lars Ingebrigtsen <larsi@gnus.org>
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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.
+
+;; GNU Emacs 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 GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'erc)
+
+(ert-deftest erc--read-time-period ()
+  (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "")))
+    (should (equal (erc--read-time-period "foo: ") nil)))
+
+  (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "   ")))
+    (should (equal (erc--read-time-period "foo: ") nil)))
+
+  (cl-letf (((symbol-function 'read-string) (lambda (&rest _) " 432 ")))
+    (should (equal (erc--read-time-period "foo: ") 432)))
+
+  (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "432")))
+    (should (equal (erc--read-time-period "foo: ") 432)))
+
+  (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "1h")))
+    (should (equal (erc--read-time-period "foo: ") 3600)))
+
+  (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "1h10s")))
+    (should (equal (erc--read-time-period "foo: ") 3610)))
+
+  (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "1d")))
+    (should (equal (erc--read-time-period "foo: ") 86400))))