viper-insert wrong number of arguments error - emacs

I have the following function and keybinding in my .viper file:
(defun th-change-to-regexp (regexp)
(interactive "s")
(kill-region (point) (progn
(re-search-forward regexp nil nil 1)
(- (point) 1)))
(backward-char)
(viper-insert))
(define-key viper-vi-global-user-map "ct" 'th-change-to-regexp)
I'm getting the following error on the viper-insert command I think -
Wrong number of arguments: #[(arg) "Ä \210^H\211^X\204^M^#Å\202(^#^H:\203'#\203^^^#H
#Æ\232\203\"^#Å\202(^#^H#\202(^#^H)^YÇÈ ÉÊ\211\211¯^F!\210Ë=\203S# \211^[ÌV
\205O^#ÊÍÎ\217\210^KS\211^S\202>^#)\202U^#Ï )\207"
[arg val viper-intermediate-command count viper-set-complex-command-for-undo 1 (nil)
viper-set-destructive-command viper-insert 114 ...] 8 ("/contrib/projects/emacs23/32bit
/share/emacs/23.1/lisp/emulation/viper-cmd.elc" . 54774) "P"], 0

I'm not a viper user, so I could be completely off about this, but viper-insert takes 1 required argument, and you are not giving it any arguments. You could send it the current prefix argument with
(viper-insert current-prefix-arg)

Related

Is is possible to bind a key plus a variable in Emacs?

I have buffers named *terminal<1>*, *terminal<2>*, *terminal<3>*, etc. Is there a way to bind a key combination that will take an argument for the number? That is, I want to bind C-c 1 to switch to *terminal<1>* and C-c 2 to switch to *terminal<2>*, and so on. If I can't do this directly, is it possible to do metaprogramming in Elisp that will define all the functions for me?
In this suggestion, the interactive switch-to-terminal will take either a prefix argument C-u 2 for example, or prompt the user.
The macro then makes setting up the key bindings a little easier.
Finally I bind C-c 1 to C-c 4 to switch to *terminal<1>* to *terminal<4>*.
(defun switch-to-terminal (buf-num)
(interactive "NNumber of buffer to visist: ")
(let* ((buf-name (format "*terminal<%d>*" buf-num))
(buf (get-buffer buf-name)))
(unless buf
(error "No buffer %s" buf-name))
(switch-to-buffer buf)))
(defmacro bind-switch-to-terminal (num)
`(global-set-key
,(kbd (format "C-c %d" num))
(lambda ()
(interactive)
(switch-to-terminal ,num))))
(bind-switch-to-terminal 1)
(bind-switch-to-terminal 2)
(bind-switch-to-terminal 3)
(bind-switch-to-terminal 4)
This change uses the same switch-to-terminal function, but replaces bind-switch-to-terminal with a function. The lexical-let* allows for the creation of a closure to create unique terminal switching functions, the dotimes loop then binds for C-c 1 to C-c 9.
(defun bind-switch-to-terminal (num)
(lexical-let* ((buf-num num)
(switch-func
(lambda ()
(interactive)
(switch-to-terminal buf-num))))
(global-set-key
(kbd (format "C-c %d" buf-num))
switch-func)))
(dotimes (num 9)
(bind-switch-to-terminal (1+ num)))
You can bind keys as usual:
(global-set-key (kbd "C-c 1") (lambda ()
(interactive)
(switch-to-buffer "*terminal<1>*")))
To create all the shortcuts from 1 to 9 we would use macros.
edit: This buggy version may put you on tracks. I give up :(
(defmacro gototerminal (count)
`(global-set-key (kbd ,(concat "C-c " (number-to-string count)))
;; with the comma I want to evaluate what is inside concat
(lambda () (interactive)
(switch-to-buffer (concat "*terminal<" ,count ">*"))))
)
(progn (setq count 1)
(while (< count 10)
(gototerminal count)
(setq count (1+ count))
))
ps: an elisp debugger is edebug. Set it with C-u C-M-x
I would write a function that calls interactive with an n argument which indicates that the function reads a number from the mini buffer:
(defun test (x)
(interactive "nNumber of buffer to visit: ")
(message (concat "received number: " (number-to-string x))))
Binding this to a key will let you enter a number in the mini buffer.
Another way is to use a numerical argument:
(defun test (x)
(interactive "P")
(message (concat "received number: " (number-to-string x))))
Say you bind this function to C-c c, you can then pass it the number 2 as an argument by pressing C-u 2 C-c c.
If you avoid the usage of an existing prefix key like C-c you can trigger a command with one keypress e.g. F9.
This command can have a single key as input.
Example:
(defun test (k)
(interactive "K")
(message "Pressed key: %d" (- (aref k 0) ?0)))
(local-set-key [f9] 'test)

Emacs Lisp: A list inside a mapcar

I'm using a function that uses a mapcar to apply a (simple) function to all members of a list, like this :
(mapcar 'my-concat-function '(
"/path/one.php"
"/path/two.php"))
But I want to use directory-files to generate the file list and filter it, something like this :
(mapcar 'my-concat-function '(
(directory-files "/path/" nil "\\.php$")))
But I always get a
find-file-noselect: Wrong type argument: stringp, (directory-files "/path/" nil "\\.php$")
When I evaluate
(directory-files "/path/" nil "\\.php$")
It returns
("one.php" "two.php" "three.php" ...)
(I did not add the "..." ; Emacs did. No matter the size of the list, it seems to always end with "...")
Question :
How can I format the output of directory-files so that it produces exactly what mapcar wants, a single list of atoms, I don't really know how to call this form :
"one.php" "two.php" "three.php"
Without the parenthesis, and without those weird "..."?
EDIT
When I try the forms suggested (thank you guys) the quoted function as 1st arg of mapcar does not work (the regexp don't find anything, all files end up open in empty (?) buffers) anymore :(
Here is the full code, thank you very much for helping, it's weird, this function took very little time to write, and now i'm blocked since hours on this simple list issue, arg.
(defun px-bpm-parse (fname)
"Extract elements. Basic Project Management."
(setq in-buf (set-buffer (find-file fname)))
(setq u1 '())
(setq u2 '())
(setq u3 '())
(setq project-dir "/var/www/html/microlabel.git/")
(beginning-of-buffer)
(while
(re-search-forward "^.*<link.*href=\"\\([^\"]+\\)\".*rel=\"stylesheet\"" nil t)
(when (match-string 0)
(setq url (match-string 1) )
(setq u3 (cons (concat "[[file:" project-dir url "][" url "]]\n") u3))))
(beginning-of-buffer)
(while
(re-search-forward "^.*<a.*href=\"\\([^\"]+\\)\"[^>]+>\\([^<]+\\)</a>" nil t)
(when (match-string 0)
(setq url (match-string 1) )
(setq title (match-string 2) )
(setq u1 (cons (concat "[[file:" project-dir url "][" title "]]\n") u1))))
(beginning-of-buffer)
(while
(re-search-forward "^.*<script.*src=\"\\([^\"]+\\)\"" nil t)
(when (match-string 0)
(setq url (match-string 1) )
(setq u2 (cons (concat "[[file:" project-dir url "][" url "]]\n") u2))))
(beginning-of-buffer)
(progn
(with-current-buffer "BPM.org"
(insert "** File: ")
;; (org-insert-link &optional COMPLETE-FILE LINK-LOCATION DEFAULT-DESCRIPTION)
(insert fname)
(insert "\n*** HREF Links (by name)\n")
(mapcar 'insert u1)
(insert "\n*** SCRIPT Links\n")
(mapcar 'insert u2)
(insert "\n*** CSS Links\n")
(mapcar 'insert u3)
(insert "\n\n"))
(switch-to-buffer "BPM.org")
(org-mode)))
(defun px-bpm ()
;; (defun px-bpm (prj-root)
"List all links"
(interactive)
;; (interactive "sEnter project root directory ")
(progn
(with-current-buffer (get-buffer-create "BPM.org")
(insert "* File dependencies\n\n"))
;; (mapcar 'px-bpm-parse '(
;; "/var/www/html/microlabel.git/add.php"
;; ))
(mapcar 'px-bpm-parse (directory-files "/var/www/html/microlabel.git/" nil "\\.php$"))
))
When you evaluate a form and see a result of the form (x y z ...), it's just printed in that way because the output is long. The result is actually the list that you'd expect. For instance,
(list 1 2 3 4 5 6 7 8 9 10 11 12 13)
;=> (1 2 3 4 5 6 7 8 9 10 11 12 ...)
Yet, the last element of the list is what it should be:
(last (list 1 2 3 4 5 6 7 8 9 10 11 12 13))
;=> (13)
Since (directory-files "/path/" nil "\\.php$") returns a list and the second argument to mapcar should be a list, you can make it the second argument:
(mapcar 'my-concat-function (directory-files "/path/" nil "\\.php$"))

un-camelCase code not working

camelCase.el emacswiki has a function to un-camelcase. But It doesn't seem to work. I added that piece to the camelCase.el itself. But can't get it to work.
What am I missing ? Did anyone else have the same problem ?
EDIT : I have added last two functions, one of which is the function that doesn't work
(defun camelCase-downcase-word (count)
"Make word starting at point lowercase, leaving point after word."
(interactive "*p")
(let ((start (point)))
(camelCase-forward-word count)
(downcase-region start (point))))
(defun un-camelcase-string (s &optional sep start)
"Convert CamelCase string S to lower case with word separator SEP.
Default for SEP is a hyphen \"-\".
If third argument START is non-nil, convert words after that
index in STRING."
(let ((case-fold-search nil))
(while (string-match "[A-Z]" s (or start 1))
(setq s (replace-match (concat (or sep "_")
(downcase (match-string 0 s)))
t nil s)))
(downcase s)))
(provide 'camelCase)
Other than the misleading doc-string (it actually defaults to "_", not "-" for the separator), the definition of un-camelcase-string you provide works. Can you give us more details about how it fails and under what circumstances?

In elisp, how to evaluate a string of "var=value\n..." into lisp variables of the same name?

An mplayer tool (midentify) outputs "shell-ready" lines intended to be evaluated by a bash/sh/whatever interpreter.
How can I assign these var-names to their corresponding values as elisp var-names in emacs?
The data is in a string (via shell-command-to-string)
Here is the data
ID_AUDIO_ID=0
ID_FILENAME=/home/axiom/abc.wav
ID_DEMUXER=audio
ID_AUDIO_FORMAT=1
ID_AUDIO_BITRATE=512000
ID_AUDIO_RATE=0
ID_AUDIO_NCH=1
ID_LENGTH=3207.00
ID_SEEKABLE=1
ID_CHAPTERS=0
ID_AUDIO_BITRATE=512000
ID_AUDIO_RATE=32000
ID_AUDIO_NCH=1
ID_AUDIO_CODEC=pcm
ID_EXIT=EOF
Here's a routine that takes a string containing midentify output, and returns an association list of the key-value pairs (which is safer than setting Emacs variables willy-nilly). It also has the advantage that it parses numeric values into actual numbers:
(require 'cl) ; for "loop"
(defun midentify-output-to-alist (str)
(setq str (replace-regexp-in-string "\n+" "\n" str))
(setq str (replace-regexp-in-string "\n+\\'" "" str))
(loop for index = 0 then (match-end 0)
while (string-match "^\\(?:\\([A-Z_]+\\)=\\(?:\\([0-9]+\\(?:\\.[0-9]+\\)?\\)\\|\\(.*\\)\\)\\|\\(.*\\)\\)\n?" str index)
if (match-string 4 str)
do (error "Invalid line: %s" (match-string 4 str))
collect (cons (match-string 1 str)
(if (match-string 2 str)
(string-to-number (match-string 2 str))
(match-string 3 str)))))
You'd use this function like so:
(setq alist (midentify-output-to-alist my-output))
(if (assoc "ID_LENGTH" alist)
(setq id-length (cdr (assoc "ID_LENGTH" alist)))
(error "Didn't find an ID_LENGTH!"))
EDIT: Modified function to handle blank lines and trailing newlines correctly.
The regexp is indeed a beast; Emacs regexps are not known for their easiness on the eyes. To break it down a bit:
The outermost pattern is ^(?:valid-line)|(.*). It tries to match a valid line, or else matches the entire line (the .*) in match-group 4. If (match-group 4 str) is not nil, that indicates that an invalid line was encountered, and an error is raised.
valid-line is (word)=(?:(number)|(.*)). If this matches, then the name part of the name-value pair is in match-string 1, and if the rest of the line matches a number, then the number is in match-string 2, otherwise the entire rest of the line is in match-string 3.
There's probably a better way but this should do it:
(require 'cl)
(let ((s "ID_AUDIO_ID=0
ID_FILENAME=/home/axiom/abc.wav
ID_DEMUXER=audio
ID_AUDIO_FORMAT=1
ID_AUDIO_BITRATE=512000
ID_AUDIO_RATE=0
ID_AUDIO_NCH=1
ID_LENGTH=3207.00
ID_SEEKABLE=1
ID_CHAPTERS=0
ID_AUDIO_BITRATE=512000
ID_AUDIO_RATE=32000
ID_AUDIO_NCH=1
ID_AUDIO_CODEC=pcm
ID_EXIT=EOF"))
(loop for p in (split-string s "\n")
do
(let* ((elements (split-string p "="))
(key (elt elements 0))
(value (elt elements 1)))
(set (intern key) value))))
Here's a function you can run on the output buffer:
(defun set-variables-from-shell-assignments ()
(goto-char (point-min))
(while (< (point) (point-max))
(and (looking-at "\\([A-Z_]+\\)=\\(.*\\)$")
(set (intern (match-string 1)) (match-string 2)))
(forward-line 1)))
I don't think regexp is what really need. You need to split your string by \n and =, so you just say exactly the same to interpreter.
I think you can also use intern to get symbol from string(and set variables). I use it for the first time, so comment here if i am wrong. Anyways, if list is what you want, just remove top-level mapcar.
(defun set=(str)
(mapcar (lambda(arg)
(set
(intern (car arg))
(cadr arg)))
(mapcar (lambda(arg)
(split-string arg "=" t))
(split-string
str
"\n" t))))
(set=
"ID_AUDIO_ID=0
ID_FILENAME=/home/axiom/abc.wav
ID_DEMUXER=audio
ID_AUDIO_FORMAT=1
ID_AUDIO_BITRATE=512000
ID_AUDIO_RATE=0
ID_AUDIO_NCH=1
ID_LENGTH=3207.00
ID_SEEKABLE=1
ID_CHAPTERS=0
ID_AUDIO_BITRATE=512000
ID_AUDIO_RATE=32000
ID_AUDIO_NCH=1
ID_AUDIO_CODEC=pcm
ID_EXIT=EOF")

How to define a function which repeats itself when passed an argument

Is there an easy way to define a function which repeats itself when passed an argument?
For example, I've defined the following function
(defun swap-sign ()
(interactive)
(search-forward-regexp "[+-]")
(if (equal (match-string 0) "-")
(replace-match "+")
(replace-match "-"))
)
I'd like C-u swap-sign to call swap-sign four times.
I've tried
(defun swap-sign (&optional num)
(interactive)
(let ((counter 0)
(num (if num (string-to-number num) 0)))
(while (<= counter num)
(search-forward-regexp "[+-]")
(if (equal (match-string 0) "-")
(replace-match "+")
(replace-match "-"))
(setq counter (1+ counter)))))
but C-u swap-sign still only runs swap-sign (or perhaps more precisely, the body of the while-loop) once. I'm guessing it is because if num is not the right way to test if num is an empty string.
Am I on the right track, or is there a better/easier way to extend swap-sign?
(defun swap-sign (arg)
(interactive "p")
(dotimes (i arg)
(search-forward-regexp "[+-]")
(if (equal (match-string 0) "-")
(replace-match "+")
(replace-match "-"))))
See the documentation of the interactive special form for more details:
C-h finteractiveRET.
You need to tell emacs to expect, and pass the parameter in, by adding a "p" as the parameter specification for interactive (M-x apropos interactive to get the documentation). Here I've made the minimal change to your code to get it to work - note, however, that you don't need the let/while to do the iteration, and the arg doesn't need to be optional.
(defun swap-sign (&optional num)
(interactive "p")
(let ((counter 1))
(while (<= counter num)
(search-forward-regexp "[+-]")
(if (equal (match-string 0) "-")
(replace-match "+")
(replace-match "-"))
(setq counter (1+ counter)))))
Note that you don't need to convert the parameter from a string - using "p" tells emacs to do this for you.