anchor.diff: +(defpackage :lem-vi-mode.ex-command
  +  (:use :cl :lem)
  +  (:export :search-forward
  +           :search-backward
  +           :goto-line
  +           :current-line
  +           :last-line
  +           :all-lines
  +           :marker
  +           :offset-line
  +           :search-forward
  +           :search-backward
  +           :goto-current-point
  +           :range))
  +
   (defpackage :lem-vi-mode.ex-parser
     (:use :cl)
     (:export :parse-ex-range))
   (in-package :lem-vi-mode.ex-parser)
   
  -(defstruct lexer
  +(defstruct (lexer (:constructor %make-lexer))
     position
     string)
  +
  +(defun make-lexer (string)
  +  (%make-lexer :string string :position 0))
   
   (defun lookahead (lexer)
     (char (lexer-string lexer) (lexer-position lexer)))
  
positive.code:   (unless (end-of-string-p lexer)
      (cond ((accept lexer #\+)
             (alexandria:when-let ((number (match-number lexer)))
               (list :offset number)))
            ((accept lexer #\-)
             (alexandria:when-let ((number (match-number lexer)))
               (list :offset (- number)))))))
  
  (defun parse-ex-range-element (lexer)
    (let ((list (loop
  
negative.code:                 :for offset := (parse-ex-offset lexer)
                  :collect line
                  :when offset :collect it
                  :unless (and (member (first line)
                                       '(lem-vi-mode.ex-command:search-forward
                                         lem-vi-mode.ex-command:search-backward))
                               (setf line (match-pattern lexer)))
                  :do (loop-finish))))
      (if (alexandria:length= list 1)
          (first list)
          `(progn . ,list))))
  
  (defun delimiter (lexer)
    (unless (end-of-string-p lexer)
      (cond ((accept lexer #\,)
             (values nil t))
            ((accept lexer #\;)
             (values 'lem-vi-mode.ex-command:goto-current-point t))
            (t
             (values nil nil)))))
  
  (defun parse-ex-range (lexer)
    (let ((range '()))
      (loop :with delim := nil :and contp := nil
            :for elt := (parse-ex-range-element lexer)
            :do (when elt (push elt range))
                (setf (values delim contp) (delimiter lexer))
                (unless contp (return))
                (when delim
                  (setf (first range) (list delim (first range)))))
      (when range
        `(lem-vi-mode.ex-command:range . ,(nreverse range)))))
  
  (defun parse-ex (lexer)
    (let ((range (parse-ex-range lexer)))
      ))
  