[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] $EDITOR with spaces, take two

From: Daniel Stenberg <daniel_at_haxx.se>
Date: 2002-04-18 14:23:49 CEST

Well

I can't say that I've felt any consensus in this subject yet, but here's
another shot at providing a patch that makes it possible to have "emacs -nw"
in the $EDITOR. This patch supports escaped spaces like "\ " for commands or
whatever that needs an actual space.

Feel free to tear it apart.

* subversion/clients/cmdline/cl.h

 (svn_cl__escaped_string_to_array) added proto

* subversion/clients/cmdline/util.c

 (svn_cl__edit_externally) added magic to deal with EDITOR strings that
 contain spaces/options. Removed old command building sprintf().

 (is_unescaped_space) new tiny static function

 (store_buffer_unescaped) unscapes a string into a stringbuf

 (svn_cl__escaped_string_to_array) convert a string into an array, deal
 with escaped spaces to treat them as part of the strings and not as
 separators. I made this an "external" symbol, but I'm not sure it needs
 to be.

Index: ./subversion/clients/cmdline/cl.h
===================================================================
--- ./subversion/clients/cmdline/cl.h
+++ ./subversion/clients/cmdline/cl.h Thu Apr 18 14:14:34 2002
@@ -190,6 +190,11 @@
 apr_array_header_t*
 svn_cl__stringlist_to_array (svn_stringbuf_t *buffer, apr_pool_t *pool);

+/* Convert a whitespace separated list of items into an apr_array_header_t.
+ Acknowledge escaped spaces. */
+apr_array_header_t*
+svn_cl__escaped_string_to_array(svn_stringbuf_t *buffer, apr_pool_t *pool);
+
 /* Splits a list of newline seperated values into an apr_array_header_t */
 apr_array_header_t*
 svn_cl__newlinelist_to_array (svn_stringbuf_t *buffer, apr_pool_t *pool);
Index: ./subversion/clients/cmdline/util.c
===================================================================
--- ./subversion/clients/cmdline/util.c
+++ ./subversion/clients/cmdline/util.c Thu Apr 18 09:57:30 2002
@@ -277,6 +277,72 @@
   return targets;
 }

+/* return true if the data[index] refers to an unscaped space */
+static svn_boolean_t
+is_unescaped_space(const char *data,
+ apr_size_t start)
+{
+ svn_boolean_t space = apr_isspace (data[start]);
+ if (space && (start > 0))
+ {
+ return data[start-1]=='\\'?FALSE:TRUE;
+ }
+ return space;
+}
+
+static svn_stringbuf_t *
+store_buffer_unescaped(const char *buffer,
+ apr_size_t length,
+ apr_pool_t *pool)
+{
+ int i;
+ apr_size_t start=0;
+ svn_stringbuf_t *string = svn_stringbuf_ncreate (NULL, 0, pool);
+
+ for (i=1; i<length; i++)
+ {
+ if (apr_isspace (buffer[i]) && (buffer[i-1] == '\\'))
+ {
+ svn_stringbuf_appendbytes (string, &buffer[start], i - start - 1);
+ start = i;
+ }
+ }
+ svn_stringbuf_appendbytes (string, &buffer[start], i - start);
+
+ return string;
+}
+
+/* Convert a whitespace separated list of items into an apr_array_header_t.
+ Acknowledge escaped spaces. */
+apr_array_header_t*
+svn_cl__escaped_string_to_array(svn_stringbuf_t *buffer, apr_pool_t *pool)
+{
+ apr_array_header_t *array = apr_array_make (pool, DEFAULT_ARRAY_SIZE,
+ sizeof(svn_stringbuf_t *));
+ if (buffer != NULL)
+ {
+ apr_size_t start = 0, end = 0;
+ svn_stringbuf_t *item;
+ while (end < buffer->len)
+ {
+ while (is_unescaped_space (buffer->data, start))
+ start++;
+
+ end = start;
+
+ while (end < buffer->len && !is_unescaped_space (buffer->data, end))
+ end++;
+
+ item = store_buffer_unescaped (&buffer->data[start],
+ end - start, pool);
+ *((svn_stringbuf_t**)apr_array_push(array)) = item;
+
+ start = end;
+ }
+ }
+ return array;
+}
+
 /* Convert a whitespace separated list of items into an apr_array_header_t */
 apr_array_header_t*
 svn_cl__stringlist_to_array(svn_stringbuf_t *buffer, apr_pool_t *pool)
@@ -366,16 +432,19 @@
                          apr_pool_t *pool)
 {
   const char *editor = NULL;
- const char *command = NULL;
+ svn_stringbuf_t *command = NULL;
+ svn_stringbuf_t **cmdstrings;
   apr_file_t *tmp_file;
   svn_stringbuf_t *tmpfile_name;
   apr_status_t apr_err;
   apr_size_t written;
   apr_finfo_t finfo_before, finfo_after;
   svn_error_t *err = SVN_NO_ERROR;
- const char *cmd_args[3] = { 0 };
+ const char **cmd_args;
   int exit_code = 0;
   apr_exit_why_e exit_why;
+ apr_array_header_t *array;
+ int i;

   /* Try to find an editor in the environment. */
   editor = getenv ("SVN_EDITOR");
@@ -422,20 +491,36 @@
       goto cleanup;
     }

- /* Create the editor command line. */
- command = apr_psprintf (pool, "%s %s", editor, tmpfile_name->data);
-
   /* Get information about the temporary file before the user has
      been allowed to edit its contents. */
   apr_stat (&finfo_before, tmpfile_name->data,
             APR_FINFO_MTIME | APR_FINFO_SIZE, pool);

+ /* split the EDITOR varible into an array, we need to do this since the
+ variable may contain spaces and options etc */
+ command = svn_stringbuf_create (editor, pool);
+
+ array = svn_cl__escaped_string_to_array (command, pool);
+
+ /* now we must convert the stringbuf** array to a plain char ** array,
+ allocate two extra entries for the file and the trailing NULL */
+ cmd_args = (const char **)apr_palloc (pool,
+ sizeof (char *) * (array->nelts + 2) );
+
+ cmdstrings=(svn_stringbuf_t **)array->elts;
+ for (i=0 ; i < array->nelts; i++)
+ cmd_args[i] = cmdstrings[i]->data;
+
+ /* it is important to add the file name here and not just as a part of the
+ 'editor' string above, as we must preserve spaces etc that this file name
+ might contain */
+ cmd_args[i++] = tmpfile_name->data;
+ cmd_args[i] = NULL;
+
   /* Now, run the editor command line. Ignore the return values; all
      we really care about (for now) is whether or not our tmpfile
      contents have changed. */
- cmd_args[0] = editor;
- cmd_args[1] = tmpfile_name->data;
- SVN_ERR (svn_io_run_cmd (".", editor, cmd_args, &exit_code, &exit_why,
+ SVN_ERR (svn_io_run_cmd (".", cmd_args[0], cmd_args, &exit_code, &exit_why,
                            TRUE, NULL, NULL, NULL, pool));

   /* Get information about the temporary file after the assumed editing. */

-- 
      Daniel Stenberg - http://daniel.haxx.se - +46-705-44 31 77
   ech`echo xiun|tr nu oc|sed 'sx\([sx]\)\([xoi]\)xo un\2\1 is xg'`ol
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Thu Apr 18 14:24:50 2002

This is an archived mail posted to the Subversion Dev mailing list.