;;; ergoemacs-lib.el --- Ergoemacs libraries -*- lexical-binding: t -*-
;; Copyright © 2013-2021 Free Software Foundation, Inc.
;; Author: Matthew L. Fidler, Xah Lee
;; Maintainer:
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 3, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Code:
;; (require 'guide-key nil t)
(require 'cl-lib)
(require 'find-func)
(eval-when-compile
(require 'ergoemacs-macros))
(defvar mode-icons-show-mode-name)
(defvar mode-icons-read-only-space)
(defvar mode-icons-cached-mode-name)
(defvar mode-icons-eol-text)
(defvar ergoemacs-excluded-major-modes)
(defvar ergoemacs-keyboard-layout)
(defvar ergoemacs-keymap)
(defvar ergoemacs-mode)
(defvar ergoemacs-mode-names)
(defvar ergoemacs-require)
(defvar ergoemacs-theme-hash)
(defvar ergoemacs-dir)
(declare-function ergoemacs-next-emacs-buffer "ergoemacs-functions")
(declare-function ergoemacs-next-user-buffer "ergoemacs-functions")
(declare-function ergoemacs-previous-emacs-buffer "ergoemacs-functions")
(declare-function ergoemacs-previous-user-buffer "ergoemacs-functions")
(declare-function mode-icons-get-mode-icon "mode-icons")
(declare-function ergoemacs-autoloadp "ergoemacs-macros")
(declare-function ergoemacs-mode-reset "ergoemacs-mode")
(declare-function ergoemacs-theme-option-on "ergoemacs-theme-engine")
(declare-function ergoemacs-key-description--menu "ergoemacs-key-description")
(declare-function ergoemacs-emacs-exe "ergoemacs-functions")
(declare-function ergoemacs-translate--ahk-ini "ergoemacs-translate")
(declare-function ergoemacs-command-loop--spinner-display "ergoemacs-command-loop")
(defun ergoemacs-setcdr (var val &optional default)
"Use `setcdr' on VAL to VAL.
If VAL is a symbol, use `ergoemacs-sv' to determine the value.
If VAR is nil, return nil and do nothing.
If DEFAULT is non-nil set the default value, instead of the symbol value."
(if (symbolp var)
(setcdr (ergoemacs-sv var default) val)
(if (not var) nil
(setcdr var val))))
(defvar ergoemacs-xah-emacs-lisp-tutorial-url
"http://ergoemacs.org/emacs/elisp.html")
(defvar ergoemacs-mode-web-page-url
"http://ergoemacs.github.io/")
(defun ergoemacs-menu--get-major-mode-name (mode)
"Gets the MODE language name.
Tries to get the value from `ergoemacs-mode-names'. If not guess the language name."
(let ((ret (assoc mode ergoemacs-mode-names)))
(if (not ret)
(setq ret (replace-regexp-in-string
"-" " "
(replace-regexp-in-string
"-mode" ""
(symbol-name mode))))
(setq ret (car (cdr ret))))
(setq ret (concat (upcase (substring ret 0 1))
(substring ret 1)))
ret))
(defcustom ergoemacs-major-mode-menu-map-extra-modes
'(fundamental-mode lisp-interaction-mode)
"List of extra modes that should bring up the major-mode menu."
:type '(repeat (function :tag "Major Mode"))
:group 'ergoemacs-mode)
(defvar ergoemacs-menu--get-major-modes nil
"List of major-modes known to `ergoemacs-mode'.")
(defcustom ergoemacs-excluded-major-modes
'(conf-colon-mode
conf-xdefaults-mode conf-space-mode conf-javaprop-mode
conf-ppd-mode mail-mode
ebrowse-tree-mode diff-mode fundamental-mode emacs-lisp-byte-code-mode
R-transcript-mode S-transcript-mode XLS-mode tar-mode
git-commit-mode git-rebase-mode image-mode
archive-mode ses-mode)
"List of major modes excluded from ergoemacs' Languages menu."
:type '(repeat (symbol :tag "Excluded Major Mode"))
:group 'ergoemacs-mode)
(defcustom ergoemacs-mode-names
'((conf-mode "Settings")
(ses-mode "Emacs Spreadsheet")
(m2-mode "Modula-2")
(snmpv2-mode "SNMPv2 MIBs")
(snmp-mode "SKMP MIBs"))
"Menu name for ergoemacs' Languages menu."
:type '(repeat
(list
(symbol :tag "Major Mode Name")
(text :tag "Alternative Description:")))
:group 'ergoemacs-mode)
(defun ergoemacs-menu--get-major-modes ()
"Gets a list of language modes known to `ergoemacs-mode'.
This gets all major modes known from the variables:
- `interpreter-mode-alist';
- `magic-mode-alist'
- `magic-fallback-mode-alist'
- `auto-mode-alist'
- `ergoemacs-major-mode-menu-map-extra-modes'
All other modes are assumed to be minor modes or unimportant.
"
;; Get known major modes
(let ((ret '())
all dups cur-lst current-letter
added-modes
(modes '()))
(dolist (elt ergoemacs-major-mode-menu-map-extra-modes)
(unless (memq elt modes)
(when (and (functionp elt)
(ignore-errors (string-match "-mode$" (symbol-name elt))))
(unless (or (memq elt ergoemacs-excluded-major-modes)
(member (downcase (symbol-name elt)) added-modes))
(let* ((name (ergoemacs-menu--get-major-mode-name elt))
(first (upcase (substring name 0 1))))
(if (member first all)
(unless (member first dups)
(push first dups))
(push first all))
(push (list elt 'menu-item
name
elt)
ret))
(push (downcase (symbol-name elt)) added-modes)
(push elt modes)))))
(dolist (elt (append
interpreter-mode-alist
magic-mode-alist
magic-fallback-mode-alist
auto-mode-alist))
(unless (memq (cdr elt) modes)
(when (and (functionp (cdr elt))
(ignore-errors (string-match "-mode$" (symbol-name (cdr elt)))))
(unless (or (memq (cdr elt) ergoemacs-excluded-major-modes)
(member (downcase (symbol-name (cdr elt))) added-modes))
(let* ((name (ergoemacs-menu--get-major-mode-name (cdr elt)))
(first (upcase (substring name 0 1))))
(if (member first all)
(unless (member first dups)
(push first dups))
(push first all))
(push (list (cdr elt) 'menu-item
name
(cdr elt))
ret))
(push (downcase (symbol-name (cdr elt))) added-modes)
(push (cdr elt) modes)))))
(setq modes (sort ret (lambda(x1 x2) (string< (downcase (nth 2 x2))
(downcase (nth 2 x1)))))
ergoemacs-menu--get-major-modes (mapcar (lambda(x) (intern x)) added-modes))
(setq ret '())
(dolist (elt modes)
(let ((this-letter (upcase (substring (nth 2 elt) 0 1))))
(cond
((not (member this-letter dups))
;; not duplicated -- add prior list and push current element.
(when cur-lst
(push `(,(intern current-letter) menu-item ,current-letter
(keymap ,@cur-lst)) ret))
(push elt ret)
(setq current-letter this-letter)
(setq cur-lst nil))
((not (equal this-letter current-letter))
;; duplicated, but not last letter.
(when cur-lst
(push `(,(intern current-letter) menu-item ,current-letter
(keymap ,@cur-lst)) ret))
(setq cur-lst nil)
(setq current-letter this-letter)
(push elt cur-lst))
(t
;; duplicated and last letter
(push elt cur-lst)))))
(when cur-lst
(push `(,(intern current-letter) menu-item ,current-letter
(keymap ,@cur-lst)) ret))
;; Now create nested menu.
`(keymap ,@ret
(separator1 menu-item "--")
(package menu-item "Manage Packages" list-packages))))
;;;###autoload
(defun ergoemacs-gen-ahk (&optional all)
"Generates autohotkey for all layouts and themes"
(interactive)
(if (called-interactively-p 'any)
(progn
(shell-command (format "%s -Q --batch -l %s/ergoemacs-mode --eval \"(ergoemacs-gen-ahk %s)\" &"
(ergoemacs-emacs-exe)
ergoemacs-dir (if current-prefix-arg "t" "nil"))))
(let ((xtra "ahk")
(extra-dir)
file-temp)
(setq extra-dir (expand-file-name "ergoemacs-extras" user-emacs-directory))
(if (not (file-exists-p extra-dir))
(make-directory extra-dir t))
(setq extra-dir (expand-file-name xtra extra-dir))
(if (not (file-exists-p extra-dir))
(make-directory extra-dir t))
(setq file-temp (expand-file-name "ergoemacs.ini" extra-dir))
(with-temp-file file-temp
(set-buffer-file-coding-system 'utf-8)
(insert (ergoemacs-translate--ahk-ini all)))
(setq file-temp (expand-file-name "ergoemacs.ahk" extra-dir))
(with-temp-file file-temp
(set-buffer-file-coding-system 'utf-8)
(insert-file-contents (expand-file-name "ahk-us.ahk" ergoemacs-dir)))
(message "Generated ergoemacs.ahk")
(when (executable-find "ahk2exe")
(shell-command (format "ahk2exe /in %s" file-temp))
(message "Generated ergoemacs.exe")))))
(defvar ergoemacs-warn nil
"List of warnings that `ergoemacs-mode' already gave.")
(defun ergoemacs-warn (&rest args)
"Warn user only once.
When not contaiend in the variable `ergoemacs-mode', apply ARGS
to the `warn' function."
(unless (member args ergoemacs-warn)
(display-warning 'ergoemacs (apply #'format args) :warning)
(push args ergoemacs-warn)))
(defvar ergoemacs-field-len nil)
(defvar ergoemacs-cc-len nil)
(defvar ergoemacs-at-len nil)
(defvar ergoemacs-et-len nil)
(defvar ergoemacs-mn-len nil)
(defvar ergoemacs-mx-len nil)
(provide 'ergoemacs-lib)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; ergoemacs-lib.el ends here
;; Local Variables:
;; coding: utf-8-emacs
;; End: