Hello,

Currently the 'lispwords' setting is global, yet three filetypes attempt
to change it on filetype/indent load: scheme, clojure, and art.

Scheme and Clojure, in particular, are two very different Lisp variants,
but both modify 'lispwords' to influence their indenting. Both filetypes
also call `setlocal lispwords<` in undo hooks to unset the local value
of the setting, but of course, this does not work.

The following attached patches make the 'lispwords' setting global-local
to allow different Lisps to use this setting concurrently:

[PATCH 1/3]
    Changes the scope of 'lispwords'.

[PATCH 2/3]
    Adds a simple test, appended to test100 (hope that's okay; it was
    the only existing test that obviously involved global-local scope).

[PATCH 3/3]
    Corrects a bug in the Clojure runtime files regarding its handling
    of 'lispwords'.

    Also moves the 'lispwords' setting from the indent script to the
    ftplugin script to mirror the Scheme filetype.

I do not foresee any backwards compatibility issues in these changes,
especially since the only two scripts that reference 'lispwords'
evidently assume that the option is already global-local.

    Cheers,
    Sung Pae
From 2eb58caa0f2f189e09ca55100eea8a707200f56e Mon Sep 17 00:00:00 2001
From: guns <[email protected]>
Date: Sun, 16 Feb 2014 00:33:03 -0600
Subject: [PATCH 1/3] Make 'lispwords' a global-local option

Multiple filetypes cannot currently use different values of 'lispwords',
even though it makes sense to have multiple values of this setting for
different lisps.

The scheme, clojure, and art filetypes currently set local values of
'lispwords', then reset them with 'setlocal lispwords<' in an undo hook.

This patch makes this actually work.
---
 runtime/doc/options.txt |  2 +-
 runtime/optwin.vim      |  2 +-
 src/buffer.c            |  3 +++
 src/misc1.c             |  2 +-
 src/option.c            | 21 ++++++++++++++++++++-
 src/option.h            |  1 +
 src/structs.h           |  3 +++
 7 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 95e0950..ea15161 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4629,7 +4629,7 @@ A jump table for the options with a short description can be found at |Q_op|.
 
 						*'lispwords'* *'lw'*
 'lispwords' 'lw'	string	(default is very long)
-			global
+			global or local to buffer |global-local|
 			{not in Vi}
 			{not available when compiled without the |+lispindent|
 			feature}
diff --git a/runtime/optwin.vim b/runtime/optwin.vim
index df36883..89ebe26 100644
--- a/runtime/optwin.vim
+++ b/runtime/optwin.vim
@@ -855,7 +855,7 @@ if has("lispindent")
   call append("$", "\t(local to buffer)")
   call <SID>BinOptionL("lisp")
   call append("$", "lispwords\twords that change how lisp indenting works")
-  call <SID>OptionG("lw", &lw)
+  call <SID>OptionL("lw", &lw)
 endif
 
 
diff --git a/src/buffer.c b/src/buffer.c
index 4eaf3db..d686467 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1978,6 +1978,9 @@ free_buf_options(buf, free_p_ff)
 #endif
     buf->b_p_ar = -1;
     buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
