all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* quote bashslash in a shell command
@ 2014-07-06 16:01 William Xu
  0 siblings, 0 replies; 8+ messages in thread
From: William Xu @ 2014-07-06 16:01 UTC (permalink / raw)
  To: help-gnu-emacs

The shell command is:
  echo foo.bar | sed -e 's/\..*//'

which will produce "foo" on bash.

If i try to pass it to shell-command-to-string:
  (shell-command-to-string "echo foo.bar | sed -e 's/\..*//'")
	=> "\n"

Then i find i need to quote the backslash in emacs once more:
  (shell-command-to-string "echo foo.bar | sed -e 's/\\..*//'")
	=> "foo\n"

Is there a function or other way that can handle this kind of backslash
quoting automatically?


-William




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: quote bashslash in a shell command
       [not found] <mailman.4940.1404662528.1147.help-gnu-emacs@gnu.org>
@ 2014-07-06 16:22 ` Pascal J. Bourguignon
  2014-07-07  6:27   ` William Xu
       [not found]   ` <mailman.4987.1404714478.1147.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 8+ messages in thread
From: Pascal J. Bourguignon @ 2014-07-06 16:22 UTC (permalink / raw)
  To: help-gnu-emacs

William Xu <william.xwl@gmail.com> writes:

> The shell command is:
>   echo foo.bar | sed -e 's/\..*//'
>
> which will produce "foo" on bash.
>
> If i try to pass it to shell-command-to-string:
>   (shell-command-to-string "echo foo.bar | sed -e 's/\..*//'")
> 	=> "\n"

When you want to put a backslash in a string, you must double it.  Here
you are backslashing the first dot.

"\." = "." 

"\n" = "
"
"\\" = "\\" = a string containing a single character, a backslash.



> Then i find i need to quote the backslash in emacs once more:
>   (shell-command-to-string "echo foo.bar | sed -e 's/\\..*//'")
> 	=> "foo\n"

Yes.


> Is there a function or other way that can handle this kind of backslash
> quoting automatically?

No and yes.

In Common Lisp, you could define a reader macro to be able to read
strings with another syntax than the default one, where backslash in
strings wouldn't serve to escape the following character (or have
special meaning as in "\n").  

But emacs lisp doesn't provide (yet) reader macros, therefore the syntax
for string literals is fixed. 

Now of course, there are many ways to generate strings.
For example, you could use format:

   (format  "echo foo.bar | sed -e 's/%c..*//'" ?\\)

But you will say that it doesn't help because:

1- you still have to type a format string,

2- in addition to have to be careful about backslash in the format
   string, you have to be careful about the string specifier characters,
   namely ?%:

     (format "echo %%%s%%" "hello") --> "echo %hello%"

3- the syntax for single characters still provides a special meaning to
   backslash, so it still has to be duplicated in ?\\ --> 92 = the code
   of the backslash character.



What you'd want to do, is to define a DSL, a domain specific language,
to build shell command strings.  So you could write something as:

   (pipe (echo foo.bar)
         (sed -e s/\..//))
         

But we have still the same problem, because in symbols, some special
characters need to or may be escaped, including the backslash which is
used to escape them!

   '(pipe (echo foo.bar)
          (sed -e s/\..//))
   --> (pipe (echo foo\.bar) (sed -e s/\.\.//))

There's no backspace in this sexp!

Again, what we want here, are reader macros that would let us redefine
the syntax for symbols when reading a shell sexp.




Introducing a readtable to implement reader macros in emacs lisp would
not be too complex.  I've implemented the Common Lisp reader in Common
Lisp.  Porting it to emacs lisp wouldn't be too hard.  Some refactoring
(or surgical amputation) of the emacs lisp reader, implemented in C
would be required.

-- 
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ?  C'est le moment d'acheter !"


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: quote bashslash in a shell command
  2014-07-06 16:22 ` quote bashslash in a shell command Pascal J. Bourguignon
