Mercurial > hg > xemacs-beta
view lisp/gtk-file-dialog.el @ 5882:bbe4146603db
Reduce regexp usage, now CL-oriented non-regexp code available, core Lisp
lisp/ChangeLog addition:
2015-04-01 Aidan Kehoe <kehoea@parhasard.net>
When calling #'string-match with a REGEXP without regular
expression special characters, call #'search, #'mismatch, #'find,
etc. instead, making our code less likely to side-effect other
functions' match data and a little faster.
* apropos.el (apropos-command):
* apropos.el (apropos):
Call (position ?\n ...) rather than (string-match "\n" ...) here.
* buff-menu.el:
* buff-menu.el (buffers-menu-omit-invisible-buffers):
Don't fire up the regexp engine just to check if a string starts
with a space.
* buff-menu.el (select-buffers-tab-buffers-by-mode):
Don't fire up the regexp engine just to compare mode basenames.
* buff-menu.el (format-buffers-tab-line):
* buff-menu.el (build-buffers-tab-internal): Moved to being a
label within the following.
* buff-menu.el (buffers-tab-items): Use the label.
* bytecomp.el (byte-compile-log-1):
Don't fire up the regexp engine just to look for a newline.
* cus-edit.el (get):
Ditto.
* cus-edit.el (custom-variable-value-create):
Ditto, but for a colon.
* descr-text.el (describe-text-sexp):
Ditto.
* descr-text.el (describe-char-unicode-data):
Use #'split-string-by-char given that we're just looking for a
semicolon.
* descr-text.el (describe-char):
Don't fire up the regexp engine just to look for a newline.
* disass.el (disassemble-internal):
Ditto.
* files.el (file-name-sans-extension):
Implement this using #'position.
* files.el (file-name-extension):
Correct this function's docstring, implement it in terms of
#'position.
* files.el (insert-directory):
Don't fire up the regexp engine to split a string by space; don't
reverse the list of switches, this is actually a longstand bug as
far as I can see.
* gnuserv.el (gnuserv-process-filter):
Use #'position here, instead of consing inside #'split-string
needlessly.
* gtk-file-dialog.el (gtk-file-dialog-update-dropdown):
Use #'split-string-by-char here, don't fire up #'split-string for
directory-sep-char.
* gtk-font-menu.el (hack-font-truename):
Implement this more cheaply in terms of #'find,
#'split-string-by-char, #'equal, rather than #'string-match,
#'split-string, #'string-equal.
* hyper-apropos.el (hyper-apropos-grok-functions):
* hyper-apropos.el (hyper-apropos-grok-variables):
Look for a newline using #'position rather than #'string-match in
these functions.
* info.el (Info-insert-dir):
* info.el (Info-insert-file-contents):
* info.el (Info-follow-reference):
* info.el (Info-extract-menu-node-name):
* info.el (Info-menu):
Look for fixed strings using #'position or #'search as appropriate
in this file.
* ldap.el (ldap-decode-string):
* ldap.el (ldap-encode-string):
#'encode-coding-string, #'decode-coding-string are always
available, don't check if they're fboundp.
* ldap.el (ldap-decode-address):
* ldap.el (ldap-encode-address):
Use #'split-string-by-char in these functions.
* lisp-mnt.el (lm-creation-date):
* lisp-mnt.el (lm-last-modified-date):
Don't fire up the regexp engine just to look for spaces in this file.
* menubar-items.el (default-menubar):
Use (not (mismatch ...)) rather than #'string-match here, for
simple regexp.
Use (search "beta" ...) rather than (string-match "beta" ...)
* menubar-items.el (sort-buffers-menu-alphabetically):
* menubar-items.el (sort-buffers-menu-by-mode-then-alphabetically):
* menubar-items.el (group-buffers-menu-by-mode-then-alphabetically):
Don't fire up the regexp engine to check if a string starts with
a space or an asterisk.
Use the more fine-grained results of #'compare-strings; compare
case-insensitively for the buffer menu.
* menubar-items.el (list-all-buffers):
* menubar-items.el (tutorials-menu-filter):
Use #'equal rather than #'string-equal, which, in this context,
has the drawback of not having a bytecode, and no redeeming
features.
* minibuf.el:
* minibuf.el (un-substitute-in-file-name):
Use #'count, rather than counting the occurences of $ using the
regexp engine.
* minibuf.el (read-file-name-internal-1):
Don't fire up the regexp engine to search for ?=.
* mouse.el (mouse-eval-sexp):
Check for newline with #'find.
* msw-font-menu.el (mswindows-reset-device-font-menus):
Split a string by newline with #'split-string-by-char.
* mule/japanese.el:
* mule/japanese.el ("Japanese"):
Use #'search rather than #'string-match; canoncase before
comparing; fix a bug I had introduced where I had been making case
insensitive comparisons where the case mattered.
* mule/korea-util.el (default-korean-keyboard):
Look for ?3 using #'find, not #'string-march.
* mule/korea-util.el (quail-hangul-switch-hanja):
Search for a fixed string using #'search.
* mule/mule-cmds.el (set-locale-for-language-environment):
#'position, #'substitute rather than #'string-match,
#'replace-in-string.
* newcomment.el (comment-make-extra-lines):
Use #'search rather than #'string-match for a simple string.
* package-get.el (package-get-remote-filename):
Use #'position when looking for ?@
* process.el (setenv):
* process.el (read-envvar-name):
Use #'position when looking for ?=.
* replace.el (map-query-replace-regexp):
Use #'split-string-by-char instead of using an inline
implementation of it.
* select.el (select-convert-from-cf-text):
* select.el (select-convert-from-cf-unicodetext):
Use #'position rather than #'string-match in these functions.
* setup-paths.el (paths-emacs-data-root-p):
Use #'search when looking for simple string.
* sound.el (load-sound-file):
Use #'split-string-by-char rather than an inline reimplementation
of same.
* startup.el (splash-screen-window-body):
* startup.el (splash-screen-tty-body):
Search for simple strings using #'search.
* version.el (emacs-version):
Ditto.
* x-font-menu.el (hack-font-truename):
Implement this more cheaply in terms of #'find,
#'split-string-by-char, #'equal, rather than #'string-match,
#'split-string, #'string-equal.
* x-font-menu.el (x-reset-device-font-menus-core):
Use #'split-string-by-char here.
* x-init.el (x-initialize-keyboard):
Search for a simple string using #'search.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Wed, 01 Apr 2015 14:28:20 +0100 |
parents | 308d34e9f07d |
children |
line wrap: on
line source
;;; gtk-file-dialog.el --- A nicer file selection dialog for XEmacs w/GTK primitives ;; Copyright (C) 2000 Free Software Foundation, Inc. ;; Maintainer: William M. Perry <wmperry@gnu.org> ;; Keywords: extensions, internal ;; This file is part of XEmacs. ;; XEmacs 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 of the License, or (at your ;; option) any later version. ;; XEmacs 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 XEmacs. If not, see <http://www.gnu.org/licenses/>. ;;; Synched up with: Not in FSF. ;;; Commentary: ;; The default GTK file selection dialog is not sufficient for our ;; needs. Limitations include: ;; ;; - not derived from GtkDialog ;; - no support for filters based on file types ;; - no support for setting an initial directory ;; - no way to tell it 'file must exist' ;; - no easy way to tell it to look at directories only ;; - ugly as sin ;; ;; This attempts to rectify the situation. (globally-declare-fboundp '(gtk-clist-clear gtk-clist-freeze gtk-clist-append gtk-clist-thaw gtk-combo-set-popdown-strings gtk-dialog-new gtk-dialog-vbox gtk-dialog-action-area gtk-window-set-title gtk-button-new-with-label gtk-container-add gtk-signal-connect gtk-entry-get-text gtk-widget-destroy gtk-combo-new gtk-combo-disable-activate gtk-box-pack-start gtk-combo-entry gtk-hbox-new gtk-clist-new-with-titles gtk-scrolled-window-new gtk-widget-set-usize gtk-clist-get-text gtk-entry-set-text gtk-button-clicked gtk-option-menu-new gtk-menu-new gtk-label-new gtk-menu-item-new-with-label gtk-menu-append gtk-widget-show gtk-option-menu-set-menu gtk-box-pack-end gtk-entry-new gtk-widget-set-sensitive gtk-widget-realize)) (defun gtk-file-dialog-fill-file-list (dialog dir) (if (not dir) (setq dir (get dialog 'x-file-dialog-current-dir nil))) (put dialog 'x-file-dialog-current-dir dir) (let ((list (get dialog 'x-file-dialog-files-list nil)) ;(remotep (file-remote-p dir)) ) (if (not list) nil (gtk-clist-clear list) (gtk-clist-freeze list) ;; NOTE: Current versions of efs / ange-ftp do not honor the ;; files-only flag to directory-files, but actually DOING these ;; checks is hideously expensive. Leave it turned off for now. (mapc #'(lambda (f) (if (or t ; Lets just wait for EFS to ;(not remotep) ; fix itself, shall we? ;(not (file-directory-p (expand-file-name f dir))) ) (gtk-clist-append list (list f)))) (directory-files dir nil (get dialog 'x-file-dialog-active-filter nil) nil t)) (gtk-clist-thaw list)))) (defun gtk-file-dialog-fill-directory-list (dialog dir) (let ((subdirs (directory-files dir nil nil nil 5)) ;(remotep (file-remote-p dir)) ;(selected-dir (get dialog 'x-file-dialog-current-dir "/")) (directory-list (get dialog 'x-file-dialog-directory-list))) (gtk-clist-freeze directory-list) (gtk-clist-clear directory-list) (while subdirs (if (equal "." (car subdirs)) nil ;; NOTE: Current versions of efs / ange-ftp do not honor the ;; files-only flag to directory-files, but actually DOING these ;; checks is hideously expensive. Leave it turned off for now. (if (or t ; Lets just wait for EFS to ;(not remotep) ; fix itself, shall we? ;(file-directory-p (expand-file-name (car subdirs) dir)) ) (gtk-clist-append directory-list (list (car subdirs))))) (pop subdirs)) (gtk-clist-thaw directory-list))) (defun gtk-file-dialog-update-dropdown (dialog dir) (let ((combo-box (get dialog 'x-file-dialog-select-list)) (components (nreverse (delete "" (split-string-by-char dir directory-sep-char)))) (entries nil)) (while components (push (concat "/" (mapconcat 'identity (reverse components) (char-to-string directory-sep-char))) entries) (pop components)) (push (expand-file-name "." "~/") entries) (gtk-combo-set-popdown-strings combo-box (nreverse entries)))) (defun gtk-file-dialog-select-directory (dialog dir) (gtk-file-dialog-fill-directory-list dialog dir) (gtk-file-dialog-fill-file-list dialog dir) (gtk-file-dialog-update-dropdown dialog dir)) (defun gtk-file-dialog-new (&rest keywords) "Create a XEmacs file selection dialog. Optional keyword arguments allowed: :title The title of the dialog :initial-directory Initial directory to show :filter-list List of filter descriptions and filters :file-must-exist Whether the file must exist or not :directory Look for a directory instead :callback Function to call with one arg, the selection " (let* ((dialog (gtk-dialog-new)) (vbox (gtk-dialog-vbox dialog)) (dir (plist-get keywords :initial-directory default-directory)) (button-area (gtk-dialog-action-area dialog)) ;(initializing-gtk-file-dialog t) (select-box nil) button hbox) (put dialog 'type 'dialog) (gtk-window-set-title dialog (plist-get keywords :title "Select a file...")) (setq button (gtk-button-new-with-label "OK")) (gtk-container-add button-area button) (gtk-signal-connect button 'clicked (lambda (button dialog) (funcall (get dialog 'x-file-dialog-callback 'ignore) (gtk-entry-get-text (get dialog 'x-file-dialog-entry nil))) (gtk-widget-destroy dialog)) dialog) (put dialog 'x-file-dialog-ok-button button) (setq button (gtk-button-new-with-label "Cancel")) (gtk-container-add button-area button) (gtk-signal-connect button 'clicked (lambda (button dialog) (gtk-widget-destroy dialog)) dialog) (put dialog 'x-file-dialog-cancel-button button) (put dialog 'x-file-dialog-callback (plist-get keywords :callback 'ignore)) (put dialog 'x-file-dialog-construct-args keywords) (put dialog 'x-file-dialog-current-dir dir) ;; Dropdown list of directories... (setq select-box (gtk-combo-new)) (gtk-combo-disable-activate select-box) (gtk-box-pack-start vbox select-box nil nil 5) (put dialog 'x-file-dialog-select-list select-box) ;; Hitting return in the entry will change dirs... (gtk-signal-connect (gtk-combo-entry select-box) 'activate (lambda (entry dialog) (gtk-file-dialog-select-directory dialog (gtk-entry-get-text entry))) dialog) ;; Start laying out horizontally... (setq hbox (gtk-hbox-new nil 0)) (gtk-box-pack-start vbox hbox t t 5) ;; Directory listing (let ((directories (gtk-clist-new-with-titles 1 '("Directories"))) (scrolled (gtk-scrolled-window-new nil nil))) (gtk-container-add scrolled directories) (gtk-widget-set-usize scrolled 200 300) (gtk-box-pack-start hbox scrolled t t 0) (put dialog 'x-file-dialog-directory-list directories) (put dialog 'x-file-dialog-directory-scrolled scrolled) (gtk-signal-connect directories 'select-row (lambda (list row column event dialog) (let ((dir (expand-file-name (gtk-clist-get-text (get dialog 'x-file-dialog-directory-list) row column) (get dialog 'x-file-dialog-current-dir)))) (if (and (misc-user-event-p event) (event-function event)) (gtk-file-dialog-select-directory dialog dir) (gtk-entry-set-text (get dialog 'x-file-dialog-entry) dir)))) dialog) ) (if (plist-get keywords :directory nil) ;; Directory listings only do not need the file or filters buttons. nil ;; File listing (let ((list (gtk-clist-new-with-titles 1 '("Files"))) (scrolled (gtk-scrolled-window-new nil nil))) (gtk-container-add scrolled list) (gtk-widget-set-usize scrolled 200 300) (gtk-box-pack-start hbox scrolled t t 0) (gtk-signal-connect list 'select-row (lambda (list row column event dialog) (gtk-entry-set-text (get dialog 'x-file-dialog-entry nil) (expand-file-name (gtk-clist-get-text list row column) (get dialog 'x-file-dialog-current-dir nil))) (if (and (misc-user-event-p event) (event-function event)) ;; Got a double or triple click event... (gtk-button-clicked (get dialog 'x-file-dialog-ok-button nil)))) dialog) (put dialog 'x-file-dialog-files-list list)) ;; Filters (if (not (plist-get keywords :filter-list nil)) ;; Don't need to bother packing this nil (setq hbox (gtk-hbox-new nil 0)) (gtk-box-pack-start vbox hbox nil nil 0) (let ((label nil) (options (plist-get keywords :filter-list nil)) (omenu nil) (menu nil) (item nil)) (setq omenu (gtk-option-menu-new) menu (gtk-menu-new) label (gtk-label-new "Filter: ")) (put dialog 'x-file-dialog-active-filter (cdr (car options))) (mapc (lambda (o) (setq item (gtk-menu-item-new-with-label (car o))) (gtk-signal-connect item 'activate (lambda (obj data) (put (car data) 'x-file-dialog-active-filter (cdr data)) (gtk-file-dialog-fill-file-list (car data) nil)) (cons dialog (cdr o))) (gtk-menu-append menu item) (gtk-widget-show item)) options) (gtk-option-menu-set-menu omenu menu) (gtk-box-pack-end hbox omenu nil nil 0) (gtk-box-pack-end hbox label nil nil 0)))) ;; Entry (let ((entry (gtk-entry-new))) (if (plist-get keywords :directory nil) nil (gtk-box-pack-start vbox entry nil nil 0)) (if (plist-get keywords :file-must-exist nil) (progn (gtk-widget-set-sensitive (get dialog 'x-file-dialog-ok-button nil) nil) (gtk-signal-connect entry 'changed (lambda (entry dialog) (gtk-widget-set-sensitive (get dialog 'x-file-dialog-ok-button) (file-exists-p (gtk-entry-get-text entry)))) dialog))) (put dialog 'x-file-dialog-entry entry)) (gtk-widget-realize dialog) ;; Populate the file list if necessary (gtk-file-dialog-select-directory dialog dir) dialog)) (provide 'gtk-file-dialog)