+#ifdef FEAT_LISP
+    clear_string_option(&buf->b_p_lw);
+#endif
 }
 
 /*
diff --git a/src/misc1.c b/src/misc1.c
index b258d0b..9434961 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -8879,7 +8879,7 @@ lisp_match(p)
 {
     char_u	buf[LSIZE];
     int		len;
-    char_u	*word = p_lispwords;
+    char_u	*word = *curbuf->b_p_lw != NUL ? curbuf->b_p_lw : p_lispwords;
 
     while (*word != NUL)
     {
diff --git a/src/option.c b/src/option.c
index 8c72da6..b1c888d 100644
--- a/src/option.c
+++ b/src/option.c
@@ -134,6 +134,7 @@
 #define PV_KP		OPT_BOTH(OPT_BUF(BV_KP))
 #ifdef FEAT_LISP
 # define PV_LISP	OPT_BUF(BV_LISP)
+# define PV_LW		OPT_BOTH(OPT_BUF(BV_LW))
 #endif
 #define PV_MA		OPT_BUF(BV_MA)
 #define PV_ML		OPT_BUF(BV_ML)
@@ -1718,7 +1719,7 @@ static struct vimoption
 			    {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
     {"lispwords",   "lw",   P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
 #ifdef FEAT_LISP
-			    (char_u *)&p_lispwords, PV_NONE,
+			    (char_u *)&p_lispwords, PV_LW,
 			    {(char_u *)LISPWORD_VALUE, (char_u *)0L}
 #else
 			    (char_u *)NULL, PV_NONE,
@@ -5412,6 +5413,9 @@ check_buf_options(buf)
     check_string_option(&buf->b_p_dict);
     check_string_option(&buf->b_p_tsr);
 #endif
+#ifdef FEAT_LISP
+    check_string_option(&buf->b_p_lw);
+#endif
 }
 
 /*
@@ -9879,6 +9883,11 @@ unset_global_local_option(name, from)
 	case PV_UL:
 	    buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
 	    break;
+#ifdef FEAT_LISP
+	case PV_LW:
+	    clear_string_option(&buf->b_p_lw);
+	    break;
+#endif
     }
 }
 
@@ -9928,6 +9937,9 @@ get_varp_scope(p, opt_flags)
 	    case PV_STL:  return (char_u *)&(curwin->w_p_stl);
 #endif
 	    case PV_UL:   return (char_u *)&(curbuf->b_p_ul);
+#ifdef FEAT_LISP
+	    case PV_LW:   return (char_u *)&(curbuf->b_p_lw);
+#endif
 	}
 	return NULL; /* "cannot happen" */
     }
@@ -9994,6 +10006,10 @@ get_varp(p)
 #endif
 	case PV_UL:	return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL
 				    ? (char_u *)&(curbuf->b_p_ul) : p->var;
+#ifdef FEAT_LISP
+	case PV_LW:	return *curbuf->b_p_lw != NUL
+				    ? (char_u *)&(curbuf->b_p_lw) : p->var;
+#endif
 
 #ifdef FEAT_ARABIC
 	case PV_ARAB:	return (char_u *)&(curwin->w_p_arab);
@@ -10567,6 +10583,9 @@ buf_copy_options(buf, flags)
 #ifdef FEAT_PERSISTENT_UNDO
 	    buf->b_p_udf = p_udf;
 #endif
+#ifdef FEAT_LISP
+	    buf->b_p_lw = empty_option;
+#endif
 
 	    /*
 	     * Don't copy the options set by ex_help(), use the saved values,
diff --git a/src/option.h b/src/option.h
index ce2dd00..5144c33 100644
--- a/src/option.h
+++ b/src/option.h
@@ -990,6 +990,7 @@ enum
     , BV_KP
 #ifdef FEAT_LISP
     , BV_LISP
+    , BV_LW
 #endif
     , BV_MA
     , BV_ML
diff --git a/src/structs.h b/src/structs.h
index c3f0312..d5b654c 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1640,6 +1640,9 @@ struct file_buffer
 #ifdef FEAT_PERSISTENT_UNDO
     int		b_p_udf;	/* 'undofile' */
 #endif
+#ifdef FEAT_LISP
+    char_u	*b_p_lw;	/* 'lispwords' local value */
+#endif
 
     /* end of buffer options */
 
-- 
1.9.0

From 824bc13447a20e436787061115936a508e7a172a Mon Sep 17 00:00:00 2001
From: guns <[email protected]>
Date: Sun, 16 Feb 2014 02:20:44 -0600
Subject: [PATCH 2/3] Add test for 'lispwords' global-local scope

---
 src/testdir/test100.in | 10 +++++++++-
 src/testdir/test100.ok | 10 ++++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/src/testdir/test100.in b/src/testdir/test100.in
index e423319..61d28c1 100644
--- a/src/testdir/test100.in
+++ b/src/testdir/test100.in
@@ -1,4 +1,4 @@
-Tests for 'undolevel' setting being global-local
+Tests for 'undolevel' and 'lispwords' settings being global-local
 
 STARTTEST
 :so small.vim
@@ -37,6 +37,14 @@ STARTTEST
 :call UndoLevel()
 :%w >> test.out
 :"sleep 10
