how to make own shell command with arguments in emacs? - emacs

I want to make my own shell command where i have a variable filename in the command. The filename is passed in an interactive function. I don't know how to save the filename passed as an argument to a variable and further use it to append the whole command.

To ask for a file name (or any other type of value), use interactive. (interactive "fFile: ") means to ask for an existing file (that's what f stands for), prompting with File:.
Then, to concatenate a number of strings, use the concat function.
So the function would look something like this:
(defun my-cat-file (filename)
(interactive "fFile: ")
(shell-command (concat "cat " filename)))

Related

Read terminal argument and pass the function in lisp?

(defun gppinterpreter (filename)
(setq fileContent (read-a-file filename))
(write filecontent)
)
(gppinterpreter filename)
I compile this file in ubuntu
clisp example.lisp
I want to get the filename parameter directly from the terminal such as >> clisp example.lisp filename
but this command not working. How can I get filename parameter in gppinterpreter from terminal
In Clisp, the program arguments are given in the variable EXT:*ARGS*..
https://clisp.sourceforge.io/impnotes/clisp.html
Before it is loaded, the variable EXT:ARGS is bound to a LIST of STRINGs, representing the arguments given to the Lisp script (i.e., $1 in /bin/sh becomes (FIRST EXT:ARGS) etc).
So I think you want to use (second EXT:*ARGS*)

An alternative find file function with the same default folder, every time

I'd like to bind super and 9 to open the "find file:", "C-x C-f" menu with ~/x/ as the "default path" in the user input field, no matter what directory the file I currently have open is in. My elisp skills are unfortunately pretty basic. I would really appreciate some help with this.
(global-set-key (kbd "s-9") 'enter_find_file_with_dir_x_as_default)
(defun enter_find_file_with_dir_x_as_default ()
"Enter find file with the path ~/x/ as the default input every time."
())
Just define a command that calls read-file-name with the directory you want as the default (in the interactive spec), and then calls find-file on the file name read.
(defun my-find-file (file)
"..."
(interactive (list (read-file-name "File: " "~/x/")))
(find-file file))
See the doc for read-file-name, to decide what other arguments you might want (e.g., whether you accept only existing file names or allow a new-file buffer).
Note too that if you want to bind this to a key then it has to be a command, so it needs an interactive spec. If you just wanted a function that reads a file name starting in directory ~/x/ then the answer is read-file-name -- just pass it ~/x/ as its DIR argument.
See the Elisp manual, node Reading File Names, for more information. (C-h i; choose Elisp; i read-file-name.)

Setting byte-compile-dest-file-function

I want to set the destination directory for emacs lisp byte compilation using relative path such as ../foo. I figured out I should use byte-compile-dest-file-function, but do not know how to set it. How can I set it?
To set the byte-compile-dest-function variable, you can use either customize-variable interactively, or setq in your init file. Since you'll have to write a function doing the job either way, I would recommand the latter, so that everything is in the same place in your init file.
For example:
(defun my-dest-function (filename)
(concat (file-name-directory filename)
"../"
(file-name-sans-extension (file-name-nondirectory filename))
".elc"))
(setq byte-compile-dest-file-function 'my-dest-function)
You can find it using C-h v followed by that variable name.
(defcustom byte-compile-dest-file-function nil
"Function for the function `byte-compile-dest-file' to call.
It should take one argument, the name of an Emacs Lisp source
file name, and return the name of the compiled file."
:group 'bytecomp
:type '(choice (const nil) function)
:version "23.2")
You can see that it is a customizable variable, so you can change it's value to "function".
EDIT: I am not so sure this is the variable you want to change. In fact, you can see that it deals with the variable directories often, I don't see how to set a certain directory where all the .elc's should go.

Emacs Lisp - declare functions with a variable/varying name

I'm working on an Emacs Lisp package and one particular feature I would like to add is ability to define functions on the fly - they would follow the same naming convention, but it would help me not having to declare every single one of them manually.
To give an example, I have a basic function called exec, which takes an argument that is the name of executable to launch:
(def exec (cmd)
(async-shell-command cmd "buffer"))
At the same time, in this particular case, I know the list of the executables that I will want to use - or more precisely, I know how to get a list of them, as it can change over time. So what I would like to do, given the following list of executables:
("a" "b" "c")
is to iterate over them and for each one to create a function with a name exec-[executable] - exec-a, exec-b, exec-c.
Unfortunately, defun does not evaluate the NAME argument so I cannot create the function name dynamically.
PS. The exec command is good enough in itself - it uses completing-read with the list of executables supplied, but I thought the above would be nice addition.
How 'bout
(dolist (name name-list)
(defalias (intern (concat "exec-" name))
`(lambda () ,(format "Run %s via `exec'." name) (interactive) (exec ,name))))

How can I set a default path for interactive directory selection to start with in a elisp defun?

I want a function to interactively prompt for an existing directory, but instead of starting from default-directory, I would like a function local default path like '~/should/start/here/always/in/this/function' to start at when using (interactive "D") how can I achieve this? My first thought is to create another function which first sets default-dir and then calls my original function, but that doesn't seem right, and I am unsure of how interactive would be prompted in that case.
Since you're writing this yourself, you can do something like this:
(defun choose-directory (directory)
"sample that uses interactive to get a directory"
(interactive (list (read-directory-name "What directory? "
choose-directory-default-directory)))
(message "You chose %s." directory))
(defvar choose-directory-default-directory "/home/tjackson/work/data"
"Initial starting point.")
Which uses interactive with a lisp expression to call read-directory to get a directory name (you might want to add additional arguments, check the link/docs).
Your original hunch would work as well, though, as you thought, isn't quite as clean. But, it does work well when you don't want to, or cannot, modify the function whose behavior you want to change. I've included that solution below to show you how you'd achieve it (the only piece of the puzzle you didn't mention was call-interactively):
;; original version of choose-directory, calling (interactive "D")
(defun choose-directory (directory)
"sample that uses interactive to get a directory"
(interactive "DWhat directory? ")
(message "You chose %s." directory))
(defun wrap-choose-directory ()
(interactive)
(let ((default-directory choose-directory-default-directory))
(call-interactively 'choose-directory)))