<commit_before>(require 'aspk-tooltip)
(require 'aspk-keybind)
(require 'aspk-debug)
(require 'aspk-lisp)

;; start and end start form 0, end not included. current-select start form 1.
(defun aspk/selectlist-create (row column candidates count &optional start)
  (tracem row column candidates count start)
  ;; (and (null end) (setq end 9999999))
  ;; (setq end (min end (+ start 9) (length candidates)))
  (when (null start) (setq start 0))

  (tracem str pos)
  (let (tt)
    (setq tt (aspk/tooltip-create-no-wrap row column ""))
    (aspk/tooltip-set tt 'page-size count)
    (aspk/tooltip-set tt 'candidates candidates)
    ;; (aspk/tooltip-set tt 'start start)
    ;; (aspk/tooltip-set tt 'end end)
    (aspk/tooltip-set tt 'current-select 1)
    ;; (aspk/tooltip-set tt 'candidates-pos (reverse pos))

    (aspk/selectlist-set-page tt 0)

    tt))

(defun aspk/selectlist-set-page (selectlist idx)
  "Set current page index to IDX.
IDX, number, page number. Start form 0"
  (traceh selectlist idx)
  (let* ((candidates (aspk/tooltip-get selectlist 'candidates))
         (page-size (aspk/tooltip-get selectlist 'page-size))
         (current-candidates (aspk/lisp-sublist candidates (* idx page-size) page-size))
         (tmp (aspk/selectlist--make-list-string current-candidates))
         (str (car tmp))
         (pos (cdr tmp)))
    (traceh str pos candidates page-size)
    (if (= 0 (length current-candidates))
        (message "No more candidates for page %d" idx)
      (aspk/tooltip-set selectlist 'page-index idx)
      (aspk/tooltip-set selectlist 'current-candidates current-candidates)
      (aspk/tooltip-set selectlist 'aspk/tooltip-content
                        (aspk/tooltip-propertize-string str))
      (aspk/tooltip-set selectlist 'candidates-pos pos)
      (aspk/selectlist-highlight selectlist 1))))

(defun aspk/selectlist--make-list-string (candidates)
  "Make CANDIDATES a select list string.
CANDIDATES, list of strings."
  (tracem candidates)
  (let* ((idx 1)
         (start 0)
         (end (length candidates))
         (str (concat "1." (nth start candidates)))
         tt
         t1
         t2 t3
         (orig-start start)
         (last-pos (length str))
         (pos (list (cons 0 (length str)))))

    ;; mapconcat (lambda (x)
    ;; (incf idx)
    ;; (format "%d. %s" idx x)) candidates "  "))

    ;; (and (null end) (setq end 9999999))

    (tracel start end t1 t2 pos last-pos idx)
    ;; (setq end (min end (+ start 9) (length candidates)))

    (incf start)
    (while (< start end)
      (tracel start end t1 t2 pos last-pos idx)
      (incf idx)
      (setq t1 (nth start candidates))
      (setq t3 (format " %d.%s" idx t1))
      (setq t2 (- (length t3) 1))
      (setq last-pos (+ 1 last-pos)) ;; 1 is length of the spliter " " for candidates

      (push (cons last-pos (+ last-pos t2)) pos)
      (setq last-pos (+ last-pos t2))
      ;; (setq last-pos (+ last-pos 2 t2))
      (setq str (concat str t3))
      (incf start))
    (cons str (reverse pos))))

(defface aspk/selectlist-highlight-face-1
  '((default :foreground "red")
    (((class color) (min-colors 88) (background light))
     (:background "cornsilk"))
    (((class color) (min-colors 88) (background dark))
     (:background "yellow")))
  "Face used for the hightlight select list.")

(defun aspk/selectlist-highlight (selectlist idx)
  "High light selectlist's `idx' candidate"
  (traceh selectlist idx)
  (let ((candidates (aspk/tooltip-get selectlist 'candidates))
        (pos (nth (- idx 1) (aspk/tooltip-get selectlist 'candidates-pos)))
        (content (aspk/tooltip-get selectlist 'aspk/tooltip-content)))
    (traceh candidates pos content)
    (aspk/selectlist-unhighlight selectlist)
    (add-text-properties (car pos) (cdr pos) '(face aspk/selectlist-highlight-face-1) content)
    ;; (add-text-properties (car pos) (cdr pos) '(face bold) content)
    (aspk/tooltip-set selectlist 'current-select idx)
    (aspk/tooltip-set selectlist 'aspk/tooltip-content content))
  (aspk/selectlist-show selectlist))

(defun aspk/selectlist-unhighlight (selectlist)
  "Unhigh light selectlist's hightlight candidate"
  (let ((candidates (aspk/tooltip-get selectlist 'candidates))
        (pos (nth (- (aspk/tooltip-get selectlist 'current-select) 1)
                  (aspk/tooltip-get selectlist 'candidates-pos)))
        (content (aspk/tooltip-get selectlist 'aspk/tooltip-content)))
    (traceh candidates pos content)
    ;; (add-text-properties (car pos) (cdr pos) '(face aspk/tooltip-face) content)
    ;; (aspk/tooltip-set selectlist 'current-select idx)
    (aspk/tooltip-propertize-string content)
    (aspk/tooltip-set selectlist 'aspk/tooltip-content content))
  (aspk/selectlist-show selectlist))

(defun aspk/selectlist-show (selectlist)
  "Select an item form the current select list, and return that value"
  ;; (aspk/selectlist-unhighlight selectlist)
  (aspk/tooltip-show selectlist))

(defun aspk/selectlist-highlight-next-one (selectlist)
  (let ((idx (aspk/tooltip-get selectlist 'current-select))
        (current-candidates (aspk/tooltip-get selectlist 'current-candidates))
        (page-index (aspk/tooltip-get selectlist 'page-index))
        (page-size (aspk/tooltip-get selectlist 'page-size)))
    (traceh idx current-candidates page-index page-size)
    (if (= idx page-size)
        (aspk/selectlist-set-page selectlist (+ 1 page-index))
      (if (<= (+ idx 1) (min  page-size (length current-candidates)))
          (aspk/selectlist-highlight selectlist (+ idx 1))))))

(defun aspk/selectlist-highlight-previous-one (selectlist)
  (let ((idx (aspk/tooltip-get selectlist 'current-select))
        (page-index (aspk/tooltip-get selectlist 'page-index))
        )
    (if (> idx 1)
        (aspk/selectlist-highlight selectlist (- idx 1))
      (if (> page-index 0)
          (progn
            (aspk/selectlist-set-page selectlist (- page-index 1))
            (aspk/selectlist-highlight selectlist
                                       (aspk/tooltip-get selectlist 'page-size)))))))

(defun aspk/selectlist-do-select (selectlist)
  "reuturn current selected candidate value"
  (let ((idx (aspk/tooltip-get selectlist 'current-select))
        (candidates (aspk/tooltip-get selectlist 'candidates))
        (page-size (aspk/tooltip-get selectlist 'page-size))
        (page-index (aspk/tooltip-get selectlist 'page-index)))
    (nth (+ (* page-index page-size) idx -1) candidates)))

(defun aspk/selectlist-select (selectlist)
  "Bind key to select."
  (let ((candidates (aspk/tooltip-get selectlist 'candidates)))
    (setq aspk/selectlist-tmp 0)
    (aspk/keybind-temporary-keymap-highest-priority
     (append `((C-f (aspk/selectlist-highlight-next-one ,selectlist))
               (C-b (aspk/selectlist-highlight-previous-one ,selectlist))
               (" " (aspk/selectlist-do-select ,selectlist) 1))
             ;; TODO: candidates start form start and end to end.
             (mapcar (lambda (x)
                       (incf aspk/selectlist-tmp)
                       (list (format "%d" aspk/selectlist-tmp)
                             `(progn
                                (aspk/selectlist-highlight ,selectlist ,aspk/selectlist-tmp)
                                (nth ,(- aspk/selectlist-tmp 1) candidates))
                             1))
                     candidates))
     )))

;; (append '((1 2)) '(2 3 )  '((4 5) (6 7)))

(defun aspk/selectlist-hide (selectlist)
  (aspk/tooltip-hide selectlist))

(provide 'aspk-selectlist)<commit_msg>add more keybinds for selecting an item.<commit_after>(require 'aspk-tooltip)
(require 'aspk-keybind)
(require 'aspk-debug)
(require 'aspk-lisp)

;; start and end start form 0, end not included. current-select start form 1.
(defun aspk/selectlist-create (row column candidates count &optional start)
  (tracem row column candidates count start)
  ;; (and (null end) (setq end 9999999))
  ;; (setq end (min end (+ start 9) (length candidates)))
  (when (null start) (setq start 0))

  (tracem str pos)
  (let (tt)
    (setq tt (aspk/tooltip-create-no-wrap row column ""))
    (aspk/tooltip-set tt 'page-size count)
    (aspk/tooltip-set tt 'candidates candidates)
    ;; (aspk/tooltip-set tt 'start start)
    ;; (aspk/tooltip-set tt 'end end)
    (aspk/tooltip-set tt 'current-select 1)
    ;; (aspk/tooltip-set tt 'candidates-pos (reverse pos))

    (aspk/selectlist-set-page tt 0)

    tt))

(defun aspk/selectlist-set-page (selectlist idx)
  "Set current page index to IDX.
IDX, number, page number. Start form 0"
  (traceh selectlist idx)
  (let* ((candidates (aspk/tooltip-get selectlist 'candidates))
         (page-size (aspk/tooltip-get selectlist 'page-size))
         (current-candidates (aspk/lisp-sublist candidates (* idx page-size) page-size))
         (tmp (aspk/selectlist--make-list-string current-candidates))
         (str (car tmp))
         (pos (cdr tmp)))
    (traceh str pos candidates page-size)
    (if (= 0 (length current-candidates))
        (message "No more candidates for page %d" idx)
      (aspk/tooltip-set selectlist 'page-index idx)
      (aspk/tooltip-set selectlist 'current-candidates current-candidates)
      (aspk/tooltip-set selectlist 'aspk/tooltip-content
                        (aspk/tooltip-propertize-string str))
      (aspk/tooltip-set selectlist 'candidates-pos pos)
      (aspk/selectlist-highlight selectlist 1))))

(defun aspk/selectlist--make-list-string (candidates)
  "Make CANDIDATES a select list string.
CANDIDATES, list of strings."
  (tracem candidates)
  (let* ((idx 1)
         (start 0)
         (end (length candidates))
         (str (concat "1." (nth start candidates)))
         tt
         t1
         t2 t3
         (orig-start start)
         (last-pos (length str))
         (pos (list (cons 0 (length str)))))

    ;; mapconcat (lambda (x)
    ;; (incf idx)
    ;; (format "%d. %s" idx x)) candidates "  "))

    ;; (and (null end) (setq end 9999999))

    (tracel start end t1 t2 pos last-pos idx)
    ;; (setq end (min end (+ start 9) (length candidates)))

    (incf start)
    (while (< start end)
      (tracel start end t1 t2 pos last-pos idx)
      (incf idx)
      (setq t1 (nth start candidates))
      (setq t3 (format " %d.%s" idx t1))
      (setq t2 (- (length t3) 1))
      (setq last-pos (+ 1 last-pos)) ;; 1 is length of the spliter " " for candidates

      (push (cons last-pos (+ last-pos t2)) pos)
      (setq last-pos (+ last-pos t2))
      ;; (setq last-pos (+ last-pos 2 t2))
      (setq str (concat str t3))
      (incf start))
    (cons str (reverse pos))))

(defface aspk/selectlist-highlight-face-1
  '((default :foreground "red")
    (((class color) (min-colors 88) (background light))
     (:background "cornsilk"))
    (((class color) (min-colors 88) (background dark))
     (:background "yellow")))
  "Face used for the hightlight select list.")

(defun aspk/selectlist-highlight (selectlist idx)
  "High light selectlist's `idx' candidate"
  (traceh selectlist idx)
  (let ((candidates (aspk/tooltip-get selectlist 'candidates))
        (pos (nth (- idx 1) (aspk/tooltip-get selectlist 'candidates-pos)))
        (content (aspk/tooltip-get selectlist 'aspk/tooltip-content)))
    (traceh candidates pos content)
    (aspk/selectlist-unhighlight selectlist)
    (add-text-properties (car pos) (cdr pos) '(face aspk/selectlist-highlight-face-1) content)
    ;; (add-text-properties (car pos) (cdr pos) '(face bold) content)
    (aspk/tooltip-set selectlist 'current-select idx)
    (aspk/tooltip-set selectlist 'aspk/tooltip-content content))
  (aspk/selectlist-show selectlist))

(defun aspk/selectlist-unhighlight (selectlist)
  "Unhigh light selectlist's hightlight candidate"
  (let ((candidates (aspk/tooltip-get selectlist 'candidates))
        (pos (nth (- (aspk/tooltip-get selectlist 'current-select) 1)
                  (aspk/tooltip-get selectlist 'candidates-pos)))
        (content (aspk/tooltip-get selectlist 'aspk/tooltip-content)))
    (traceh candidates pos content)
    ;; (add-text-properties (car pos) (cdr pos) '(face aspk/tooltip-face) content)
    ;; (aspk/tooltip-set selectlist 'current-select idx)
    (aspk/tooltip-propertize-string content)
    (aspk/tooltip-set selectlist 'aspk/tooltip-content content))
  (aspk/selectlist-show selectlist))

(defun aspk/selectlist-show (selectlist)
  "Select an item form the current select list, and return that value"
  ;; (aspk/selectlist-unhighlight selectlist)
  (aspk/tooltip-show selectlist))

(defun aspk/selectlist-goto-previous-page (selectlist &optional highlight-index)
  "Go to previous page.
HIGHLIGHT-INDEX, number, the item that will be highlighted in the new page, default to 1. Start form 1"
  (let ((page-index (aspk/tooltip-get selectlist 'page-index)))
    (when (> page-index 0)
      (aspk/selectlist-set-page selectlist (- page-index 1))
      (aspk/selectlist-highlight selectlist (or highlight-index 1)))))

(defun aspk/selectlist-goto-next-page (selectlist &optional highlight-index)
  "Go to next page.
HIGHLIGHT-INDEX, number, the item that will be highlighted in the new page, default to 1. Start form 1"
  (aspk/selectlist-set-page selectlist (+ 1 (aspk/tooltip-get selectlist 'page-index)))
  (aspk/selectlist-highlight selectlist (or highlight-index 1)))

(defun aspk/selectlist-highlight-next-one (selectlist)
  (let ((idx (aspk/tooltip-get selectlist 'current-select))
        (current-candidates (aspk/tooltip-get selectlist 'current-candidates))
        (page-index (aspk/tooltip-get selectlist 'page-index))
        (page-size (aspk/tooltip-get selectlist 'page-size)))
    (traceh idx current-candidates page-index page-size)
    (if (= idx page-size)
        (aspk/selectlist-goto-next-page selectlist)
      (if (<= (+ idx 1) (min  page-size (length current-candidates)))
          (aspk/selectlist-highlight selectlist (+ idx 1))))))

(defun aspk/selectlist-highlight-previous-one (selectlist)
  (let ((idx (aspk/tooltip-get selectlist 'current-select)))
    (if (> idx 1)
        (aspk/selectlist-highlight selectlist (- idx 1))
      (aspk/selectlist-goto-previous-page
       selectlist
       (aspk/tooltip-get selectlist 'page-size)))))

(defun aspk/selectlist-do-select (selectlist)
  "reuturn current selected candidate value"
  (let ((idx (aspk/tooltip-get selectlist 'current-select))
        (candidates (aspk/tooltip-get selectlist 'candidates))
        (page-size (aspk/tooltip-get selectlist 'page-size))
        (page-index (aspk/tooltip-get selectlist 'page-index)))
    (nth (+ (* page-index page-size) idx -1) candidates)))

(defun aspk/selectlist-select (selectlist)
  "Bind key to select."
  (let ((candidates (aspk/tooltip-get selectlist 'candidates))
        (last-element-index (min (aspk/tooltip-get selectlist 'page-size)
                                 (length (aspk/tooltip-get selectlist 'current-candidates)))))
    (setq aspk/selectlist-tmp 0)
    (aspk/keybind-temporary-keymap-highest-priority
     (append `((C-f (aspk/selectlist-highlight-next-one ,selectlist))
               (C-b (aspk/selectlist-highlight-previous-one ,selectlist))
               (C-a (aspk/selectlist-highlight ,selectlist 1))
               (C-e (aspk/selectlist-highlight ,selectlist ,last-element-index))
               (C-n (aspk/selectlist-goto-next-page ,selectlist))
               (C-p (aspk/selectlist-goto-previous-page ,selectlist))
               (" " (aspk/selectlist-do-select ,selectlist) 1))
             ;; TODO: candidates start form start and end to end.
             (mapcar (lambda (x)
                       (incf aspk/selectlist-tmp)
                       (list (format "%d" aspk/selectlist-tmp)
                             `(progn
                                (aspk/selectlist-highlight ,selectlist ,aspk/selectlist-tmp)
                                (nth ,(- aspk/selectlist-tmp 1) candidates))
                             1))
                     candidates))
     )))

;; (append '((1 2)) '(2 3 )  '((4 5) (6 7)))

(defun aspk/selectlist-hide (selectlist)
  (aspk/tooltip-hide selectlist))

(provide 'aspk-selectlist)
{'fraction_non_alphanumeric': 0.13499409827918246, 'fraction_numerical': 0.009877616947257252, 'mean_word_length': 2.856732151413512, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4976990', 'n_tokens_mistral': 5438, 'n_tokens_neox': 5154, 'n_words': 1404}