@ 2014-07-07  6:27   ` William Xu
  2014-07-07 11:34     ` Aurélien Aptel
  2014-07-07 15:27     ` Pascal J. Bourguignon
       [not found]   ` <mailman.4987.1404714478.1147.help-gnu-emacs@gnu.org>
  1 sibling, 2 replies; 8+ messages in thread
From: William Xu @ 2014-07-07  6:27 UTC (permalink / raw)
  To: help-gnu-emacs

"Pascal J. Bourguignon" <pjb@informatimago.com> writes:

> What you'd want to do, is to define a DSL, a domain specific language,
> to build shell command strings.  So you could write something as:
>
>    (pipe (echo foo.bar)
>          (sed -e s/\..//))

That sounds a overkill.

What i'd like to have is that i try a shell command on bash, then i can
simpy copy and paste in elisp.

-- 
William

http://xwl.appspot.com




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: quote bashslash in a shell command
  2014-07-07  6:27   ` William Xu
@ 2014-07-07 11:34     ` Aurélien Aptel
  2014-07-07 15:27     ` Pascal J. Bourguignon
  1 sibling, 0 replies; 8+ messages in thread
From: Aurélien Aptel @ 2014-07-07 11:34 UTC (permalink / raw)
  To: William Xu; +Cc: help-gnu-emacs@gnu.org

On Mon, Jul 7, 2014 at 8:27 AM, William Xu <william.xwl@gmail.com> wrote:
> What i'd like to have is that i try a shell command on bash, then i can
> simpy copy and paste in elisp.

I don't think it's possible. It's a good use case for raw strings
(which I've tried to get in vanilla emacs [1]) or more generally
reader macros (see Pascal's post).

But what you can do is copy and paste your shell code, select it, and
call this function:

(defun my-raw-string (start end)
  (interactive "r")
  (let ((r (prin1-to-string (buffer-substring-no-properties start end))))
    (delete-region start end)
    (insert r)))

which will turn this:

a b \ c

to this:

"a b \\ c"

1: http://definitelyaplug.b0.cx/post/raw-strings/



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: quote bashslash in a shell command
  2014-07-07  6:27   ` William Xu
  2014-07-07 11:34     ` Aurélien Aptel
@ 2014-07-07 15:27     ` Pascal J. Bourguignon
  2014-07-08  3:59       ` William Xu
  1 sibling, 1 reply; 8+ messages in thread
From: Pascal J. Bourguignon @ 2014-07-07 15:27 UTC (permalink / raw)
  To: help-gnu-emacs

William Xu <william.xwl@gmail.com> writes:

> "Pascal J. Bourguignon" <pjb@informatimago.com> writes:
>
>> What you'd want to do, is to define a DSL, a domain specific language,
>> to build shell command strings.  So you could write something as:
>>
>>    (pipe (echo foo.bar)
>>          (sed -e s/\..//))
>
> That sounds a overkill.
>
> What i'd like to have is that i try a shell command on bash, then i can
> simpy copy and paste in elisp.

If you use the paredit minor mode in emacs lisp mode buffers, then M-"
paredit-doublequote will double the backquotes.

Unfortunately, since | is an escape character in lisp, if you paste a
shell pipe with an odd number of | in elisp, select it and M-", it will
signal an Unbalanced parentheses error and not do the work. 

Instead you can add a | at the end to make an even number of them,
select the shell expression and type M-".


C-y               echo foo.bar | sed -e s/\..//
|                 echo foo.bar | sed -e s/\..//|
C-SPC C-a        [echo foo.bar | sed -e s/\..//|]
M-"              "echo foo.bar | sed -e s/\\..//|"
C-e C-b DEL      "echo foo.bar | sed -e s/\\..//"


In any case, you should always use paredit-mode for lisp editing.

-- 
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ?  C'est le moment d'acheter !"




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: quote bashslash in a shell command
  2014-07-07 15:27     ` Pascal J. Bourguignon
@ 2014-07-08  3:59       ` William Xu
  2014-07-08  5:04         ` Pascal J. Bourguignon
  0 siblings, 1 reply; 8+ messages in thread
From: William Xu @ 2014-07-08  3:59 UTC (permalink / raw)
  To: help-gnu-emacs

"Pascal J. Bourguignon" <pjb@informatimago.com> writes:

> If you use the paredit minor mode in emacs lisp mode buffers, then M-"
> paredit-doublequote will double the backquotes.

Neat! Thanks.

I use paredit, but not this paredit-doublequote.

> Unfortunately, since | is an escape character in lisp, if you paste a
> shell pipe with an odd number of | in elisp, select it and M-", it will
> signal an Unbalanced parentheses error and not do the work. 
>
> Instead you can add a | at the end to make an even number of them,
> select the shell expression and type M-".

Seems I don't have this problem.

Aurélien's my-raw-string is also a good work around.

My paredit.el git head: 67d6a4f5ad505af98a311bd955dbe7bd2fc4e0b1

-- 
William

http://xwl.appspot.com




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: quote bashslash in a shell command
  2014-07-08  3:59       ` William Xu
@ 2014-07-08  5:04         ` Pascal J. Bourguignon
  0 siblings, 0 replies; 8+ messages in thread
From: Pascal J. Bourguignon @ 2014-07-08  5:04 UTC (permalink / raw)
  To: help-gnu-emacs

William Xu <william.xwl@gmail.com> writes:

> "Pascal J. Bourguignon" <pjb@informatimago.com> writes:
>
>> If you use the paredit minor mode in emacs lisp mode buffers, then M-"
>> paredit-doublequote will double the backquotes.
>
> Neat! Thanks.
>
> I use paredit, but not this paredit-doublequote.
>
>> Unfortunately, since | is an escape character in lisp, if you paste a
>> shell pipe with an odd number of | in elisp, select it and M-", it will
>> signal an Unbalanced parentheses error and not do the work. 
>>
>> Instead you can add a | at the end to make an even number of them,
>> select the shell expression and type M-".
>
> Seems I don't have this problem.

It depends whether you are in emacs-lisp-mode or lisp-mode.
Indeed, in emacs-lisp-mode, | is not an escape character, so the problem
doesn't occur. I tried it in lisp-mode.


-- 
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ?  C'est le moment d'acheter !"




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: quote bashslash in a shell command
       [not found]   ` <mailman.4987.1404714478.1147.help-gnu-emacs@gnu.org>
@ 2014-07-08  7:49     ` jduthen
  0 siblings, 0 replies; 8+ messages in thread
From: jduthen @ 2014-07-08  7:49 UTC (permalink / raw)
  To: help-gnu-emacs

Le lundi 7 juillet 2014 08:27:22 UTC+2, William Xu wrote :
> What i'd like to have is that i try a shell command on bash,
> then i can simpy copy and paste in elisp.

You could also quote the backslashs from within the shell using 'qbs':

$ function qbs() { if [ $# -gt 0 ] ; then l=$1; else read -r l; fi; 
echo "$l" | sed -e 's/\\/\\\\/g'; }

$ echo foo.bar | sed -e 's/\..*//'
foo

# This command works. I want to quote the backslahs to copy it in emacs.
# So I copy and paste it into 'qbs'

$ qbs
echo foo.bar | sed -e 's/\..*//'    # <- This is what I copied/pasted
echo foo.bar | sed -e 's/\\..*//'   # <- This is what 'qbs' produces

# or pass it as argument to qbs:

$ qbs "echo foo.bar | sed -e 's/\..*//'"
echo foo.bar | sed -e 's/\\..*//'

HTH
)jack(


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2014-07-08  7:49 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.4940.1404662528.1147.help-gnu-emacs@gnu.org>
2014-07-06 16:22 ` quote bashslash in a shell command Pascal J. Bourguignon
2014-07-07  6:27   ` William Xu
2014-07-07 11:34     ` Aurélien Aptel
2014-07-07 15:27     ` Pascal J. Bourguignon
2014-07-08  3:59       ` William Xu
2014-07-08  5:04         ` Pascal J. Bourguignon
     [not found]   ` <mailman.4987.1404714478.1147.help-gnu-emacs@gnu.org>
2014-07-08  7:49     ` jduthen
2014-07-06 16:01 William Xu

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.