[sawfish] Implements SAWFISH_USER_LISP_DIR.



commit 49c6de7e02ba02a67bbd8e07a3768c718c71223d
Author: Teika kazura <teika lavabit com>
Date:   Sat Feb 27 13:16:03 2010 +0900

    Implements SAWFISH_USER_LISP_DIR.
    
    Like PATH, it's colon seperated directories.
    Its value will be prepended to load-path. Now it's possible for users to override any installed lisp files.
    sawfish-config respects it, too.
    Doc.

 lisp/Makefile.in            |    3 +-
 lisp/sawfish/cfg/main.jl.in |   20 +++++++--
 lisp/sawfish/wm.jl          |    8 ++--
 man/news.texi               |   15 +++++++
 man/sawfish.texi            |   12 +++++
 src/main.c                  |   99 +++++++++++++++++++++++++++++++++++++++++--
 src/sawfish_subrs.h         |    3 +-
 themes/Makefile.in          |    3 +-
 8 files changed, 147 insertions(+), 16 deletions(-)
---
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index 015ebd4..d303239 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -31,7 +31,8 @@ REP_ENVIRON:=$(REP_ENVIRON) REP_LOAD_PATH=$(top_srcdir)/lisp:$(top_builddir)/lis
 sawfish_prog = ../src/sawfish --batch --no-rc
 COMPILE_ENV = SAWFISHLISPDIR=. \
 	      SAWFISHEXECDIR=$(top_builddir)/src/.libexec \
-	      SAWFISHDOCFILE=../DOC
+	      SAWFISHDOCFILE=../DOC \
+	      SAWFISH_USER_LISP_DIR=
 
 SAWFISH_LISP_FILES := sawfish/wm.jlc
 SAWFISH_LISP_DIRS := sawfish/wm
diff --git a/lisp/sawfish/cfg/main.jl.in b/lisp/sawfish/cfg/main.jl.in
index c2d7fc2..9836f53 100644
--- a/lisp/sawfish/cfg/main.jl.in
+++ b/lisp/sawfish/cfg/main.jl.in
@@ -34,13 +34,23 @@ exec rep "$0" "$@"
     (open rep
 	  rep.system
 	  rep.io.streams
-	  sawfish.gtk.widget
-	  sawfish.cfg.i18n
-	  sawfish.cfg.shell
-	  sawfish.cfg.group)
-
+	  rep.io.files
+	  rep.regexp)
   (define socket-id nil)
 