+:"
+:" Testing 'lispwords'
+:"
+:setglobal lispwords=foo,bar,baz
+:setlocal lispwords-=foo | setlocal lispwords+=quux
+:redir >> test.out | echon "\nTesting 'lispwords' local value" | setglobal lispwords? | setlocal lispwords? | echo &lispwords . "\n" | redir end
+:setlocal lispwords<
+:redir >> test.out | echon "\nTesting 'lispwords' value reset" | setglobal lispwords? | setlocal lispwords? | echo &lispwords . "\n" | redir end
 :qa!
 ENDTEST
 
diff --git a/src/testdir/test100.ok b/src/testdir/test100.ok
index 95b3184..477106b 100644
--- a/src/testdir/test100.ok
+++ b/src/testdir/test100.ok
@@ -39,3 +39,13 @@ THREE: expecting global undolevels: 50, local undolevels: -123456 (default)
 
   undolevels=50 global
   undolevels=-123456 local
+
+Testing 'lispwords' local value
+  lispwords=foo,bar,baz
+  lispwords=bar,baz,quux
+bar,baz,quux
+
+Testing 'lispwords' value reset
+  lispwords=foo,bar,baz
+  lispwords=foo,bar,baz
+foo,bar,baz
-- 
1.9.0

From ff13adb305ec78a6e436018a3ef893b5c120a5b5 Mon Sep 17 00:00:00 2001
From: guns <[email protected]>
Date: Sun, 16 Feb 2014 03:49:46 -0600
Subject: [PATCH 3/3] Change 'lispwords' in Clojure filetype for new
 global-local scope

- 'lispwords' is moved to the ftplugin file from the indent file to
  mirror the Scheme filetype

- The value is now assigned on one line, instead of attempting to blank
  the setting with `setlocal lispwords=`, which is now tantamount to
  `setlocal lispwords<`
---
 runtime/ftplugin/clojure.vim | 19 ++++++++--
 runtime/indent/clojure.vim   | 83 ++------------------------------------------
 2 files changed, 19 insertions(+), 83 deletions(-)

diff --git a/runtime/ftplugin/clojure.vim b/runtime/ftplugin/clojure.vim
index 2b935a5..8a89877 100644
--- a/runtime/ftplugin/clojure.vim
+++ b/runtime/ftplugin/clojure.vim
@@ -5,7 +5,7 @@
 " Maintainer:	Sung Pae <[email protected]>
 " URL:		https://github.com/guns/vim-clojure-static
 " License:	Same as Vim
-" Last Change:	08 September 2013
+" Last Change:	16 February 2014
 
 if exists("b:did_ftplugin")
 	finish
@@ -15,7 +15,7 @@ let b:did_ftplugin = 1
 let s:cpo_save = &cpo
 set cpo&vim
 
-let b:undo_ftplugin = 'setlocal iskeyword< define< formatoptions< comments< commentstring<'
+let b:undo_ftplugin = 'setlocal iskeyword< define< formatoptions< comments< commentstring< lispwords<'
 
 setlocal iskeyword+=?,-,*,!,+,/,=,<,>,.,:,$
 
@@ -31,6 +31,21 @@ setlocal formatoptions-=t formatoptions+=croql
 setlocal comments=n:;
 setlocal commentstring=;\ %s
 
+" Specially indented symbols from clojure.core and clojure.test.
+"
+" Clojure symbols are indented in the defn style when they:
+"
+"   * Define vars and anonymous functions
+"   * Create new lexical scopes or scopes with altered environments
+"   * Create conditional branches from a predicate function or value
+"
+" The arglists for these functions are generally in the form of [x & body];
+" Functions that accept a flat list of forms do not treat the first argument
+" specially and hence are not indented specially.
+"
+" Generated from https://github.com/guns/vim-clojure-static/blob/vim-release-009/clj/src/vim_clojure_static/generate.clj
+setlocal lispwords=as->,binding,bound-fn,case,catch,cond->,cond->>,condp,def,definline,definterface,defmacro,defmethod,defmulti,defn,defn-,defonce,defprotocol,defrecord,defstruct,deftest,deftest-,deftype,doall,dorun,doseq,dotimes,doto,extend,extend-protocol,extend-type,fn,for,if,if-let,if-not,let,letfn,locking,loop,ns,proxy,reify,set-test,testing,when,when-first,when-let,when-not,while,with-bindings,with-in-str,with-local-vars,with-open,with-precision,with-redefs,with-redefs-fn,with-test
+
 " Provide insert mode completions for special forms and clojure.core. As
 " 'omnifunc' is set by popular Clojure REPL client plugins, we also set
 " 'completefunc' so that the user has some form of completion available when
