[sawfish] partial rewrite of fdo-menu
- From: Christopher Bratusek <chrisb src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [sawfish] partial rewrite of fdo-menu
- Date: Sun, 6 Sep 2009 19:35:44 +0000 (UTC)
commit b774d5e749d3e49b37b2d794f2e73abd7d9a0f6a
Author: chrisb <zanghar freenet de>
Date: Sun Sep 6 21:34:38 2009 +0200
partial rewrite of fdo-menu
ChangeLog | 3 +
lisp/sawfish/wm/ext/fdo-menu.jl | 403 +++++++++++++++++----------------------
2 files changed, 175 insertions(+), 231 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index ca8f612..96f9dad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2009-09-06 Christopher Bratusek <zanghar freenet de>
+ * lisp/sawfish/wm/ext/fdo-menu.jl: Partial rewrite of fdo-menu [Matthew Love]
+
2009-09-05 Christopher Bratusek <zanghar freenet de>
* sawfish.spec.in: improved [Kim B. Heino]
diff --git a/lisp/sawfish/wm/ext/fdo-menu.jl b/lisp/sawfish/wm/ext/fdo-menu.jl
index 35a1d59..eea940f 100644
--- a/lisp/sawfish/wm/ext/fdo-menu.jl
+++ b/lisp/sawfish/wm/ext/fdo-menu.jl
@@ -1,5 +1,5 @@
;-*-sawfish-*-
-;; (fdo-menu.jl (v0.6.5) --- sawfish wm menu generation -- librep)
+;; (fdo-menu.jl (v1.0.0) --- sawfish wm menu generation -- librep)
;; (c) 2009 Matthew Love
;; Christopher Bratusek
@@ -11,68 +11,12 @@
;; Create a sawfish wm menu from .desktop files
;; in your /usr/share/applications folder.
-#|
-
-Usage:
-
-Make sure the mk-saw-menu.jl is in your load path
-(i.e. ~/.sawfish/lisp), then in your .sawfish[/]rc file add:
-
-;; Optional Part, config bits, defaults listed below
-;; can be savely skipped, if you're fine with the defaults
-
-;; change xterm -e to your appropriate string (must have
-;; a space at the end)
-
-(setq my-term-string "xterm -e ")
-
-;; what locale for localized strings to use, if available
-;; eg.: set to de to read Dokumentbetrachter instead of Documentviewer
-
-(setq my-lang-string '())
-
-;; if your .desktop files are located somewhere else than
-;; /usr/share/applications, then change the desktop-directory
-
-(setq desktop-directory '("/usr/share/applications"))
-
-;; some entries are hidden from the menu, especially GNOME Apps
-;; like eog, nautilus or evince & Co, if you want to have them
-;; added to your menu, then replace '() by 't in the following
-
-(setq ignore-no-display '())
-
-;; if you don't want your menus to be sorted alphabetically
-;; then replace 't by '() in the following
-
-(setq want-alphabetize 't)
-
-;; Necessary part, can't be skipped
-
-;; load our script
-
-(require 'fdo-menu)
-
-;; generate and set the menu
-
-(update-saw-menu)
-
-|#
-
-;;; TODO:
-
-;; adhere to the desktop entry file specifications.
-;; http://standards.freedesktop.org/desktop-entry-spec/latest/
-;; add support for field codes: <a href="http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s06.html"
-;; add support for Comment=/Comment[lang]=
-;; add support for Icon=
-
;;; Code:
(define-structure sawfish.wm.ext.fdo-menu
(export update-saw-menu)
-
+
(open rep
rep.io.files
rep.io.streams
@@ -84,28 +28,74 @@ Make sure the mk-saw-menu.jl is in your load path
(unless batch-mode
- ;; Some defaults
- ;;my-comm ()
- ;;my-icon ()
- (defvar my-name nil)
- (defvar my-disp nil)
- (defvar my-term nil)
- (defvar my-exec nil)
- (defvar my-cat nil)
- (defvar file-line nil)
+ (defvar this-line nil)
(defvar *loc-menu* nil)
(make-variable-special 'apps-menu)
+ ;; fdo-desktop-file-parsing
+
+ (defun desktop-file-p (directory-file)
+ (let ((this-file (open-file directory-file 'read)))
+ (string= (read-line this-file) "[Desktop Entry]\012")))
+
+ (defun desktop-group-p (instring)
+ (string= (substring instring 0 1) "["))
+
+ (defun desktop-skip-line-p (instring)
+ (or (not instring)
+ (string= (substring instring 0 1) "#")
+ (string= (substring instring 0 1) "\012")))
+
+ (defun get-key-break (instring key)
+ (if instring
+ (do ((mcount 0 (1+ mcount)))
+ ((or (string= (substring instring mcount (+ mcount 1)) "\n")
+ (string= (substring instring mcount (+ mcount 1)) key)
+ (= mcount 398)) mcount))))
+
+ (defun get-desktop-key (instring)
+ (if (> (length instring) 3)
+ (let ((break-number (get-key-break instring "=")))
+ (if (< break-number 20)
+ (substring instring 0 break-number)))))
+
+ (defun get-desktop-value (instring)
+ (if (> (length instring) 3)
+ (let ((break-number (get-key-break instring "=")))
+ (if (< break-number 20)
+ (substring instring (+ 1 break-number))))))
+
+ (defun get-desktop-group (instring)
+ (substring instring 1 (- (length instring) 2)))
+
+ (defun parse-desktop-file-line (infile)
+ (if (setq this-line (read-line infile))
+ (if (not (desktop-skip-line-p this-line))
+ (cons
+ (if (desktop-group-p this-line)
+ (get-desktop-group this-line)
+ (if (not (desktop-group-p this-line))
+ (cons (get-desktop-key this-line) (get-desktop-value this-line))))
+ (parse-desktop-file-line infile))
+ (parse-desktop-file-line infile))))
+
+ (defun parse-desktop-file (infile)
+ (unless (not (desktop-file-p infile))
+ (let ((d-file (open-file infile 'read)))
+ (parse-desktop-file-line d-file))))
+
+ ;; generic functions
+
(defun map-desk-files (in-desk-files in-directory)
(if in-desk-files
(cons (expand-file-name (car in-desk-files) in-directory)
(map-desk-files (cdr in-desk-files) in-directory))))
-
+
(defun map-dir-files (directories)
(if directories
(if (file-directory-p (car directories))
(let ((desk0 (directory-files (car directories))))
- (cons (map-desk-files desk0 (car directories))
+ (cons (map-desk-files desk0 (car directories))
(map-dir-files (cdr directories))))
(map-dir-files (cdr directories)))))
@@ -114,91 +104,106 @@ Make sure the mk-saw-menu.jl is in your load path
((atom input) (list input))
(t (append (flatten (car input))
(flatten (cdr input))))))
+
+ (defun trim-end (string)
+ (cond
+ ((string= (aref string (- (length string) 3)) 37)
+ (substring string 0 (- (length string) 4)))
+ (string
+ (substring string 0 (- (length string) 1)))))
(defun find-lang-string ()
- (if (getenv "LANG")
- (if (> (length (getenv "LANG")) 2)
- (substring (getenv "LANG") 0 5)
- (substring (getenv "LANG") 0 2))
- '()))
-
- ;; Variables that can be set in .sawfish[/]rc
- (unless (variable-customized-p 'desktop-directory)
+ (cond
+ ((getenv "LANGUAGE")
+ (let ((mlang (getenv "LANGUAGE")))
+ (if (> (length mlang) 2)
+ (substring mlang 0 5)
+ (substring mlang 0 2))))
+ ((getenv "LC_ALL")
+ (let ((mlang (getenv "LC_ALL")))
+ (if (> (length mlang) 2)
+ (substring mlang 0 5)
+ (substring mlang 0 2))))
+ ((getenv "LC_MESSAGES")
+ (let ((mlang (getenv "LC_MESSAGES")))
+ (if (> (length mlang) 2)
+ (substring mlang 0 5)
+ (substring mlang 0 2))))
+ ((getenv "LANG")
+ (let ((mlang (getenv "LANG")))
+ (if (> (length mlang) 2)
+ (substring mlang 0 5)
+ (substring mlang 0 2))))))
+
+ ;; Variables that can be set in .sawfish[/]rc
+
+ (if (not (boundp 'desktop-directory))
(defvar desktop-directory '("/usr/share/applications")))
-
- (unless (variable-customized-p 'my-lang-string)
+
+ (if (not (boundp 'my-lang-string))
(defvar my-lang-string (find-lang-string)))
(if my-lang-string
- (define name-string "Name[")
- (defvar name-string "Name="))
+ (defvar name-string "Name["))
- (unless (variable-customized-p 'ignore-no-display)
+ (if (not (boundp 'ignore-no-display))
(defvar ignore-no-display '()))
- (unless (variable-customized-p 'want-alphabetize)
+ (if (not (boundp 'want-alphabetize))
(defvar want-alphabetize 't))
- (unless (variable-customized-p 'my-term-string)
+ (if (not (boundp 'my-term-string))
(defvar my-term-string "xterm -e "))
- (unless (variable-customized-p 'use-fdo-menu)
+ (if (not (boundp 'use-fdo-menu))
(defvar use-fdo-menu 't))
;; The Master Category List
- (defvar menu-cat-alist
- '(("Desktop" . ("X-Desktop" "X-DesktopApplets" "X-DesktopCountry" \
- "DesktopSettings" "GNOME" "KDE" "X-GNOME-PersonalSettings" \
- "X-Xfce-Toplevel"))
- ("Personal" . ("X-Personal" "X-PersonalUtility" "Calendar" "ContactManagement"))
- ("Office" . ("Office" "WordProcessor" "Presentation" "X-Document" \
- "TextEditor" "SpreadSheet" "Calculator" "X-Calculate" \
- "Chart" "FlowChart" "Finance"))
- ("Internet" . ("Telephony" "Network" "Dialup" "VideoConference" \
- "RemoteAccess" "News" "HamRadio" "FileTransfer" \
- "X-Internet" "P2P" "Email" "WebBrowser" "IRCClient" "Chat" \
- "InstantMessaging" "Chat" "WebDevelopment"))
- ("Games" . ("Game" "ActionGame" "AdventureGame" "ArcadeGame" "BoardGame" "Emulator"\
- "BlocksGame" "CardGame" "KidsGame" "LogicGame" "RolePlaying" "Simulation"))
- ("Graphics" . ("RasterGraphics" "VectorGraphics" "X-GraphicUtility" \
- "2DGraphics" "3dGraphics" "3DGraphics" "Scanning" "OCR" "Photography" \
- "Viewer" "Publishing" "Art" "ImageProcessing"))
- ("Media" . ("AudioVideo" "Audio", "Video" "Midi" "Mixer" "Sequencer" "Tuner" \
- "TV" "AudioVideoEditing" "Player" "Recorder" "DiscBurning" "Music"))
- ("Science" . ("Science" "Astrology" "ArtificialIntelligence" "Astronomy" \
- "Biology" "Chemistry" "ComputerScience" "DataVisualization" \
- "Electricity" "Robotics" "Physics" "Math" "Education" "Geography"))
- ("Development" . ("GUIDesigner" "IDE" "Profiling" "RevisionControl" \
- "ProjectManagement" "Translation" "GTK" "Development" \
- "Qt" "Development" "Documentation"))
- ("Utility" . ("X-SystemMemory" "Security" "Utility" \
- "X-SetupEntry" "X-SetupUtility" "X-SystemMemory" \
- "TextTools" "TelephonyTools" "Accessibility" "Clock" \
- "ConsoleOnly"))
- ("Filesystem" . ("X-FileSystemFind" "X-FileSystemUtility" "Archiving" \
- "FileManager" "X-FileSystemMount" "Compression"))
- ("System" . ("X-SystemSchedule" "System" "X-SystemMemory" \
- "TerminalEmulator" "Dictionary" "Puppy" "Printing" "Monitor" "Security"))
- ("Settings" . ("Settings" "HardwareSettings" "PackageManager"))))
-
- ;; Some file-verifiers
- (defun desktop-file-p (directory-file)
- (let ((this-file (open-file directory-file 'read)))
- (let ((this-line (read-line this-file)))
- (string= this-line "[Desktop Entry]\012"))))
-
- (defun backup-file-p (input-file-name)
- (or (string= "~" (substring input-file-name (- (length input-file-name) 1)))
- (string= "#" (substring input-file-name 0 1))))
- ;; Helper for (parse-desk-line) - specifically, for categories.
- ;; line must be excluding the categories= part -> (substring line 11)
- (defun build-cat-list (line)
- (if (> (length line) 1)
- (let ((this-cat (prin1-to-string (read-from-string line))))
- (cons this-cat (build-cat-list (substring line (+ 1 (length this-cat))))))))
-
- ;; Helper function for (fix-cats)
+ (defvar menu-cat-alist
+ '(("Desktop" . ("X-Desktop" "X-DesktopApplets" "X-DesktopCountry" \
+ "DesktopSettings" "GNOME" "KDE" "X-GNOME-PersonalSettings" \
+ "X-Xfce-Toplevel"))
+ ("Personal" . ("X-Personal" "X-PersonalUtility" "Calendar" "ContactManagement"))
+ ("Office" . ("Office" "WordProcessor" "Presentation" "X-Document" \
+ "TextEditor" "SpreadSheet" "Calculator" "X-Calculate" \
+ "Chart" "FlowChart" "Finance"))
+ ("Internet" . ("Telephony" "Network" "Dialup" "VideoConference" \
+ "RemoteAccess" "News" "HamRadio" "FileTransfer" \
+ "X-Internet" "P2P" "Email" "WebBrowser" "IRCClient" "Chat" \
+ "InstantMessaging" "Chat" "WebDevelopment"))
+ ("Games" . ("Game" "ActionGame" "AdventureGame" "ArcadeGame" "BoardGame" "Emulator"\
+ "BlocksGame" "CardGame" "KidsGame" "LogicGame" "RolePlaying" "Simulation"))
+ ("Graphics" . ("RasterGraphics" "VectorGraphics" "X-GraphicUtility" \
+ "2DGraphics" "3dGraphics" "3DGraphics" "Scanning" "OCR" "Photography" \
+ "Viewer" "Publishing" "Art" "ImageProcessing"))
+ ("Media" . ("AudioVideo" "Audio", "Video" "Midi" "Mixer" "Sequencer" "Tuner" \
+ "TV" "AudioVideoEditing" "Player" "Recorder" "DiscBurning" "Music"))
+ ("Science" . ("Science" "Astrology" "ArtificialIntelligence" "Astronomy" \
+ "Biology" "Chemistry" "ComputerScience" "DataVisualization" \
+ "Electricity" "Robotics" "Physics" "Math" "Education" "Geography"))
+ ("Development" . ("GUIDesigner" "IDE" "Profiling" "RevisionControl" \
+ "ProjectManagement" "Translation" "GTK" "Development" \
+ "Qt" "Development" "Documentation"))
+ ("Utility" . ("X-SystemMemory" "Security" "Utility" \
+ "X-SetupEntry" "X-SetupUtility" "X-SystemMemory" \
+ "TextTools" "TelephonyTools" "Accessibility" "Clock" \
+ "ConsoleOnly"))
+ ("Filesystem" . ("X-FileSystemFind" "X-FileSystemUtility" "Archiving" \
+ "FileManager" "X-FileSystemMount" "Compression"))
+ ("System" . ("X-SystemSchedule" "System" "X-SystemMemory" \
+ "TerminalEmulator" "Dictionary" "Puppy" "Printing" "Monitor" "Security"))
+ ("Settings" . ("Settings" "HardwareSettings" "PackageManager"))))
+
+ ;; Get the correct Name value based on language settings
+ (defun find-lang-in-desktop-file (fdo-list)
+ (if (assoc (concat name-string my-lang-string "]") fdo-list)
+ (concat name-string my-lang-string "]")
+ (if (assoc (concat name-string (substring my-lang-string 0 2) "]") fdo-list)
+ (concat name-string (substring my-lang-string 0 2) "]")
+ "Name")))
+
+ ;; Functions for categories
(defun fix-sub-cats (cat-list loc-list)
(if cat-list
(let ((cat-val (car cat-list)))
@@ -207,11 +212,7 @@ Make sure the mk-saw-menu.jl is in your load path
(fix-sub-cats cat-list (remove (assoc cat-val loc-list) loc-list)))
(fix-sub-cats (cdr cat-list) loc-list)))))
- ;; Second Part of process, after (parse-desktop-file) has run \
- ;; through and generated the *loc-menu*.
- ;; Will run through the Category alist and assign menu values accordingly, and \
- ;; will output the base of the menu, to \
- ;; be fed into (build-saw-menu)
+ ;; Associate values from the Master Category list with sub-categories from file
(defun fix-cats (cat-list)
(if cat-list
(let ((cat-val (car (car cat-list)))
@@ -220,6 +221,14 @@ Make sure the mk-saw-menu.jl is in your load path
(cons (cons cat-val c-list) (fix-cats (cdr cat-list)))
(fix-cats (cdr cat-list))))))
+ ;; Convert a Categories key value from ; delineated records to a list
+ (defun build-cat-list (line)
+ (if (> (length line) 1)
+ (let ((this-cat (prin1-to-string (read-from-string line))))
+ (cons this-cat
+ (if (< (length this-cat) (length line))
+ (build-cat-list (substring line (+ 1 (length this-cat)))))))))
+
;; Helper for (parse-desk-line)
;; Determine best category to use... :|
(defun parse-cat-list (cat-list)
@@ -233,110 +242,42 @@ Make sure the mk-saw-menu.jl is in your load path
(string= this-cat "X-XFCE")
(string= this-cat "Application"))
(parse-cat-list (cdr cat-list))
- ;; to do specific things for the above entries (uncomment below, \
- ;; and comment out the above (parse-cat-list (cdr cat-list)):
- ;;(let ((dm-specific this-cat))
- ;; (if (or (string= dm-specific "Application")
- ;; (string= dm-specific "Qt")
- ;; (string= dm-specific "GTK"))
- ;; (parse-cat-list (cdr cat-list))
- ;;"Settings"))
this-cat))
(car cat-list)))
- ;; Helper function for (create-menu), which will parse the string input there.
- ;; Will only give an output for specified lines (i.e. category, name, etc.)
- (defun parse-desk-line (line desk-value)
- (let ((line-len (length line)))
- (cond
-
- ;; this section is for the multi-lingual name string
- ((and (> line-len 7)
- my-lang-string
- (string= desk-value (substring line 0 5))
- (string= (substring line 4 5) "[")
- (string= my-lang-string (substring line 5 (+ (length my-lang-string) 5)))
- (string= (substring line (+ (length my-lang-string) 5) (+ (length my-lang-string) 6)) "]"))
- (substring line (+ 4 (length my-lang-string) 3) (- line-len 1)))
-
- ;; this section is for the exec and default name strings
- ((and (> line-len 5)
- (string= (substring desk-value 0 4) (substring line 0 4))
- (string= (substring line 4 5) "="))
- (if (string= (aref line (- line-len 3)) 37)
- (substring line 5 (- line-len 4))
- (substring line 5 (- line-len 1))))
-
- ;; this section is for the category string
- ((and (> line-len 10) (string= desk-value (substring line 0 11)))
- (let ((cat-string (parse-cat-list (build-cat-list (substring line 11)))))
- cat-string))
-
- ;; this section is for the terminal string
- ((and (> line-len 8) (string= desk-value (substring line 0 9)))
- (substring line 9 (- line-len 1)))
-
- ;; this section is for the nodisplay string
- ((and (> line-len 9) (string= desk-value (substring line 0 10)))
- (substring line 10 (- line-len 1))))))
-
- ;; begining of parsing for (parse-desktop-file), feed a .desktop file line into this.
- ;; (create-menu "Name=Emacs ") ==> "Emacs"
- ;; (create-menu "Categories=Development;TextEditor;") ==> "Development"
- (defun create-menu (line)
- (cond
- ((parse-desk-line line "Categories=")
- (setq my-cat (parse-desk-line line "Categories=")))
- ((parse-desk-line line name-string)
- (setq my-name (parse-desk-line line name-string)))
- ;;((parse-desk-line line "Comment=")
- ;; (setq my-comm (parse-desk-line line "Comment=")))
- ;;((parse-desk-line line "Icon=")
- ;; (setq my-icon (parse-desk-line line "Icon=")))
- ((parse-desk-line line "Exec=")
- (setq my-exec (concat (parse-desk-line line "Exec=") " &")))
- ((parse-desk-line line "Terminal=")
- (setq my-term (parse-desk-line line "Terminal=")))
- ((parse-desk-line line "NoDisplay=")
- (setq my-disp (parse-desk-line line "NoDisplay=")))))
-
- ;; Parse a .desktop file into a list suitable for a menu
- ;; ex. (parse-desktop-file "emacs.desktop") ==> ("Development" "Emacs Text Editor" (system "emacs &"))
- (defun parse-desktop-file (desktop-file)
- (let ((desktop-file-name desktop-file))
- (if (and (file-exists-p desktop-file-name)
- (desktop-file-p desktop-file-name)
- (not (file-directory-p desktop-file-name)))
- (let ((new-file (open-file desktop-file-name 'read)))
- (while (setq file-line (read-line new-file))
- (create-menu file-line))
- (if ignore-no-display
- (setq my-disp '()))
- (if (not (string= my-disp "true"))
- (if (not (string= (string-downcase my-term) "true"))
- (cons my-cat (cons my-name (cons (list 'system my-exec) nil)))
- ;;(cons my-cat (cons my-icon (cons my-name (cons my-comm (cons (list 'system my-exec) nil)))))
- (cons my-cat (cons my-name (cons (list 'system (concat my-term-string my-exec)) nil))))
- ;;(cons my-cat (cons my-icon (cons my-name (cons my-comm (cons (list 'system (concat my-term-string my-exec)) nil))))))
- (setq my-disp ()))))))
-
;; Alphabetize the entries in the category menus
(defun alphabetize-entries (saw-menu)
(if saw-menu
- (cons (cons (car (car saw-menu))
- (sort (cdr (car saw-menu)) string<))
+ (cons (cons (car (car saw-menu))
+ (sort (cdr (car saw-menu)) string<))
(alphabetize-entries (cdr saw-menu)))))
- ;; Update the menu and set it to 'apps-menu
+ ;; generate a saw-fish menu entry from a .desktop file
+ (defun generate-menu-entry (desk-file)
+ (if (and (not (file-directory-p desk-file))
+ (desktop-file-p desk-file))
+ (let ((fdo-list (parse-desktop-file desk-file)))
+ (if (not (string= (cdr (assoc "NoDisplay" fdo-list)) "true\n"))
+ (cons (parse-cat-list (build-cat-list (trim-end (cdr (assoc "Categories" fdo-list)))))
+ (cons (trim-end (cdr (assoc (find-lang-in-desktop-file fdo-list) fdo-list)))
+ (if (string= (cdr (assoc "Terminal" fdo-list)) "true\012")
+ (cons (list
+ 'system (concat my-term-string (trim-end (cdr (assoc "Exec" fdo-list))) " &")))
+ (cons (list 'system (concat (trim-end (cdr (assoc "Exec" fdo-list))) " &"))))))))))
+
+ ;; Update the menu
(define (update-saw-menu)
+ (interactive)
(unless (not use-fdo-menu)
(setq *loc-menu* nil)
(defvar desk-files (flatten (map-dir-files desktop-directory)))
(mapc (lambda (x)
- (setq *loc-menu* (append *loc-menu* (list (parse-desktop-file x))))) desk-files)
+ (setq *loc-menu* (append *loc-menu* (list (generate-menu-entry x))))) desk-files)
(if want-alphabetize
(setq apps-menu (alphabetize-entries (fix-cats menu-cat-alist)))
(setq apps-menu (fix-cats menu-cat-alist)))))
(define-command 'update-saw-menu update-saw-menu)
-))
+))
+ ;; END-FILE
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]