Function: editorconfig-fnmatch--do-translate

editorconfig-fnmatch--do-translate is a byte-compiled function defined in editorconfig-fnmatch.el.gz.

Signature

(editorconfig-fnmatch--do-translate PATTERN &optional NESTED)

Documentation

Translate a shell PATTERN to a regular expression.

Set NESTED to t when this function is called from itself.

This function is called from editorconfig-fnmatch-translate, when no cached translation is found for PATTERN.

Source Code

;; Defined in /usr/src/emacs/lisp/editorconfig-fnmatch.el.gz
(defun editorconfig-fnmatch--do-translate (pattern &optional nested)
  "Translate a shell PATTERN to a regular expression.

Set NESTED to t when this function is called from itself.

This function is called from `editorconfig-fnmatch-translate', when no cached
translation is found for PATTERN."
  (let ((index 0)
        (length (length pattern))
        (brace-level 0)
        (in-brackets nil)
        ;; List of strings of resulting regexp, in reverse order.
        (result ())
        (is-escaped nil)
        (matching-braces (= (editorconfig-fnmatch--match-num
                             editorconfig-fnmatch--left-brace-regexp
                             pattern)
                            (editorconfig-fnmatch--match-num
                             editorconfig-fnmatch--right-brace-regexp
                             pattern)))

        current-char
        pos
        has-slash
        has-comma
        num-range)

    (while (< index length)
      (if (and (not is-escaped)
               (string-match "[^]\\*?[{},/]+"
                             ;;(string-match "[^]\\*?[{},/\\-]+" "?.a")
                             pattern
                             index)
               (eq index (match-beginning 0)))
          (progn
            (push (regexp-quote (match-string 0 pattern)) result)
            (setq index (match-end 0)
                  is-escaped nil))

        (setq current-char (aref pattern index)
              index (1+ index))

        (push
         (cl-case current-char
           (?*
            (setq pos index)
            (if (and (< pos length)
                     (= (aref pattern pos) ?*))
                (progn
                  (setq index (1+ index))
                  ".*")
              "[^/]*"))

           (?? "[^/]")

           (?\[
            (if in-brackets
                "\\["
              (if (= (aref pattern index) ?/)
                  ;; Slash after an half-open bracket
                  (progn
                    (setq index (+ index 1))
                    "\\[/")
                (setq pos index
                      has-slash nil)
                (while (and (< pos length)
                            (not (= (aref pattern pos) ?\]))
                            (not has-slash))
                  (if (and (= (aref pattern pos) ?/)
                           (not (= (aref pattern (- pos 1)) ?\\)))
                      (setq has-slash t)
                    (setq pos (1+ pos))))
                (if has-slash
                    (let ((content (substring pattern index (1+ pos))))
                      (setq index (+ pos 2))
                      (concat "\\[" content "\\]"))
                  (setq in-brackets t)
                  (if (and (< index length)
                           (memq (aref pattern index)
                                 '(?! ?^)))
                      (progn
                        (setq index (1+ index))
                        "[^")
                    "[")))))

           (?\] (setq in-brackets nil) "]")

           (?\{
            (setq pos index
                  has-comma nil)
            (while (and (or (and (< pos length)
                                 (not (= (aref pattern pos) ?})))
                            is-escaped)
                        (not has-comma))
              (if (and (eq (aref pattern pos) ?,)
                       (not is-escaped))
                  (setq has-comma t)
                (setq is-escaped (and (eq (aref pattern pos)
                                          ?\\)
                                      (not is-escaped))
                      pos (1+ pos))))
            (if (and (not has-comma)
                     (< pos length))
                (let ((pattern-sub (substring pattern index pos)))
                  (setq num-range (string-match
                                   editorconfig-fnmatch--numeric-range-regexp
                                   pattern-sub))
                  (setq index (1+ pos))
                  (if num-range
                      (let ((number-start (string-to-number
                                           (match-string 1 pattern-sub)))
                            (number-end (string-to-number
                                         (match-string 2 pattern-sub))))
                        (regexp-opt
                         (mapcar #'number-to-string
                                 (cl-loop for i from number-start to number-end
                                          collect i))))
                    (let ((inner (editorconfig-fnmatch--do-translate
                                  pattern-sub t)))
                      (format "{%s}" inner))))
              (if matching-braces
                  (progn
                    (setq brace-level (1+ brace-level))
                    "\\(?:")
                "{")))

           (?,
            (if (and (> brace-level 0)
                     (not is-escaped))
                "\\|" ","))

           (?\}
            (if (and (> brace-level 0)
                     (not is-escaped))
                (progn
                  (setq brace-level (- brace-level 1))
                  "\\)")
              "}"))

           (?/
            (if (and (<= (+ index 3) (length pattern))
                     (string= (substring pattern index (+ index 3)) "**/"))
                (progn
                  (setq index (+ index 3))
                  "\\(?:/\\|/.*/\\)")
              "/"))

           (?\\ (when is-escaped "\\\\"))
           (t (regexp-quote (char-to-string current-char))))
         result)

        (setq is-escaped (and (= current-char ?\\) (not is-escaped)))))
    (unless nested
      (setq result `("\\'" ,@result "\\`")))
    (apply #'concat (reverse result))))