|
@@ -0,0 +1,225 @@
|
|
|
+* What
|
|
|
+ Code to do cpp ifdef-like substitution on org-mode export.
|
|
|
+* Why
|
|
|
+ Because I wanted to ifdef my resume for different versoins
|
|
|
+ (LinkedIn, etc)
|
|
|
+* How
|
|
|
+ Define functions to implmenet #define, #ifdef, etc. Add as an
|
|
|
+ org-mode export hook. Define keybindings.
|
|
|
+
|
|
|
+ See sample text below.
|
|
|
+
|
|
|
+* Who
|
|
|
+* When
|
|
|
+ To run on the current buffer by hand NOW type =C-x # b=.
|
|
|
+
|
|
|
+ To run automatically AT EXPORT, just run org-mode export. The hook should fire.
|
|
|
+
|
|
|
+* Code
|
|
|
+** ifdef keybindings and function definitions
|
|
|
+#+BEGIN_SRC emacs-lisp
|
|
|
+ (global-set-key (kbd "C-x # i") 'ifdef-ifdef)
|
|
|
+ (global-set-key (kbd "C-x # d") 'ifdef-define)
|
|
|
+ (global-set-key (kbd "C-x # b") 'ifdef-buffer)
|
|
|
+
|
|
|
+ ; define global config things for ifdef.
|
|
|
+ ; I'm pretty sure global setq is not the right way...
|
|
|
+
|
|
|
+ ; set one of these
|
|
|
+ (setq ifdef-delete-chunks t) ; delete non-matching chunks
|
|
|
+ (setq ifdef-comment-chunks nil) ; delete non-matching chunks
|
|
|
+ (setq comment-start "#")
|
|
|
+
|
|
|
+ (defun my-text-mode-hook ()
|
|
|
+ (setq comment-start "#")
|
|
|
+ ; (message "my-text-mode-hook ran.")
|
|
|
+ )
|
|
|
+
|
|
|
+ (defun my-ifdef-hook (backend)
|
|
|
+ "Apply cpp(1) style ifdefs to buffer before org-mode export."
|
|
|
+ (ifdef-org-export-hook))
|
|
|
+
|
|
|
+ (add-hook 'org-export-before-parsing-hook 'my-ifdef-hook)
|
|
|
+
|
|
|
+
|
|
|
+ (add-hook 'text-mode-hook 'my-text-mode-hook)
|
|
|
+
|
|
|
+(defun ifdef-org-export-hook ()
|
|
|
+ "Export hook to apply #ifdef logic to buffer during org-mode export"
|
|
|
+ (interactive)
|
|
|
+ (setq ifdef-delete-chunks t) ; delete non-matching chunks
|
|
|
+ (ifdef-buffer)
|
|
|
+ (ifdef-delete-all-ifdef-lines)
|
|
|
+)
|
|
|
+
|
|
|
+(defun ifdef-buffer ()
|
|
|
+ "Apply cpp-like #ifdef processing to current buffer."
|
|
|
+ (interactive)
|
|
|
+
|
|
|
+ (ifdef-define)
|
|
|
+ (goto-char (point-min))
|
|
|
+ (while (ifdef-ifdef) nil)
|
|
|
+ (ifdef-delete-all-ifdef-lines)
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+(defun ifdef-delete-all-ifdef-lines ()
|
|
|
+ "Delete all #define, #ifdef, and #endif lines in the current buffer"
|
|
|
+ (interactive)
|
|
|
+
|
|
|
+ (goto-char (point-min))
|
|
|
+
|
|
|
+ (while (re-search-forward "^\\s\-\*#\\(ifdef\\|define\\|endif\\)" nil t)
|
|
|
+ (setq pos1 (line-beginning-position) )
|
|
|
+ (forward-line 1)
|
|
|
+ (beginning-of-line)
|
|
|
+ (setq pos2 (line-beginning-position) )
|
|
|
+ (delete-region pos1 pos2)
|
|
|
+ )
|
|
|
+)
|
|
|
+
|
|
|
+(defun ifdef-define ()
|
|
|
+ "Find #ifdef FOO. (setq ifdef-condition FOO). FOO can be an elisp regexp.
|
|
|
+
|
|
|
+e.g. #define \(interesting\|contributions\)"
|
|
|
+ (interactive)
|
|
|
+ (setq ifdef-condition nil)
|
|
|
+
|
|
|
+ (let ((case-fold-search t))
|
|
|
+ (save-excursion
|
|
|
+ (goto-char (point-min))
|
|
|
+ ; first #define wins
|
|
|
+ (if (search-forward-regexp "^\\s\-\*\\(#define\\) \\(.*$\\)" nil t) (setq ifdef-condition (match-string 2)))
|
|
|
+ ) ; save-excursion
|
|
|
+ ) ;let
|
|
|
+
|
|
|
+ (message (concat (concat "ifdef-condition is \"" ifdef-condition) "\""))
|
|
|
+ ifdef-condition
|
|
|
+)
|
|
|
+
|
|
|
+(defun ifdef-ifdef ()
|
|
|
+ "Delete the next non-matching #ifdef section.
|
|
|
+
|
|
|
+Find ifdef FOO. Cut it out if conditional not defined.
|
|
|
+Return t if #ifdef section found (matching or not), nil if not found or no pattern."
|
|
|
+
|
|
|
+ (interactive)
|
|
|
+ (catch 'exit
|
|
|
+ ; (message "ifdef-ifdef")
|
|
|
+ (let ((case-fold-search t))
|
|
|
+ (if (boundp 'ifdef-condition)
|
|
|
+ (progn ; true
|
|
|
+ (setq ifdef-look-for-this (concat "#ifdef " ifdef-condition))
|
|
|
+ ; (message (concat "ifdef-look-for-this " ifdef-look-for-this))
|
|
|
+ )
|
|
|
+ (progn ; false
|
|
|
+ (message "ifdef-condition not defined")
|
|
|
+ (throw 'exit nil)
|
|
|
+ )
|
|
|
+ )
|
|
|
+ (setq ifdef-found-ifdef-section nil)
|
|
|
+
|
|
|
+ ; (message "ifdef-ifdef continue")
|
|
|
+ (let (beg end (cnt 1) ifdefChunk)
|
|
|
+ ; (save-excursion
|
|
|
+ (progn
|
|
|
+ ; (message "ifdef-ifdef looking for chunk to delete")
|
|
|
+ (when (re-search-forward
|
|
|
+ "^\\s\-\*#ifdef" nil t)
|
|
|
+
|
|
|
+ (setq beg (match-beginning 0))
|
|
|
+ (while (re-search-forward "^\\s\-\*#endif" nil t)
|
|
|
+ (setq ifdef-chunk (buffer-substring beg (point)))
|
|
|
+ ; (message (concat "ifdef-chunk-START>" ifdef-chunk "<ifdef-chunk-END"))
|
|
|
+ ; (message (concat "ifdef-look-for-this " ifdef-look-for-this))
|
|
|
+ (setq ifdef-found-ifdef-section t)
|
|
|
+ (setq ifdef-delete-or-comment-this-chunk nil)
|
|
|
+
|
|
|
+ (when (not (string-match ifdef-look-for-this ifdef-chunk))
|
|
|
+ (setq ifdef-delete-or-comment-this-chunk t))
|
|
|
+ ; (message "ifdef-delete-or-comment-this-chunk")
|
|
|
+ (if ifdef-delete-or-comment-this-chunk
|
|
|
+ (if ifdef-delete-chunks ; if delete-chunks
|
|
|
+ (progn ; if delete chunks
|
|
|
+ ; (message "deleting chunk")
|
|
|
+ (delete-region beg (point))
|
|
|
+ ; now get rid of any resulting blank lines
|
|
|
+
|
|
|
+ (setq ifdef-this-line-is-blank (looking-at "[ \t]*$"))
|
|
|
+ (setq ifdef-this-line-is-blank t)
|
|
|
+ (if ifdef-this-line-is-blank
|
|
|
+ (delete-blank-lines); collapse surrounding bank lines to one
|
|
|
+ )
|
|
|
+ )
|
|
|
+ (if ifdef-comment-chunks ; else if comment chunks
|
|
|
+ (progn
|
|
|
+ (comment-region beg (point))
|
|
|
+ )
|
|
|
+ ) ; if commenting this chunk
|
|
|
+ ) ; if deleting this chunk
|
|
|
+ ) ; if commenting or deleting this chunk
|
|
|
+
|
|
|
+ (throw 'exit ifdef-found-ifdef-section)))
|
|
|
+ nil)))))
|
|
|
+#+END_SRC
|
|
|
+
|
|
|
+* Some sample text
|
|
|
+#+BEGIN_EXAMPLE
|
|
|
+#deFine \(ALICE\|LARRY\)
|
|
|
+
|
|
|
+The start of the story is the same.
|
|
|
+
|
|
|
+#iFdef ALICE
|
|
|
+Alice is special, this message is just for her.
|
|
|
+#endif
|
|
|
+#ifdef BOB
|
|
|
+Bob gets a different story
|
|
|
+#endif
|
|
|
+#ifdef ALiCE
|
|
|
+For Alice, the story continues.
|
|
|
+#endif
|
|
|
+#ifdef BOB
|
|
|
+but Bob is left in the dark.
|
|
|
+#endif
|
|
|
+#ifdef LARRY
|
|
|
+Larry Boy. Lean and mean, green machine, outta sight, DYN-O-MITE !!!
|
|
|
+Lorum ipsum.
|
|
|
+Foo.
|
|
|
+#endif
|
|
|
+#+END_EXAMPLE
|
|
|
+
|
|
|
+* To Do List
|
|
|
+** Clean up symbols
|
|
|
+ - [X] Make everything ifdef-
|
|
|
+ - [ ] Avoid globals (setq) whehn not neede
|
|
|
+** Check logic
|
|
|
+ - [X] correct placement after ifdef-ifdef ?
|
|
|
+** Think about name of ifdef-cut
|
|
|
+ - [X] should it be something like ifdef-ifdef ?
|
|
|
+** Think about doing it without regexps
|
|
|
+ - [ ] narrow-to-region
|
|
|
+ - [ ] see Le Wang's reply to my post on G++
|
|
|
+ https://github.com/lewang/ws-butler/blob/master/ws-butler.el#L109
|
|
|
+** Inhibit ifdef expansoin of example above on export
|
|
|
+ - It would be more useful as an example if ifdef left it alone
|
|
|
+ - Probably a conditional in the export hook. Look for this file
|
|
|
+ name and skip ifdef processing, or find a way to quote the
|
|
|
+ #ifdefs
|
|
|
+** TODO Seems to only work with one #define, fix this
|
|
|
+** TODO Add #else or #ifndef
|
|
|
+
|
|
|
+* Test
|
|
|
+
|
|
|
+This is some text
|
|
|
+
|
|
|
+#define foo
|
|
|
+#define bar
|
|
|
+
|
|
|
+#ifdef foo
|
|
|
+ foo - should see this
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef bar
|
|
|
+ bar - should see this too, but seems not to work.
|
|
|
+#endif
|
|
|
+
|