+  (when (getenv "SAWFISH_USER_LISP_DIR")
+    (setq load-path
+	  (append
+	   (mapcar canonical-file-name
+		   (string-split ":" (getenv "SAWFISH_USER_LISP_DIR")))
+	   load-path)))
+
+  ;; mapcar fails for compilation 
+  (require 'sawfish.gtk.widget)
+  (require 'sawfish.cfg.i18n)
+  (require 'sawfish.cfg.shell)
+  (require 'sawfish.cfg.group)
+
   (when (get-command-line-option "--help")
     (write standard-output "\
 usage: sawfish-config [OPTIONS...]\n
diff --git a/lisp/sawfish/wm.jl b/lisp/sawfish/wm.jl
index fb7c47b..15ccb8c 100644
--- a/lisp/sawfish/wm.jl
+++ b/lisp/sawfish/wm.jl
@@ -28,6 +28,10 @@
 ;; this will be changed to 'user later
 (setq *user-structure* 'sawfish.wm)
 
+;; Expand tilde for efficiency. Otherwise, tilde file-handler is called
+;; everytime in path search.
+(setq load-path (mapcar canonical-file-name load-path))
+
 ;; load always-present session-manager stuff
 (require 'sawfish.wm.session.init)
 
@@ -60,10 +64,6 @@
 (defmacro i18n-define args (cons 'define args))
 (export-bindings '(i18n-defvar i18n-define))
 
-;; add ~/.sawfish/lisp to load-path for user-code (canonicalize it
-;; now to avoid calling tilde file-handler multiple times)
-(setq load-path (cons (canonical-file-name "~/.sawfish/lisp") load-path))
-
 ;; import libraries that may be needed by autoload files
 (require 'sawfish.wm.commands)
 (require 'sawfish.wm.custom)
diff --git a/man/news.texi b/man/news.texi
index f9d0677..f6f3241 100644
--- a/man/news.texi
+++ b/man/news.texi
@@ -15,6 +15,21 @@ they occurred between. For more detailed information see the
 
 @item The 1.6.3 release has some improvements.
 
+ itemize @minus
+ item Customizable lisp directory [Teika kazura]
+
+User can add lisp directories to be read with the environmental
+variable @code{SAWFISH_USER_LISP_DIR}. Its value is directories
+separated by colon, like @code{PATH}, and prepended to
+ code{load-path}  If not set, @file{~/.sawfish/lisp} is assumed.
+
+User can override system lisp files. For example, if there is
+ file{~/.sawfish/lisp/sawfish/wm/windows.jl}, then it is read as
+ code{sawfish wm windows}, instead of the installed one. In fact, it
+was possible for some lisp files, but now it's guaranteed for all
+files.  Of course, you can define new modules, too.
+
+ end itemize
 @item Other Changes
 @itemize @minus
 @item Then pressing the lock-button also do a state-change of the window
diff --git a/man/sawfish.texi b/man/sawfish.texi
index 5be59c8..2672996 100644
--- a/man/sawfish.texi
+++ b/man/sawfish.texi
@@ -6339,6 +6339,18 @@ example: @code{"/usr/share/sawfish/site-lisp"}. You can override it
 with the environment variable @code{SAWFISHSITELISPDIR}.
 @end defvar
 
+ defvar sawfish-user-lisp-directory
+The list of user's sawfish lisp directories. The default value is
+ code{($HOME/.sawfish/lisp)}. It is prepended to @code{load-path}, so
+that files under these directories are searched prior to
+ code{sawfish-lisp-lib-directory} 
+
+You can override the value with environment variable
+ code{SAWFISH_USER_LISP_DIR}  Paths are seperated by colon, like
+the @code{PATH} environmental variable. Example:
+ code{~/.sawfish/lisp-test:~/.sawfish/lisp}.
+ end defvar
+
 @defun exit-type
 If Sawfish is shutting down, this function returns one of the strings
 @code{"user-quit"}, @code{"user-restart"} or @code{"session-quit"}.
diff --git a/src/main.c b/src/main.c
index 1210748..35a3054 100644
--- a/src/main.c
+++ b/src/main.c
@@ -55,6 +55,7 @@ DEFSYM(sawfish_lisp_lib_directory, "sawfish-lisp-lib-directory");
 DEFSYM(sawfish_site_lisp_directory, "sawfish-site-lisp-directory");
 DEFSYM(sawfish_exec_directory, "sawfish-exec-directory");
 DEFSYM(sawfish_locale_directory, "sawfish-locale-directory");
+DEFSYM(sawfish_user_lisp_directory, "sawfish-user-lisp-directory");
 DEFSYM(sawfish_version, "sawfish-version"); /*
 ::doc:sawfish-directory::
 The directory in which all of sawfish's installed data files live.
@@ -157,10 +158,53 @@ DEFUN ("exit-type", Fexit_type, Sexit_type, (void), rep_Subr0)
     }
 }
 
+static repv split_by_colon(char * str){
+  // Split string at colon, and return lisp list of the strings.
+  repv * elm;
+  repv val;
+  int length, i, from, elm_ind;
+
+  length = 1;
+  i = 0;
+  // first, scan how many colons are there
+  while (str[i] != 0){
+    if(str[i] == ':'){
+      length++;
+    }
+    i++;
+  }
+  // well, sawfish doesn't check malloc failure...
+  elm = (repv *) malloc(sizeof(repv) * length);
+
+  from = 0; i = 0; elm_ind = 0;
+  while(1){
+    if((str[i] == ':') || (str[i] == 0)){
+      if(from < i){
+	// Add it only when non-zero
+	elm[elm_ind] = rep_string_dupn(str + from, i - from);
+	elm_ind++;
+      }
+      from = i + 1;
+    }
+    if(str[i] == 0){
+      break;
+    }
+    i++;
+  }
+
+  // Flist isn't exported...
+  val = Qnil;
+  for(elm_ind--; elm_ind >= 0; elm_ind--){
+    val = Fcons(elm[elm_ind], val);
+  }
+  free(elm);
+  return val;
+}
+
 static void
 sawfish_symbols (void)
 {
-    repv tem;
+    repv tem, tem2;
 
     rep_INTERN_SPECIAL(sawfish_directory);
     if(getenv("SAWFISHDIR") != 0)
@@ -211,9 +255,56 @@ sawfish_symbols (void)
     Fset (Qdocumentation_files, Fcons(Fsymbol_value (Qdocumentation_file, Qt),
 				      Fsymbol_value (Qdocumentation_files, Qt)));
 
-    Fset (Qload_path, Fcons (Fsymbol_value (Qsawfish_lisp_lib_directory, Qt),
-			     Fcons (Fsymbol_value (Qsawfish_site_lisp_directory, Qt),
-				    Fsymbol_value (Qload_path, Qt))));
+    rep_INTERN_SPECIAL(sawfish_user_lisp_directory);
+
+    if(getenv("SAWFISH_USER_LISP_DIR") != 0){
+      Fset(Qsawfish_user_lisp_directory,
+	   split_by_colon(getenv("SAWFISH_USER_LISP_DIR")));
+    }
+    else{
+      Fset(Qsawfish_user_lisp_directory,
+	   split_by_colon("~/.sawfish/lisp"));
+    }
+
+    /* in lisp,
+       (setq load-path
+             (append sawfish-user-lisp-directory
+                     (list sawfish-lisp-lib-directory
+		           sawfish-site-lisp-directory)
+		     load-path)) */
+
+    /* rep_copy_list is not exported...
+       tem =
+         rep_copy_list(Fsymbol_value(Qsawfish_user_lisp_directory, Qt));
+    */
+
+    if(getenv("SAWFISH_USER_LISP_DIR") != 0){
+      tem = split_by_colon(getenv("SAWFISH_USER_LISP_DIR"));
+    }
+    else{
+      tem = split_by_colon("~/.sawfish/lisp");
+    }
+
+    // tem2 will point to load-path
+    if(tem != Qnil){
+      tem2 = tem;
+
+      while(rep_CDR(tem) != Qnil){
+	tem = rep_CDR(tem);
+      }
+      rep_CDR(tem) = Fcons(Fsymbol_value(Qsawfish_lisp_lib_directory, Qt),
+			   Qnil);
+      tem = rep_CDR(tem);
+    }else{
+      tem = Fcons(Fsymbol_value(Qsawfish_lisp_lib_directory, Qt),
+		  Qnil);
+      tem2 = tem;
+    }
+    rep_CDR(tem) = Fcons(Fsymbol_value(Qsawfish_site_lisp_directory, Qt),
+			 Qnil);
+    tem = rep_CDR(tem);
+    rep_CDR(tem) = Fsymbol_value(Qload_path, Qt);
+    Fset(Qload_path, tem2);
 
     Fset (Qdl_load_path, Fcons (Fsymbol_value (Qsawfish_exec_directory, Qt),
 				Fsymbol_value (Qdl_load_path, Qt)));
diff --git a/src/sawfish_subrs.h b/src/sawfish_subrs.h
index f9639ca..2f4dd8e 100644
--- a/src/sawfish_subrs.h
+++ b/src/sawfish_subrs.h
@@ -252,7 +252,8 @@ extern void keys_init (void);
 /* from main.c */
 extern int exit_code;
 extern repv Qsawfish_directory, Qsawfish_lisp_lib_directory,
-    Qsawfish_site_lisp_directory, Qsawfish_exec_directory;
+      Qsawfish_site_lisp_directory, Qsawfish_exec_directory,
+      Qsawfish_user_lisp_directory;
 extern repv Qwindow_error, Qinvalid_pos, Qbad_event_desc;
 extern repv Qbefore_exit_hook, Qfonts_are_fontsets;
 extern bool batch_mode_p (void);
diff --git a/themes/Makefile.in b/themes/Makefile.in
index 0750021..bb9e624 100644
--- a/themes/Makefile.in
+++ b/themes/Makefile.in
@@ -34,7 +34,8 @@ sawfish_prog = $(rep_LIBTOOL) --mode=execute -dlopen ../src/gradient.la \
 		../src/sawfish --batch --no-rc
 COMPILE_ENV = SAWFISHLISPDIR=../lisp \
 	      SAWFISHEXECDIR=$(top_builddir)/src/.libs \
-	      SAWFISHDOCFILE=../DOC
+	      SAWFISHDOCFILE=../DOC \
+	      SAWFISH_USER_LISP_DIR=
 
 THEMES := absolute-e Crux brushed-metal gradient gtk microGUI mono simple smaker get-S-tabbed mxflat Elberg-tabbed
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]