summaryrefslogtreecommitdiff
path: root/modules/hugo-config.el
blob: 8bc2cef285ee6f4bed5a487b0616e91765c828b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
;;; hugo-config.el --- Hugo Blog Configuration -*- lexical-binding: t; coding: utf-8; -*-
;; author: Craig Jennings <c@cjennings.net>

;;; Commentary:
;; Integrates ox-hugo for publishing Org files to a Hugo website.
;;
;; One-file-per-post workflow:
;; - Each blog post is a standalone Org file in content-org/log/
;; - File-level keywords control Hugo front matter
;; - Export with C-; h e, create new posts with C-; h n
;;
;; Keybindings (C-; h prefix):
;; - C-; h n : New post (create from template)
;; - C-; h e : Export current post to Hugo markdown
;; - C-; h o : Open blog source directory in dirvish
;; - C-; h O : Open blog source directory in system file manager
;; - C-; h d : Toggle draft status (TODO/DONE)

;;; Code:

(require 'user-constants)
(require 'host-environment)

;; --------------------------------- Constants ---------------------------------

(defconst cj/hugo-content-org-dir
  (expand-file-name "content-org/log/" website-dir)
  "Directory containing Org source files for Hugo blog posts.")

;; ---------------------------------- ox-hugo ----------------------------------

(use-package ox-hugo
  :after ox)

;; ----------------------------- Hugo Blog Functions ---------------------------

(defun cj/hugo-new-post ()
  "Create a new Hugo blog post as a standalone Org file.
Prompts for title, generates the slug filename, and opens the
new file with Hugo front matter keywords pre-filled."
  (interactive)
  (require 'ox-hugo)
  (let* ((title (read-from-minibuffer "Post Title: "))
         (slug (org-hugo-slug title))
         (date (format-time-string "%Y-%m-%d"))
         (file (expand-file-name (concat slug ".org") cj/hugo-content-org-dir)))
    (when (file-exists-p file)
      (user-error "Post already exists: %s" file))
    (unless (file-directory-p cj/hugo-content-org-dir)
      (make-directory cj/hugo-content-org-dir t))
    (find-file file)
    (insert (format "#+hugo_base_dir: ../../
#+hugo_section: log
#+hugo_auto_set_lastmod: t
#+title: %s
#+date: %s
#+hugo_tags:
#+hugo_draft: true
#+hugo_custom_front_matter: :description \"\"

" title date))
    (save-buffer)
    (message "New post: %s" file)))

(defun cj/hugo-export-post ()
  "Export the current Org file to Hugo-compatible Markdown."
  (interactive)
  (require 'ox-hugo)
  (unless (derived-mode-p 'org-mode)
    (user-error "Not in an Org buffer"))
  (org-hugo-export-to-md)
  (message "Exported: %s" (buffer-name)))

(defun cj/hugo-open-blog-dir ()
  "Open the blog source directory in dirvish/dired."
  (interactive)
  (unless (file-directory-p cj/hugo-content-org-dir)
    (make-directory cj/hugo-content-org-dir t))
  (dired cj/hugo-content-org-dir))

(defun cj/hugo-open-blog-dir-external ()
  "Open the blog source directory in the system file manager."
  (interactive)
  (unless (file-directory-p cj/hugo-content-org-dir)
    (make-directory cj/hugo-content-org-dir t))
  (let ((cmd (cond
              ((env-macos-p) "open")
              ((env-windows-p) "explorer.exe")
              (t "xdg-open"))))
    (start-process "hugo-file-manager" nil cmd cj/hugo-content-org-dir)))

(defun cj/hugo-toggle-draft ()
  "Toggle the draft status of the current Hugo post.
Switches #+hugo_draft between true and false."
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (if (re-search-forward "^#\\+hugo_draft: *\\(true\\|false\\)" nil t)
        (let ((current (match-string 1)))
          (replace-match (if (string= current "true") "false" "true") t t nil 1)
          (save-buffer)
          (message "Draft: %s → %s" current
                   (if (string= current "true") "false" "true")))
      (user-error "No #+hugo_draft keyword found in this file"))))

;; -------------------------------- Keybindings --------------------------------

(global-set-key (kbd "C-; h n") #'cj/hugo-new-post)
(global-set-key (kbd "C-; h e") #'cj/hugo-export-post)
(global-set-key (kbd "C-; h o") #'cj/hugo-open-blog-dir)
(global-set-key (kbd "C-; h O") #'cj/hugo-open-blog-dir-external)
(global-set-key (kbd "C-; h d") #'cj/hugo-toggle-draft)

(with-eval-after-load 'which-key
  (which-key-add-key-based-replacements
    "C-; h" "hugo blog menu"
    "C-; h n" "new post"
    "C-; h e" "export post"
    "C-; h o" "open in dirvish"
    "C-; h O" "open in file manager"
    "C-; h d" "toggle draft"))

(provide 'hugo-config)
;;; hugo-config.el ends here