Xah Talk Show 2025-11-12 Ep712 Emacs Lisp, Move File to Parent Dir. car cdr cons, Functional Programing sans Variable
Video Summary (Generated by AI, Edited by Human.)
In this video, Xah Lee codes in Emacs Lisp to create a command that moves files or marked files to their parent directory (0:08).
Here's a breakdown of the video's content:
- Demonstration of manual file movement in Emacs Dired (1:02): The speaker first demonstrates the manual process of moving files in Emacs's Dired mode, which involves splitting windows, navigating directories, marking files, and using the capital R key to move them (1:02-2:08).
- He emphasizes the desire to automate this process with a single command (2:12).
- Introduction to Dired and File Managers (3:28): The speaker explains Dired as Emacs's directory editor, which is essentially a file manager.
- He compares it to Windows File Explorer, Mac Finder, and various Linux file managers (3:28-4:32).
- Getting a list of marked files (5:02): The first step in coding the command is to get a list of files that are currently marked in Dired.
- If no files are marked, the file under the cursor is considered the "current file" (5:02-6:10).
- The dired-get-marked-files command is used for this purpose (7:21).
- Finding the parent directory (9:25): The speaker then looks for the function to find the parent directory of a given file path.
- He refers to his own Emacs Lisp tutorial for this (9:32-11:58).
- He identifies file-name-directory as the function to get the directory of a file and later introduces file-name-parent-directory for obtaining the parent directory specifically (52:22).
- Renaming/Moving files with rename-file (12:50): The rename-file command is introduced as the way to move or rename files, following Unix conventions (13:13).
- Discussion on car and cdr in Lisp (15:22): A significant portion of the video is dedicated to explaining car and cdr (pronounced "car" and "carder" by the speaker) in Lisp.
- Cons Cells: He explains that Lisp lists are fundamentally built from "cons cells," which are pairs of two things (17:45).
- car refers to the first part of a cons cell, and cdr refers to the second part (20:16-20:58).
- Nesting for Lists: Lists are formed by nesting these cons cells (21:56).
- Historical Context: The speaker provides historical context, explaining that this design originated from early Lisp machines that had hardware optimized for these two-part cells (23:41).
- Modern Alternatives: He advises against using the nested car and cdr functions (like cadr or cddar) for accessing elements in a list, calling them "idiotic" and "silly" (28:18-33:11).
- Instead, he recommends using higher-level functions like nth for direct access (33:37) and push and pop for stack-like operations (36:56).
- List Traversal and Efficiency: He highlights that functions like length for lists are inefficient because they have to traverse each element, which is a nature of Lisp's linked list implementation (38:55).
- Completing the file movement command (42:30): The speaker proceeds to finalize the Emacs Lisp command, using mapc to apply the rename-file function to each selected file, concatenating the parent directory with the file's name (55:57).
- Testing the command (56:30): The command is successfully tested by moving a file to its parent directory and then moving it back (56:30-58:06).
- Refinement and Future Improvements (58:11): The speaker notes that the command could be further refined by adding error checking for root directories and printing messages about the move (58:11).
- He also discusses simplifying the code by removing unnecessary variables (59:23) and functional programing technique to not use any variable or constant.
- computer science and history. For lisp fans.
- explains cons car cdr in lisp list.
- https://youtu.be/n_JUKfSf8sc?t=922
- Computer Science, Advanced Functional Programing. Emacs Lisp.
- Demo of supreme functional programing technique, of not using any variable or constant at all, in your program.
- https://youtu.be/n_JUKfSf8sc?t=3563
- Play at 1.5 speed.
- emacs lisp write a move up dir
xah-move-to-parent-dir
(defun xah-move-to-parent-dir () "move current file or marked file up one dir. Created: 2025-11-12 Version: 2025-11-12" (interactive) (let ((xfiles (dired-get-marked-files)) xcur-dir xparent-dir) (setq xcur-dir (file-name-directory (car xfiles))) (setq xparent-dir (file-name-parent-directory xcur-dir)) (mapc (lambda (x) (rename-file x (concat xparent-dir (file-name-nondirectory x)))) xfiles))) ;; s------------------------------ (defun xah-move-to-parent-dir () "move current file or marked file up one dir. Created: 2025-11-12 Version: 2025-11-12" (interactive) (let* ((xfiles (dired-get-marked-files)) (xcur-dir (file-name-directory (car xfiles))) (xparent-dir (file-name-parent-directory xcur-dir))) (mapc (lambda (x) (rename-file x (concat xparent-dir (file-name-nondirectory x)))) xfiles))) ;; s------------------------------ (defun xah-move-to-parent-dir () "move current file or marked file up one dir. Created: 2025-11-12 Version: 2025-11-12" (interactive) (let ((xfiles (dired-get-marked-files))) (mapc (lambda (x) (rename-file x (concat (file-name-parent-directory (file-name-directory (car xfiles))) (file-name-nondirectory x)))) xfiles))) ;; s------------------------------ (defun xah-move-to-parent-dir () "move current file or marked file up one dir. Created: 2025-11-12 Version: 2025-11-12" (interactive) (mapc (lambda (x) (rename-file x (concat (file-name-parent-directory (file-name-directory (car (dired-get-marked-files)))) (file-name-nondirectory x)))) (dired-get-marked-files))) ;; s------------------------------ (defun xah-move-to-parent-dir () "move current file or marked file up one dir. Created: 2025-11-12 Version: 2025-11-12" (interactive) (funcall (lambda (yy) (mapc (lambda (x) (rename-file x (concat (file-name-parent-directory (file-name-directory (car yy))) (file-name-nondirectory x)))) yy)) (dired-get-marked-files)))
(list 1 2 3) (cons 1 (cons 2 (cons 3 nil))) (cons 1 2) (car (cons 1 2)) ;; 1 (cdr (cons 1 2)) ;; 2 (car (list 1 2 3)) ;; 1 (cdr (list 1 2 3)) ;; (2 3) ;; s------------------------------ (list 1 2 3) (cons 1 (cons 2 (cons 3 nil))) (car (cdr (list 1 2 3))) ;; 2 (cadr (list 1 2 3)) ;; 2 (nth 1 (list 1 2 3)) ;; 2 ;; s------------------------------ (number-sequence 0 200) ;; (0 1 2 3 4 5 6 7 8 9 10 11 ...) (length (number-sequence 0 200)) ;; 201 (< (length mylist) 200) (length< mylist 200)