Emacs in place filename / path insertion - emacs

I am looking for a way to insert a filename/path inline while editing. Something like an inline ido-style file selection would be perfect. Is there anything like that out there?

I always use comint-dynamic-complete-filename for this. This does not seem to be loaded by default, but provided by comint-mode. Thus you could put something like
(autoload 'comint-dynamic-complete-filename "comint" nil t)
(global-set-key "\M-]" 'comint-dynamic-complete-filename)
in your ~/.emacs or the like. Use your own prefered keybinding of course.

Okay, if you want to just insert the current file name at point, then
(insert (expand-file-name (buffer-file-name)))
should do it.
If you want to be able to find a file at any path, then you'll want to replicate some of the code in find-file-noselect in files.el at about line 1714 .
In either case, if you want to bind this a a function, you'll probably want
(defun insert-file-name-at-point ()
(interactive) .... )

(defun insert-file-name (file &optional relativep)
"Read file name and insert it at point.
With a prefix argument, insert only the non-directory part."
(interactive "fFile: \nP")
(when relativep (setq file (file-name-nondirectory file)))
(insert file))

Related

How to use the function option of org-capture correctly?

I want to dynamically open the correct file in an orgmode capture template using the function option:
("a" "foo" plain
(function my-visit-timestamped-file)
"<some content>")
Function my-visit-timestamped-file is defined as
(defun my-visit-timestamped-file ()
(interactive)
(let
((theDate (format-time-string "%Y%m%d-%H%M.org")))
(find-file (concat "<some_path>" theDate))))
If I run the capture template a, emacs opens the file <some_path>theDate in a buffer and opens the capture buffer with the file.
Thus my window is split into 2 buffers showing the same content.
Can function my-visit-timestamped-file be changed somehow such that the buffer is not opened but org capture still gets the correct file pointer/file handle?
The answer by #jpkotta pointed me in the right direction.
The bug was gone, but instead the content of the capture buffer was always pasted into the buffer I was currently editing.
In an old thread on the org-mode mailing list I found the answer to my question. The function should be:
(defun my-visit-timestamped-file ()
"Visit a new file named by the current timestamp"
(interactive)
(let* (
(curr-date-stamp (format-time-string "%Y%m%d-%H%M.org"))
(file-name (expand-file-name curr-date-stamp "/some/path/")))
(set-buffer (org-capture-target-buffer file-name))
(goto-char (point-max))))
Link to mailing list thread: https://lists.gnu.org/archive/html/emacs-orgmode/2013-11/msg00676.html
You probably want find-file-noselect instead of find-file. Note that the docs of org-capture-templates say this:
(function function-finding-location)
Most general way: write your own function which both visits
the file and moves point to the right location
so you might want to add some code to go to the correct location (I'm guessing either (point-min) or (point-max)) in the file. That might look like this:
(defun my-visit-timestamped-file ()
(interactive)
(let* ((the-date (format-time-string "%Y%m%d-%H%M.org"))
(the-buffer (find-file-noselect (expand-file-name the-date "/some/path/"))))
(with-current-buffer the-buffer
(goto-char (point-min)))
the-buffer))

Adding hook on elisp function

I'm using Emacs.
Is there any way to add hook on a function?
Assume that there is a markdown-export function.
It is designed to export HTML file into current directory where current working 'markdown file' exsits.
But, I want to export HTML file into another directory. How can I do that without modification on Emacs markdown plugin (markdown-mode.el)?
This is markdown-mode.el's export function:
(defun markdown-export (&optional output-file)
"Run Markdown on the current buffer, save to file, and return the filename.
If OUTPUT-FILE is given, use that as the filename. Otherwise, use the filename
generated by `markdown-export-file-name', which will be constructed using the
current filename, but with the extension removed and replaced with .html."
(interactive)
(unless output-file
(setq output-file (markdown-export-file-name ".html")))
(when output-file
(let* ((init-buf (current-buffer))
(init-point (point))
(init-buf-string (buffer-string))
(output-buffer (find-file-noselect output-file))
(output-buffer-name (buffer-name output-buffer)))
(run-hooks 'markdown-before-export-hook)
(markdown-standalone output-buffer-name)
(with-current-buffer output-buffer
(run-hooks 'markdown-after-export-hook)
(save-buffer))
;; if modified, restore initial buffer
(when (buffer-modified-p init-buf)
(erase-buffer)
(insert init-buf-string)
(save-buffer)
(goto-char init-point))
output-file)))
=====================================================================
I have made an advice to save exported HTML at temp directory
Here is the code.
(defadvice markdown-export (around set-temp-path-for-exported-file activate)
(ad-set-arg 0 (format "%s/%s" "~/.emacs.d/temp-dir" (file-name-nondirectory buffer-file-name)))
ad-do-it)
Thanks!!!!!!!!!!!!!!
In this case you do not need to hook on this function since it already accepts the filename as an argument, unfortunately it does not accept the filename when called interactively. As a workaround you can define a simple wrapper around the function like follows
(defun my-markdown-export (&optional file)
(interactive (list (ido-read-file-name "Export as: ")))
(markdown-export file))
The advice mechanism is a bit like having hooks for any arbitrary function, but here you have actual hooks you can use, as well as a function argument which addresses your requirement directly.
So you can:
(a) Pass the function any arbitrary output filename.
(b) Use the provided markdown-before-export-hook to setq whichever variables you need to (which at a glance looks like output-file, output-buffer, and output-buffer-name).

How to create an empty file by elisp?

I set an explicit file to customization created via the UI. It's named custom.el. Currently, I use the followed snippets to create this file if not exist.
(defconst custom-file (expand-file-name "custom.el" user-emacs-directory))
(unless (file-exists-p custom-file)
(shell-command (concat "touch " custom-file)))
There is an ugly shell-command touch in, any other elisp functions can do this?
You can use (write-region "" nil custom-file) not sure that is the ideal solution.
Perhaps a simpler solution to the underlying problem would be:
(defconst custom-file (expand-file-name "custom.el" user-emacs-directory))
;; NOERROR to ignore nonexistent file - Emacs will create it
(load custom-file t)
In other words, instead of manually creating custom.el, simply don't error when you try to load it (optional arg NOERROR is only for file existence error). Emacs will create the file the first time it writes out custom variables.
This is what I'm currently using in my init.el
I write this function below based on Joao Tavara anwser in this post: How do I create an empty file in emacs?
(defun fzl-create-empty-file-if-no-exists(filePath)
"Create a file with FILEPATH parameter."
(if (file-exists-p filePath)
(message (concat "File " (concat filePath " already exists")))
(with-temp-buffer (write-file filePath))))
(make-empty-file custom-file)
Check help to know more about it: C-h f make-empty-file

Getting ido mode functionality similar to dired-at-point in emacs

I like using ido mode in emacs and the listing of directories with C-x C-d which runs ido-list-directory. Is there a command to enable ido-mode operation but at the current point like dired-at-point. I use this quite often but would prefer to use something like ido-dired-at-point.
Didn't know if this was already implemented and I just couldn't find it in the documentation or if it is easy to implement.
Looks like ido-list-directory is used for interactive completion of list-directory. So, if the thing at point is a filename, rather than use ido, using list-directory directly should achieve the same end result.
How about something like this:
(defun ido-ffap-list-directory ()
(interactive)
(let ((fap (ffap-guess-file-name-at-point)))
(if fap
(list-directory (file-name-directory fap))
(ido-list-directory))))
EDIT:
or, if you want confirmation for the directory # point (only for a C-u prefix) replace the list-directory sexp above with something like this:
(defun ido-ffap-list-directory (&optional arg)
(interactive "P")
(let ((fap (ffap-guess-file-name-at-point)))
(if (null fap)
(ido-list-directory)
(if arg
(list-directory
(ido-read-directory-name "Directory: "
(file-name-directory fap)))
(list-directory (file-name-directory fap))))))
(setq ido-use-filename-at-point 'guess)

Emacs org-mode: textual reference to a file:line

I am using org-mode in Emacs to document my development activities. One of the tasks which I must continuously do by hand is to describe areas of code. Emacs has a very nice Bookmark List: create a bookmark with CTRL-x r m, list them with CTRL-x r l. This is very useful, but is not quite what I need.
Org-mode has the concept of link, and the command org-store-link will record a link to the current position in any file, which can be pasted to the org-file. The problem with this is two-fold:
It is stored as an org-link, and the linked position is not directly visible (just the description).
It is stored in the format file/search, which is not what I want.
I need to have the bookmark in textual form, so that I can copy paste it into org-mode, end edit it if needed, with a simple format like this:
absolute-file-path:line
And this must be obtained from the current point position. The workflow would be as simple as:
Go to the position which I want to record
Call a function: position-to-kill-ring (I would bind this to a keyboard shortcut)
Go to the org-mode buffer.
Yank the position.
Edit if needed (sometimes I need to change absolute paths by relative paths, since my code is in a different location in different machines)
Unfortunately my lisp is non-existent, so I do not know how to do this. Is there a simple solution to my problem?
(defun position-to-kill-ring ()
"Copy to the kill ring a string in the format \"file-name:line-number\"
for the current buffer's file name, and the line number at point."
(interactive)
(kill-new
(format "%s:%d" (buffer-file-name) (save-restriction
(widen) (line-number-at-pos)))))
You want to use the org-create-file-search-functions and org-execute-file-search-functions hooks.
For example, if you need the search you describe for text-mode files, use this:
(add-hook 'org-create-file-search-functions
'(lambda ()
(when (eq major-mode 'text-mode)
(number-to-string (line-number-at-pos)))))
(add-hook 'org-execute-file-search-functions
'(lambda (search-string)
(when (eq major-mode 'text-mode)
(goto-line (string-to-number search-string)))))
Then M-x org-store-link RET will do the right thing (store a line number as the search string) and C-c C-o (i.e. M-x org-open-at-point RET) will open the file and go to this line number.
You can of course check for other modes and/or conditions.
An elisp beginner myself I though of it as a good exercise et voila:
Edit: Rewrote it using the format methode, but I still think not storing it to the kill-ring is less intrusive in my workflow (don't know about you). Also I have added the capability to add column position.
(defvar current-file-reference "" "Global variable to store the current file reference")
(defun store-file-line-and-col ()
"Stores the current file, line and column point is at in a string in format \"file-name:line-number-column-number\". Insert the string using \"insert-file-reference\"."
(interactive)
(setq current-file-reference (format "%s:%d:%d" (buffer-file-name) (line-number-at-pos) (current-column))))
(defun store-file-and-line ()
"Stores the current file and line oint is at in a string in format \"file-name:line-number\". Insert the string using \"insert-file-reference\"."
(interactive)
(setq current-file-reference (format "%s:%d" (buffer-file-name) (line-number-at-pos))))
(defun insert-file-reference ()
"Inserts the value stored for current-file-reference at point."
(interactive)
(if (string= "" current-file-reference)
(message "No current file/line/column set!")
(insert current-file-reference)))
Not tested extensively but working for me. Just hit store-file-and-line or store-file-line-and-col to store current location and insert-file-reference to insert the stored value at point.
BTW, if you want something better than FILE:LINE, you can try to use add-log-current-defun (in add-log.el) which should return the name of the current function.
;; Insert a org link to the function in the next window
(defun insert-org-link-to-func ()
(interactive)
(insert (with-current-buffer (window-buffer (next-window))
(org-make-link-string
(concat "file:" (buffer-file-name)
"::" (number-to-string (line-number-at-pos)))
(which-function)
))))
This func generates link with the function name as the description.
Open two windows, one is the org file and the other is src code.
Then M-x insert-org-link-to-func RET