;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: help, faces
-;; Version: 0.98
+;; Version: 0.995
;; X-URL: http://www.dina.kvl.dk/~abraham/custom/
;;; Commentary:
(require 'custom)
(require 'widget-edit)
+(require 'easymenu)
(define-widget-keywords :custom-show :custom-magic
:custom-state :custom-level :custom-form
sexp
(list 'quote sexp)))
-(defun custom-unimplemented (&rest ignore)
- "Apologize for my laziness."
- (error "Sorry, not implemented"))
-
;;; Modification of Basic Widgets.
;;
;; We add extra properties to the basic widgets needed here. This is
FACE is a face used to present the state.
The list should be sorted most significant first."
- :type '(repeat (list (choice (item nil)
- (item unknown)
- (item hidden)
- (item invalid)
- (item modified)
- (item applied)
- (item saved)
- (item rogue)
- (item factory))
+ :type '(repeat (list (choice (const nil)
+ (const unknown)
+ (const hidden)
+ (const invalid)
+ (const modified)
+ (const applied)
+ (const saved)
+ (const rogue)
+ (const factory))
string face))
:group 'customize)
;;; The `custom' Widget.
+(defvar custom-save-needed-p nil
+ "Non-nil if any customizations need to be saved.")
+
+(add-hook 'kill-emacs-hook 'custom-save-maybe)
+
+(defun custom-save-maybe ()
+ (and custom-save-needed-p
+ (y-or-n-p "You have unsaved customizations, save them now? ")
+ (custom-save)))
+
(define-widget 'custom 'default
"Customize a user option."
:convert-widget 'widget-item-convert-widget
(defun custom-format-handler (widget escape)
;; We recognize extra escape sequences.
- (let* ((symbol (widget-get widget :value))
- (buttons (widget-get widget :buttons))
+ (let* ((buttons (widget-get widget :buttons))
(level (widget-get widget :custom-level)))
(cond ((eq escape ?l)
(when level
(form (widget-get widget :custom-form))
(state (widget-get widget :custom-state))
(symbol (widget-get widget :value))
+ (options (get symbol 'custom-options))
(child-type (or (get symbol 'custom-type) 'sexp))
- (type (if (listp child-type)
- child-type
- (list child-type)))
+ (type (let ((tmp (if (listp child-type)
+ child-type
+ (list child-type))))
+ (when options
+ (widget-put tmp :options options))
+ tmp))
(conv (widget-convert type))
(value (if (boundp symbol)
(symbol-value symbol)
(cond ((eq state 'hidden)
(error "Cannot apply hidden variable."))
((setq val (widget-apply child :validate))
- (error "Invalid %S"))
+ (error "Invalid %S" val))
((eq form 'lisp)
(set symbol (eval (widget-value child))))
(t
(cond ((eq state 'hidden)
(error "Cannot apply hidden variable."))
((setq val (widget-apply child :validate))
- (error "Invalid %S"))
+ (error "Invalid %S" val))
((eq form 'lisp)
+ (setq custom-save-needed-p (cons symbol custom-save-needed-p))
(put symbol 'saved-value (list (widget-value child)))
(set symbol (eval (widget-value child))))
(t
+ (setq custom-save-needed-p (cons symbol custom-save-needed-p))
(put symbol
'saved-value (list (custom-quote (widget-value
child))))
"Restore the factory setting for the variable being edited by WIDGET."
(let ((symbol (widget-value widget)))
(if (get symbol 'factory-value)
- (set symbol (car (get symbol 'factory-value)))
+ (set symbol (eval (car (get symbol 'factory-value))))
(error "No factory default for %S" symbol))
(when (get symbol 'saved-value)
+ (setq custom-save-needed-p (cons symbol custom-save-needed-p))
(put symbol 'saved-value nil))
(widget-put widget :custom-state 'unknown)
(custom-redraw widget)))
(cond ((eq escape ?s)
(setq child (widget-create-child-and-convert
widget 'custom-level
- :format "(%[sample%])\n"
+ :format "(%[show%])\n"
:button-face symbol)))
(t
(custom-format-handler widget escape)))
(child (car (widget-get widget :children))))
(unless (get symbol 'saved-face)
(error "No saved value for this face")
- (widget-value-set child (get symbol 'saved-face)))))
+ (widget-value-set child (get symbol 'saved-face)))))
(defun custom-face-factory (widget)
"Restore WIDGET to the face's factory settings."
(define-widget 'face 'default
"Select and customize a face."
:convert-widget 'widget-item-convert-widget
- :format "%[%t%]%v"
+ :format "%[%t%]: %v"
+ :tag "Face"
:value 'default
:value-create 'widget-face-value-create
:value-delete 'widget-radio-value-delete
(let* ((symbol (widget-value widget))
(child (widget-create-child-and-convert
widget 'custom-face
+ :format "%t %s%m %h%v"
:custom-level nil
- :tag ""
:value symbol)))
(custom-magic-reset child)
(widget-put widget :children (list child))))
'face-history)))
(unless (zerop (length answer))
(widget-value-set widget (intern answer))
+ (widget-apply widget :notify widget event)
(widget-setup))))
+;;; The `hook' Widget.
+
+(define-widget 'hook 'list
+ "A emacs lisp hook"
+ :convert-widget 'custom-hook-convert-widget
+ :tag "Hook")
+
+(defun custom-hook-convert-widget (widget)
+ ;; Handle `:custom-options'.
+ (let* ((options (widget-get widget :options))
+ (other `(editable-list :inline t (function :format "%v")))
+ (args (if options
+ (list `(checklist :inline t
+ ,@(mapcar (lambda (entry)
+ `(function-item ,entry))
+ options))
+ other)
+ (list other))))
+ (widget-put widget :args args)
+ widget))
+
;;; The `custom-group' Widget.
(define-widget 'custom-group 'custom
(interactive)
(custom-save-variables)
(custom-save-faces)
+ (setq custom-save-needed-p nil)
(save-excursion
(set-buffer (find-file-noselect custom-file))
(save-buffer)))