;;; lisp file for xyzzy ver0.2.2.234
;;; sort-text.l ver.0.1.0.0 // crayonzen [2023-03-12]16:07:38(+0900)

;;; テキストの行ソート。選択範囲とリージョンのそれぞれ昇順と降順
;;; stable-sort によるラインソート。keyは付けてない
;;; ソート sort（外部処理） コマンドは ANSI（Shift_JIS）でないと文字化けするため作成

(provide "sort-text")

(in-package "editor")

(export '(sort-lines-buffer
	  sort-lines-buffer-reverse
	  sort-lines
	  sort-region
	  sort-region-reverse
	  sort-selection
	  sort-selection-reverse))

(defun sort-lines-buffer ()
  (interactive "*")
  (if (pre-selection-p)
      (sort-selection)
    (sort-region)))

(defun sort-lines-buffer-reverse ()
  (interactive "*")
  (if (pre-selection-p)
      (sort-selection-reverse)
    (sort-region-reverse)))

(defun sort-lines (&optional from to (compare #'string-lessp))
  (interactive "*")
  
  (if (or (null from) (equal from ""))
      (setq from (point-min)))

  (if (or (null to) (equal to ""))
      (setq to (point-max)))
  
  (if (> from to)
      (rotatef from to))
  (save-excursion
    (goto-char from)
    (goto-bol)
    (setq frompoint (point))
    (setq fromlinenum (current-line-number))
    (goto-char to)
    (goto-eol)
    (setq topoint (point))
    (setq tolinenum (current-line-number))
    (if (equal fromlinenum tolinenum)
	(progn
	  (message "The range specification point is the same: ~S" fromlinenum))
      (progn
	(setq num fromlinenum)
	(goto-char from)
	(let* (linelist result)
	  (while (<= num tolinenum)
	    (setq line1 (buffer-substring (progn (goto-bol) (point))
					  (progn (goto-eol) (point))))
	    (push line1 linelist)
	    (forward-line)
	    (setq num (+ num 1)))
	  (setq linelist (stable-sort linelist compare))
	  (dolist (item linelist result)
	    (setq result (concat result (concat item "\n"))))
	  (setq result (delete #\LFD result :from-end t :count 1))
	  (delete-region frompoint topoint)
	  (insert result))))))

(defun sort-region ()
  (interactive "*")
  (sort-lines (mark) (point) #'string-lessp))

(defun sort-region-reverse ()
  (interactive "*")
  (sort-lines (mark) (point) #'string-not-lessp))

(defun sort-selection ()
  (interactive "*")
  (sort-lines (selection-mark) (selection-point) #'string-lessp))

(defun sort-selection-reverse ()
  (interactive "*")
  (sort-lines (selection-mark) (selection-point) #'string-not-lessp))

(global-set-key #\C-F7 'sort-lines-buffer)
(global-set-key #\C-S-F7 'sort-lines-buffer-reverse)

;下記の Ctrl-x- 後のキー入力だとリージョンはOKだが、選択範囲は解除されてしまう。
;(define-key ctl-x-map #\l 'sort-lines-buffer)
;(define-key ctl-x-map #\m 'sort-lines-buffer-reverse)
