1
votes

I'm creating a function in Emacs Lisp that will read that whole buffer aloud if there is no active region. Otherwise, it reads the active region.

(defun speak-my-text () "Speaks text in buffer."
  (interactive)
(if (equal mark-active t)
   (
    (kill-ring-save (point-min) (point-max))
      (start-process-shell-command "speakbuffvar" nil 
        "bash -c \"killall espeak;xsel --clipboard|espeak -s 290\"")
           )
  (
    (kill-ring-save (region-beginning) (region-end))
      (start-process-shell-command "speakbuffvar" nil 
        "bash -c \"killall espeak;xsel --clipboard|espeak -s 290\"")
           )))

(global-set-key (kbd "C-z") 'speak-my-text)

I'm having trouble with the first line of the else clause:

(kill-ring-save (region-beginning) (region-end))

When I define the function, bind it, and run, I get "Invalid function" and it points to that line. I'm running Linux Mint.

2
what are those lone open parens about? I think there should be progn after themenrey
Also see duplicate-ish Q&A stackoverflow.com/questions/15880783/…phils

2 Answers

4
votes

Use C-h f progn to evaluate multiple expressions sequentially.

You're currently attempting to call a function named (kill-ring-save (region-beginning) (region-end)) and pass it the argument (start-process-shell-command ...)

Naturally, Emacs is telling you that (kill-ring-save (region-beginning) (region-end)) is not the name of a function.

1
votes

In addition to phils' answer:

mark-active is not reliable in this context, as it might be non-nil also if a region has no extend.

Function region-active-p would be usable, however depends on an active transient-mark-mode, which might be unrelated - in most cases it's useful and sufficient BTW.

Here is a example how to check for an valid region greater then zero and surpassing transient-mark-mode issue:

(defun ar-region-active-p ()
  "Check for and existing region of some extend.

Don't mix up that question with transient-mark-mode "
  (interactive)
  (and (ignore-errors (region-beginning))(region-end) (< (region-beginning)(region-end))))

Based on this, your command might be written slightly differently:

(defun my-command-on-region ()
  "If a region of some extend exists, use on it.

Otherwise use whole buffer.

Doesn't require `transient-mark-mode' being active"
  (interactive)
  (let ((beg (or (and (ignore-errors (region-beginning))(region-end) (< (region-beginning)(region-end))(region-beginning))
         (point-min)))
   (end (or (and (ignore-errors (region-beginning))(region-end) (< (region-beginning)(region-end))(region-end))
         (point-max))))
    (DO-SOMETHING beg end)))