emacs/lisp/system.el

152 lines
5.8 KiB
EmacsLisp

;;; system.el --- System-specific configuration -*- lexical-binding: t; -*-
;;; Commentary:
;; When using Emacs on separate computers, some variables need different
;; settings. This library contains functions and variables to work with
;; different system configurations for Emacs.
;;; Code:
(require 'cl-lib)
(defgroup system nil
"System-specific configurations."
:group 'emacs
:prefix "system-")
;;; Variables
(defcustom system-load-alist '((system-microsoft-p . windows)
(system-linux-p . linux))
"Alist describing which system Emacs is on.
Each cell is of the form (PREDICATE . SYSTEM), where PREDICATE is
a function of no arguments and SYSTEM is a string or symbol that
will be passed to `system-settings-load'.
This list need not be exhaustive; see `system-settings-load' for
more details on what happens if this alist is exhausted."
:type '(alist :key-type function :value-type (choice string symbol)))
(defcustom system-load-directory (locate-user-emacs-file "systems")
"The directory from which to load system-specific configurations."
:type 'file)
;; `defcustoms' defined here are best-guess defaults.
(defcustom system-default-font (pcase system-type
((or 'ms-dos 'windows-nt)
"Consolas")
(_ "monospace"))
"The font used for the `default' face."
:type 'string)
(defcustom system-default-height 100
"The height used for the `default' face."
:type 'number)
(defcustom system-variable-pitch-font (pcase system-type
((or 'ms-dos 'windows-nt)
"Arial")
(_ "sans-serif"))
"The font used for the `variable-pitch' face."
:type 'string)
(defcustom system-variable-pitch-height 1.0
"The height used for the `variable-pitch' face.
A floating-point number is recommended, since that makes it
relative to the `default' face height."
:type 'number)
(defvar system-file nil
"The current system's file for system-specific configuration.
Do not edit this by hand. Instead, call `system-system-file'.")
;;; Functions
;; Convenience functions for systems
(defun system-microsoft-p ()
"Return non-nil if running in a Microsoft system."
(memq system-type '(ms-dos windows-nt)))
(defun system-linux-p ()
"Return non-nil if running on a Linux system."
(memq system-type '(gnu/linux)))
(defun system-warn (message &rest args)
"Display a wraning message made from (format-message MESSAGE ARGS...).
This function is like `warn', except it uses the `system' type."
(display-warning 'system (apply #'format-message message args)))
(defun system-system-file (&optional system refresh-cache set-system-file-p)
"Determine the current system's system-specific file.
The current system's file will be returned, and the value of
`system-file' set /unless/ the parameter SYSTEM was passed to
this function and SET-SYSTEM-FILE-P is nil. If both SYSTEM and
SET-SYSTEM-FILE-P are non-nil, this function will still set
`system-file'.
If SYSTEM is not passed, and `system-file' is set, simply return
its value /unless/ REFRESH-CACHE is non-nil, in which case
`system-load-alist' will be looped through to find the
appropriate system by testing the car of each cell there. When
one matches, use the cdr of that cell as SYSTEM. If none
matches, return nil.
This function will only look for system-specific files in
`system-load-directory'."
(let* ((system* (or system
(and system-file (not refresh-cache))
(cl-loop for (p . s) in system-load-alist
if (funcall p) return s)))
(file (expand-file-name (format "%s" system*) system-load-directory)))
(when (or (not system)
(and system set-system-file-p))
(setq system-file file))
file))
;;;###autoload
(defun system-settings-load (&optional system error nomessage)
"Load system settings.
Load settings from `system-file', or the `system-file' as
determined by SYSTEM, if passed. See `system-system-file' for
details on how the `system-file' is determined.
ERROR determines how to deal with errors: if nil, warn the user
when `system-file' can't be found or when the system being used
can't be determined. If t, those are elevated to errors. If any
other value, the errors are completely ignored.
NOMESSAGE is passed directly to `load'."
(let ((file (system-system-file system)))
(if file
(condition-case e
(load file nil nomessage)
(t (cond ((eq error t) (signal (car e) (cdr e)))
((null error) (system-warn "Couldn't find file `%s'."
file)))))
(funcall (cond ((eq error t) #'error)
((null error) #'system-warn)
(t #'ignore))
"Could not determine the system being used."))))
;;;###autoload
(defun system-find-system-file (&optional system)
"Find the current system's system-file."
(interactive (list (completing-read "System file: "
(mapcar (lambda (a) (format "%s" (cdr a)))
system-load-alist)
nil t nil nil
(cl-loop for (p . s) in system-load-alist
if (funcall p)
return (format "%s" s)))))
(find-file (cl-loop with file = (system-system-file system)
for cand in (list file
(concat file ".el"))
if (file-exists-p cand)
return cand
finally return cand)))
(provide 'system)
;;; system.el ends here