Writing "Hello World" in Emacs? - emacs

I would like to write a few Unix scripts in Emacs Lisp. However, there doesn't seem to be a clean way to write to STDOUT so I can redirect the results to a file or pipe the output to another command. The print function places double quotes around the output strings so I get "Hello world!" instead of Hello world!.
Here's the emacs script.
#!/usr/bin/emacs --script
;;
;; Run me from a Unix shell: ./hello.el > x.txt
;;
(message "Hello world! I'm writing to STDERR.")
(print "Hello world! I'm writing to STDOUT but I'm in quotes")
(insert "Hello world! I'm writing to an Emacs buffer")
(write-file "y.txt")
And here's how I would like to call it.
hello.el > x.txt
hello.el | wc

Seems like you want princ instead of print. So, basically:
(princ "Hello world! I'm writing to STDOUT but I'm not in quotes!")
However, one caveat is that princ does not automatically terminate the output with \n.

As David Antaramian says, you probably want princ.
Also, message supports a format control string (akin to printf in C) that is adapted from format. So, you may eventually want to do something like
(princ (format "Hello, %s!\n" "World"))
As a couple of functions plus demonstration:
(defun fmt-stdout (&rest args)
(princ (apply 'format args)))
(defun fmtln-stdout (&rest args)
(princ (apply 'format
(if (and args (stringp (car args)))
(cons (concat (car args) "\n") (cdr args))
args))))
(defun test-fmt ()
(message "Hello, %s!" "message to stderr")
(fmt-stdout "Hello, %s!\n" "fmt-stdout, explict newline")
(fmtln-stdout "Hello, %s!" "fmtln-stdout, implicit newline"))

Related

Subprocess output to string in Racket

How would you implement the following procedure in Racket:
(command->string "printf" "hello world")
in such a way that:
It runs the argv[] '("printf" "hello world") in a subprocess, finding printf in PATH.
If the subprocess exits with code zero, returns stdout as a string.
If the subprocess exits nonzero, raises an exception.
Stdin and stderr are ignored; they are the same as for the Racket process.
You can use
(with-output-to-string
(lambda ()
(or (system* (find-executable-path "printf") "hello world")
(error 'who "command failed"))))
If you try this at the Racket REPL, it works but it seems to confuse the REPL, and the next prompt is not shown. I think maybe the printf command is peeking at stdin, or perhaps there's a bug in XREPL. Wrapping the expression above with
(parameterize ((current-input-port (open-input-string ""))) _)
seems to fix the issue.
(define (command->string command . args)
(let-values (((sub stdout stdin stderr)
(apply subprocess #f
(current-input-port)
(current-error-port)
(find-executable-path command)
args)))
(let ((output (port->string stdout)))
(subprocess-wait sub)
(if (eqv? 0 (subprocess-status sub))
output
(error "Command failed:" (cons command args))))))
(writeln (command->string "printf" "%s" "hello world"))
In case anyone from Racket is reading, please consider adding something like this to the standard library. This is simple and quite commonly needed.

Hook into man output

I want to hook into man output (from man.el) but the commands run asynchronously. Does anyone know how to set a process sentinel for the man command, or an alternative to hook the function?
For example, how can I replace the sit-for in the following snippet with a callback to run when man finishes its processing?
(defun get-some-help (cmd &optional num)
(let ((buf (man (concat (number-to-string (or num 3)) " " cmd))))
(sit-for 0.1) ;how to replace this?
(unless (buffer-live-p buf)
(message "Do something else instead"))))
(get-some-help "wait4")

How to redirect message/echo output to a buffer in Emacs?

I'm writing a couple of helper functions for my use. They first call up org-publish-project and then call external scripts on that output. I'd like to collect all output from the execution in a temp buffer that pops up.
The external stuff is easier. The function shell-command accepts a second argument about a buffer where to send stdout. But org-publish-project only echoes stuff to minibuffer and it shows on *Messages* if anywhere. Could I somehow redirect all echoes to a given buffer?
No, there's no such redirect, sadly. You can try to advise the message function, which will catch many of those messages, tho not necessarily all of them.
(defvar my-message-output-buffer nil)
(defadvice message (around my-redirect activate)
(if my-message-output-buffer
(with-current-buffer my-message-output-buffer
(insert (apply #'format (ad-get-args 0))))
ad-do-it))
Depending on what org-publish-project internally uses to display messages, the following might work:
(with-output-to-temp-buffer "*foo*"
(do-stuff))
(pop-to-buffer "*foo*")
To temporarily redirect all message output to the current buffer, do the following:
(defvar orig-message (symbol-function 'message))
(defun message-to-buffer (format-string &rest args)
(insert (apply 'format format-string args) "\n"))
(defmacro with-messages-to-buffer (&rest body)
`(progn (fset 'message (symbol-function 'message-to-buffer))
(unwind-protect
(progn ,#body)
(fset 'message orig-message))))
;; Usage
(with-messages-to-buffer
(message "hello"))

How do I print a string in Emacs lisp with ielm?

I'd like to print a string in ielm. I don't want to print the printed representation, I want the string itself. I'd like this result:
ELISP> (some-unknown-function "a\nb\n")
a
b
ELISP>
I can't see any way to do this. The obvious functions are print and princ, but these give me the printable representation:
ELISP> (print "* first\n* second\n* third\n")
"* first\n* second\n* third\n"
I've played with pp and pp-escape-newlines, but these still escape other characters:
ELISP> (setq pp-escape-newlines nil)
nil
ELISP> (pp "a\n")
"\"a
\""
Is this possible? For inspecting large strings, message doesn't cut it.
How about inserting directly into the buffer?
(defun p (x) (move-end-of-line 0) (insert (format "\n%s" x)))
That gets you:
ELISP> (p "a\nb\n")
a
b
nil
ELISP>
EDIT: Use format to be able to print things other than strings.
;;; Commentary:
;; Provides a nice interface to evaluating Emacs Lisp expressions.
;; Input is handled by the comint package, and output is passed
;; through the pretty-printer.
IELM uses (pp-to-string ielm-result) (so binding pp-escape-newlines has an effect in general), but if you want to bypass pp altogether then IELM doesn't provide for that, so I suspect Sean's answer is your best option.
ELISP> (setq pp-escape-newlines nil)
nil
ELISP> "foo\nbar"
"foo
bar"
#Sean's answer is correct if you want to display the string as part of your session.
However, you say you want to inspect large strings. An alternative approach would be to put the string in a separate window. You could use with-output-to-temp-buffer to do this. For instance:
(with-output-to-temp-buffer "*string-inspector*"
(print "Hello, world!")
nil)
A new window will pop up (or if it already exists, its output will be changed). It's in Help mode, so it's readonly and can be closed with q.
If you want to do some more sophisticated stuff in your output buffer you could use with-temp-buffer-window instead, like so:
(with-temp-buffer-window "*string-inspector*"
#'temp-buffer-show-function
nil
(insert "hello, world!!"))

Help writing emacs lisp for emacs etags search

I'm looking for some help developing what I think should be an easy program.
I want something similar to Emacs tags-search command, but I want to collect all search results into a buffer. (I want to see all results of M-,)
I'm thinking this python style pseudo code should work, but I have no idea how to do this in emacs lisp? Any help would be greatly appreciated.
def myTagsGrep(searchValue):
for aFile in the tag list:
result = grep aFile seachValue
if len(result) > 0:
print aFile # to the buffer
print result # to the buffer
I would like to be able to browse through the buffer with the same features tags-apropos does.
Note that a similar question has been asked before:
Is there a way to get emacs tag-search command to output all results to a buffer?
Since I'm such a fan of igrep, I'd use it as the building block. From there it's two simple routines and you're done. With that library and these two functions, all you have to do is:
M-x igrep-tags ^SomeRegexp.*Here RET
Here's the code:
(require 'igrep)
(defun igrep-tags (regex)
(interactive "sTAGS Regexp: ")
(igrep igrep-program regex (tags-file-names)))
(defun tags-file-names ()
(save-excursion
(visit-tags-table-buffer)
(mapcar (lambda (f) (file-truename f))
(tags-table-files))))
And, because the list of files can get really long, and you likely don't care what that list is, you can add these two pieces of code which will make the filenames invisible after the grep has finished:
(add-hook 'compilation-finish-functions 'igrep-tags-hide-filenames)
(defun igrep-tags-hide-filenames (buffer stat)
"hide the filenames b/c they can get long"
(save-excursion
(set-buffer buffer)
(save-match-data
(goto-char (point-min))
(if (search-forward (combine-and-quote-strings (tags-file-names))
nil
(save-excursion (forward-line 10) (point)))
(let ((display-string "..<files from TAGS>.."))
(put-text-property (match-beginning 0) (match-end 0) 'invisible t)
(put-text-property (match-beginning 0) (match-end 0) 'display display-string))))))
To avoid the really long command line, you can use the following code (which creates a temporary file containing all the names of files from TAGS file and uses that instead):
(defun igrep-tags (regex)
(interactive "sTAGS Regexp: ")
(let ((igrep-find t)
(igrep-use-file-as-containing-files t))
(igrep igrep-program regex nil)))
(defvar igrep-use-file-as-containing-files nil)
(defadvice igrep-format-find-command (around igrep-format-find-command-use-filename-instead activate)
"use the second argument as a file containing filenames"
(if igrep-use-file-as-containing-files
(progn (with-temp-file
(setq igrep-use-file-as-containing-files (make-temp-file "tags-files"))
(insert (combine-and-quote-strings (tags-file-names))))
(setq ad-return-value (format "cat %s | xargs -e %s"
igrep-use-file-as-containing-files
(ad-get-arg 0))))
ad-do-it))
And, for those using Emacs 22 or earlier, you'll need the routine that's shipped with Emacs 23 (from subr.el)
(defun combine-and-quote-strings (strings &optional separator)
"Concatenate the STRINGS, adding the SEPARATOR (default \" \").
This tries to quote the strings to avoid ambiguity such that
(split-string-and-unquote (combine-and-quote-strings strs)) == strs
Only some SEPARATORs will work properly."
(let* ((sep (or separator " "))
(re (concat "[\\\"]" "\\|" (regexp-quote sep))))
(mapconcat
(lambda (str)
(if (string-match re str)
(concat "\"" (replace-regexp-in-string "[\\\"]" "\\\\\\&" str) "\"")
str))
strings sep)))
Here is the code I use to create a tag system for my personal notes. It uses bookmarks and treats each word in a bookmark as a single tag. Its not quite what you're looking for but it might get you started.
The first couple of functions are probably already implemented in emacs, but I wrote my own for reasons that I no longer recall.
;; FILTER keeps only elements of li for which pred returns true
(defun filter (pred li)
(let (acc)
(dolist (elem li)
(if (funcall pred elem)
(setq acc (cons elem acc))))
(reverse acc)))
(defun string-match-all-p (str li)
(if li
(if (string-match-p (car li) str)
(string-match-all-p str (cdr li))
nil)
t))
;;bookmarks as tags
(defun lookup-bookmark-tags (tagstring)
(interactive "s")
(let ((taglist (split-string tagstring " ")))
(let ((bookmark-alist (filter
(lambda (elem)
(string-match-all-p (car elem) taglist))
bookmark-alist)))
(call-interactively 'list-bookmarks))))
I then bind the 'tagging' behavior to a key (F11) and the 'lookup' behavior to another (F12).
(global-set-key [f11] 'bookmark-set)
(global-set-key [f12] 'lookup-bookmark-tags))
Hope that is useful to you.
This is what you want:
http://www.emacswiki.org/emacs/Icicles_-_Emacs_Tags_Enhancements#icicle-tags-search
This is the doc string for icicle-tags-search:
Search all source files listed in tags tables for matches for REGEXP.
You are prompted for the REGEXP to match. Enter REGEXP with `RET'.
You do not need `M-,' - you see all matches as search hits to visit.
All tags in a tags file are used, including duplicate tags from the
same or different source files.
By default, all tags files are used, but if you provide a prefix
argument then only the current tag table is used.
If your TAGS file references source files that no longer exist, those
files are listed. In that case, you might want to update your TAGS
file.
You can alternatively choose to search, not the search contexts as
defined by the context regexp you provide, but the non-contexts, that
is, the text in the files that does not match the regexp. To do this,
use `C-M-~' during completion. (This is a toggle, and it affects only
future search commands, not the current one.)
See also this page for more explanation about Icicles search:
http://www.emacswiki.org/emacs/Icicles_-_Search_Commands%2c_Overview