5

I want to write an emacs function for debug purposes in c++ code. Basically I'm fed up typing the following:

std::cout << "variable is: " << variable << std::endl; 

Instead I want to define an emacs function called say "td" for temp debug such that I do

M-x td RETURN foo 

And it will print

std::cout << "foo is: " << foo << std::endl; 

I want it to behave like M-x goto-line whereby I type M-x goto-line and press enter then it prompts me for an input, in my case I want my input to be the variable name and something like td instead of goto-line.

Open to other suggestions, but I'd like to know how to code this type of function for future reference anyway.

6
  • 2
    Try looking at the source to goto-line to see if you can figure it out. Use C-h f goto-line RET and click on the link that says simple.el to see the source. Commented Nov 7, 2014 at 16:43
  • 1
    Here are a couple of useful functions which you can combine to get the functionality you're after. See read-minibuffer and format in the manual. (And, for good measure here's the intro to elisp you can reference as well.) Commented Nov 7, 2014 at 16:47
  • 2
    Have you looked into yasnippet Commented Nov 7, 2014 at 18:52
  • 1
    The "expand <something> into <something else>" concept is called abbrevs in Emacs, and might be worth looking in to. emacswiki.org/AbbrevMode Commented Nov 8, 2014 at 7:56
  • 1
    I'd do that kind of thing with a C++ macro. That way you can easily tell the temporary debug code (DBG(foo)) from the normal output, and disable the debug code in production. Commented Nov 12, 2014 at 4:57

2 Answers 2

9

The interactive special form provides the easiest way to get input from a user.

(defun td (variable) (interactive "sVariable:") (insert (format "std::cout << \"%s is: \" << %s << std::endl;" variable variable))) 

Here "sVariable:" consists of the "s" code character (read a string) and the prompt. (See Using interactive in the Emacs Lisp Manual for more.)

In addition to using a string with with code characters, the interactive special form can use a lisp form as its argument descriptor; this form should evaluate to a list of arguments.

This lets an interactive command compute its arguments from the context, record argument history, and so on.

read-from-minibuffer supports both setting the initial value and recording history; with its help we can make td remember what was entered and offer it upon next invocation.

(defun td (stream variable) (interactive (list (read-from-minibuffer "Stream: " (when (boundp 'td-history) (car td-history)) nil nil 'td-history) (read-from-minibuffer "Variable: "))) (insert (format "%s << \"%s is: \" << %s << std::endl;" stream variable variable))) 

PS: Since you are debugging C++ code, you can add __FILE__ and __LINE__ macros, to get something similar to

(defun td (variable) (interactive "sVariable:") (insert (format "std::cout << \"file \" << __FILE__ << \" line \" << __LINE__ << \" %s is: \" << %s << std::endl;" variable variable))) 
4
  • Thanks. That's great. Works really nicely. I modified it to also allow me to specify the stream, e.g. std::err or std::cout etc. So I have defun td(stream variable) etc. I would like to know if I can make stream default to the last one I used. In the same way that regexp-search does if you invoke it twice? Commented Nov 14, 2014 at 14:46
  • This is how you should do it. But being C++, for maintainability, you'll probably want to format with an error macro (can't use a function of the FILE and LINE macros won't expand right). Commented Nov 16, 2014 at 9:03
  • #define error(v) do { if (debug) std::cerr << "file " << __FILE__ << " line " << __LINE__ << " " #v " is: " << v << std::endl; } while(true) Commented Nov 16, 2014 at 9:09
  • Dang it, past five minutes. I meant while(0) I really did. Commented Nov 16, 2014 at 9:17
5

Like this

(defun example(name) (interactive "sWhat's your name: ") (message "Hello, %s" name)) 

The key part is the "s" prefix. Use s for plain strings, b for buffers, etc.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.