diff --git a/etc/NEWS b/etc/NEWS index a143550f03..67a2f9833d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -335,6 +335,11 @@ Use something like 'M-x shell RET ssh RET' instead. * Changes in Emacs 29.1 +--- +** New functions 'ffap-ipv4-at-point', 'ffap-ipv4-p' +'ffap-ipv4-at-point' return an IPv4 address if it is found at point, +or nil. 'ffap-ipv4-p' check for a valid IPv4 address. + --- ** Emacs is now capable of editing files with arbitrarily long lines. The display of long lines has been optimized, and Emacs no longer diff --git a/lisp/ffap.el b/lisp/ffap.el index 9de0dd40d1..44e9ed9b1e 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -641,6 +641,24 @@ ffap-fixup-url ((and ffap-url-unwrap-remote (ffap-url-unwrap-remote url))) (url))) + +;;; IP Address (`ffap-ipv4-p'): + +;;;###autoload +(defun ffap-ipv4-at-point () + "Return an IPv4 address if it is found at point, or nil." + (let ((mach (ffap-string-at-point 'ipv4))) + (and (ffap-ipv4-p mach) mach))) + +(defun ffap-ipv4-p (ip) + "Decide whether IP is a valid IPv4 address." + (when-let* ((start (string-match "\\([0-9]\\{1,3\\}\\.\\)\\{3\\}[0-9]\\{1,3\\}" ip)) + (end (match-end 0)) + (nums (mapcar #'string-to-number (split-string (substring ip start end) "\\.")))) + (and (zerop start) + (length= ip end) + (seq-every-p #'(lambda (num) (and (>= num 0) (<= num 255))) nums)))) + ;;; File Name Handling: ;; @@ -1094,6 +1112,8 @@ ffap-string-at-point-mode-alist (nocolon "--9$+<>@-Z_[:alpha:]~" "<@" "@>;.,!?") ;; A machine: (machine "-[:alnum:]." "" ".") + ;; An IPv4 address: + (ipv4 "[0-9]." "" ".") ;; Mathematica paths: allow backquotes (math-mode ",-:$+<>@-Z_[:lower:]~`" "<" "@>;.,!?`:") ;; (La)TeX: don't allow braces diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el index c7ff175e08..15195a1fdf 100644 --- a/lisp/net/net-utils.el +++ b/lisp/net/net-utils.el @@ -577,7 +577,7 @@ dns-lookup-host This command uses `dns-lookup-program' for looking up the DNS information." (interactive - (list (let ((default (ffap-machine-at-point))) + (list (let ((default (or (ffap-machine-at-point) (ffap-ipv4-at-point)))) (read-string (format-prompt "Lookup host" default) nil nil default)) (if current-prefix-arg (read-from-minibuffer "Name server: ")))) (let ((options diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el index 4b580b5af5..1f9313e274 100644 --- a/test/lisp/ffap-tests.el +++ b/test/lisp/ffap-tests.el @@ -158,6 +158,32 @@ ffap-test-path (goto-char (point-min)) (should (equal (ffap-file-at-point) nil)))) +(ert-deftest ffap-ipv4-at-point () + (with-temp-buffer + (insert "\ +aaaaaaaaaaaaaaaaaaaaaaa +3.14,15:92 +1.X2.3.4 +5.6.7 +8.9.444.2 +1.2.3.4 +bbbb5.6.7.8ccc\n") + (goto-char (point-min)) + (should-not (ffap-ipv4-at-point)) + (forward-line) + (should-not (ffap-ipv4-at-point)) + (forward-line) + (should-not (ffap-ipv4-at-point)) + (forward-line) + (should-not (ffap-ipv4-at-point)) + (forward-line) + (should-not (ffap-ipv4-at-point)) + (forward-line) + (should (equal (ffap-ipv4-at-point) "1.2.3.4")) + (forward-line) + (forward-char 7) + (should (equal (ffap-ipv4-at-point) "5.6.7.8")))) + (provide 'ffap-tests) ;;; ffap-tests.el ends here