diff --git a/runtime/indent/clojure.vim b/runtime/indent/clojure.vim
index df88cea..64f1333 100644
--- a/runtime/indent/clojure.vim
+++ b/runtime/indent/clojure.vim
@@ -6,7 +6,7 @@
 " Maintainer:	Sung Pae <[email protected]>
 " URL:		https://github.com/guns/vim-clojure-static
 " License:	Same as Vim
-" Last Change:	16 December 2013
+" Last Change:	16 February 2014
 
 " TODO: Indenting after multibyte characters is broken:
 "       (let [Δ (if foo
@@ -21,7 +21,7 @@ let b:did_indent = 1
 let s:save_cpo = &cpo
 set cpo&vim
 
-let b:undo_indent = 'setlocal autoindent< smartindent< lispwords< expandtab< softtabstop< shiftwidth< indentexpr< indentkeys<'
+let b:undo_indent = 'setlocal autoindent< smartindent< expandtab< softtabstop< shiftwidth< indentexpr< indentkeys<'
 
 setlocal noautoindent nosmartindent
 setlocal softtabstop=2 shiftwidth=2 expandtab
@@ -307,85 +307,6 @@ else
 
 endif
 
-" Specially indented symbols from clojure.core and clojure.test.
-"
-" Clojure symbols are indented in the defn style when they:
-"
-"   * Define vars and anonymous functions
-"   * Create new lexical scopes or scopes with altered environments
-"   * Create conditional branches from a predicate function or value
-"
-" The arglists for these functions are generally in the form of [x & body];
-" Functions that accept a flat list of forms do not treat the first argument
-" specially and hence are not indented specially.
-
-" Definitions
-setlocal lispwords=
-setlocal lispwords+=bound-fn
-setlocal lispwords+=def
-setlocal lispwords+=definline
-setlocal lispwords+=definterface
-setlocal lispwords+=defmacro
-setlocal lispwords+=defmethod
-setlocal lispwords+=defmulti
-setlocal lispwords+=defn
-setlocal lispwords+=defn-
-setlocal lispwords+=defonce
-setlocal lispwords+=defprotocol
-setlocal lispwords+=defrecord
-setlocal lispwords+=defstruct
-setlocal lispwords+=deftest " clojure.test
-setlocal lispwords+=deftest- " clojure.test
-setlocal lispwords+=deftype
-setlocal lispwords+=extend
-setlocal lispwords+=extend-protocol
-setlocal lispwords+=extend-type
-setlocal lispwords+=fn
-setlocal lispwords+=ns
-setlocal lispwords+=proxy
-setlocal lispwords+=reify
-setlocal lispwords+=set-test " clojure.test
-
-" Binding forms
-setlocal lispwords+=as->
-setlocal lispwords+=binding
-setlocal lispwords+=doall
-setlocal lispwords+=dorun
-setlocal lispwords+=doseq
-setlocal lispwords+=dotimes
-setlocal lispwords+=doto
-setlocal lispwords+=for
-setlocal lispwords+=if-let
-setlocal lispwords+=let
-setlocal lispwords+=letfn
-setlocal lispwords+=locking
-setlocal lispwords+=loop
-setlocal lispwords+=testing " clojure.test
-setlocal lispwords+=when-first
-setlocal lispwords+=when-let
-setlocal lispwords+=with-bindings
-setlocal lispwords+=with-in-str
-setlocal lispwords+=with-local-vars
-setlocal lispwords+=with-open
-setlocal lispwords+=with-precision
-setlocal lispwords+=with-redefs
-setlocal lispwords+=with-redefs-fn
-setlocal lispwords+=with-test " clojure.test
-
-" Conditional branching
-setlocal lispwords+=case
-setlocal lispwords+=cond->
-setlocal lispwords+=cond->>
-setlocal lispwords+=condp
-setlocal lispwords+=if
-setlocal lispwords+=if-not
-setlocal lispwords+=when
-setlocal lispwords+=when-not
-setlocal lispwords+=while
-
-" Exception handling
-setlocal lispwords+=catch
-
 let &cpo = s:save_cpo
 unlet! s:save_cpo
 
-- 
1.9.0

Attachment: pgpjtjVU4yQH5.pgp
Description: PGP signature

Raspunde prin e-mail lui