summaryrefslogtreecommitdiff
path: root/config.org
diff options
context:
space:
mode:
Diffstat (limited to 'config.org')
-rw-r--r--config.org145
1 files changed, 9 insertions, 136 deletions
diff --git a/config.org b/config.org
index 462fbc5..27bc979 100644
--- a/config.org
+++ b/config.org
@@ -332,128 +332,12 @@ reports.
(defvar ss/people-roster--cache-mtime nil
"Modification time of the cached roster entries.")
- (defun ss/people-roster--split-values (value)
- "Split VALUE on commas or semicolons and trim each item."
- (when (and value (not (string-empty-p value)))
- (seq-filter
- (lambda (string) (not (string-empty-p string)))
- (mapcar #'string-trim (split-string value "[,;]" t)))))
-
- (defun ss/people-roster--normalize-engagement (employee-time)
- "Map the CSV EMPLOYEE-TIME field to a roster engagement category."
- (cond ((or (null employee-time) (string-empty-p employee-time)) nil)
- ((string-match-p "\\`Perm\\'" employee-time) "permanent")
- ((string-match-p "\\`NCS India\\'" employee-time) "permanent")
- ((string-match-p "\\`SOW" employee-time) "sow")
- (t (downcase employee-time))))
-
- (defun ss/people-roster--csv-header-key (header)
- "Convert a CSV HEADER to a plist keyword."
- (intern
- (concat ":"
- (replace-regexp-in-string
- "[^[:alnum:]]+" "-"
- (downcase (string-trim header))))))
-
- (defun ss/people-roster--csv-row-values (line)
- "Split a CSV LINE into trimmed values."
- (mapcar #'string-trim
- (split-string (string-trim-right line "\r") "," nil)))
-
- (defun ss/people-roster--csv-row-plist (headers values)
- "Zip HEADERS and VALUES into a plist."
- (let ((plist nil))
- (while headers
- (setq plist (plist-put plist (pop headers) (or (pop values) ""))))
- plist))
-
- (defun ss/people-roster--csv-rows ()
- "Return the rows from `ss/people-roster-source-file'."
- (when (file-exists-p ss/people-roster-source-file)
- (with-temp-buffer
- (insert-file-contents ss/people-roster-source-file)
- (let* ((lines (split-string (buffer-string) "\n" t))
- (headers (mapcar #'ss/people-roster--csv-header-key
- (ss/people-roster--csv-row-values (car lines)))))
- (mapcar (lambda (line)
- (ss/people-roster--csv-row-plist
- headers
- (ss/people-roster--csv-row-values line)))
- (cdr lines))))))
-
- (defun ss/people-roster--csv-row->entry (row)
- "Convert CSV ROW to a roster entry plist."
- (let ((name (string-trim (or (plist-get row :name) "")))
- (role (string-trim (or (plist-get row :role)
- (plist-get row :title)
- "")))
- (employee-time (string-trim (or (plist-get row :employee-time) "")))
- (team (string-trim (or (plist-get row :team) "")))
- (abbrev (string-trim (or (plist-get row :abbrev) "")))
- (aliases (ss/people-roster--split-values (plist-get row :aliases)))
- (manager (string-trim (or (plist-get row :manager) "")))
- (email (string-trim (or (plist-get row :email) "")))
- (location (string-trim (or (plist-get row :location) "")))
- (engagement (string-trim
- (or (plist-get row :engagement)
- (ss/people-roster--normalize-engagement employee-time)
- ""))))
- (list :name name
- :abbrev (if (string-empty-p abbrev)
- (ss/name-dictionary-default-abbrev name)
- abbrev)
- :aliases aliases
- :role role
- :employee-time employee-time
- :engagement engagement
- :team team
- :manager manager
- :email email
- :location location)))
-
(defun ss/people-roster--org-property-line (key value)
"Return an Org property line for KEY and VALUE, or the empty string."
(if (and value (not (string-empty-p value)))
(format ":%s: %s\n" key value)
""))
- (defun ss/people-roster--csv-entry-to-org (entry)
- "Render ENTRY as an Org headline with properties."
- (let ((name (ss/people-roster--entry-name entry))
- (abbrev (ss/people-roster--entry-abbrev entry))
- (aliases (ss/people-roster--entry-aliases entry))
- (role (ss/people-roster--entry-role entry))
- (employee-time (plist-get entry :employee-time))
- (engagement (ss/people-roster--entry-engagement entry))
- (team (ss/people-roster--entry-team entry))
- (manager (ss/people-roster--entry-manager entry))
- (email (ss/people-roster--entry-email entry))
- (location (ss/people-roster--entry-location entry)))
- (concat
- "* " name "\n"
- ":PROPERTIES:\n"
- (ss/people-roster--org-property-line "NAME" name)
- (ss/people-roster--org-property-line "ABBREV" abbrev)
- (ss/people-roster--org-property-line "ALIASES" (mapconcat #'identity aliases "; "))
- (ss/people-roster--org-property-line "EMPLOYEE-TIME" employee-time)
- (ss/people-roster--org-property-line "ROLE" role)
- (ss/people-roster--org-property-line "ENGAGEMENT" engagement)
- (ss/people-roster--org-property-line "TEAM" team)
- (ss/people-roster--org-property-line "MANAGER" manager)
- (ss/people-roster--org-property-line "EMAIL" email)
- (ss/people-roster--org-property-line "LOCATION" location)
- ":END:\n\n")))
-
- (defun ss/people-roster--seed-from-csv ()
- "Write the roster file from the CSV seed data."
- (let ((entries (mapcar #'ss/people-roster--csv-row->entry
- (ss/people-roster--csv-rows))))
- (with-temp-file ss/people-roster-file
- (insert "#+title: People roster\n\n")
- (dolist (entry entries)
- (insert (ss/people-roster--csv-entry-to-org entry))))
- entries))
-
(defun ss/people-roster--entry-name (entry)
"Return the canonical name in ENTRY."
(plist-get entry :name))
@@ -494,6 +378,13 @@ reports.
"Return the location in ENTRY."
(plist-get entry :location))
+ (defun ss/people-roster--split-values (value)
+ "Split VALUE on commas or semicolons and trim each item."
+ (when (and value (not (string-empty-p value)))
+ (seq-filter
+ (lambda (string) (not (string-empty-p string)))
+ (mapcar #'string-trim (split-string value "[,;]" t)))))
+
(defun ss/people-roster--entry-summary (entry)
"Return a one-line summary for ENTRY."
(string-join
@@ -525,24 +416,10 @@ reports.
"Create the roster file when it is missing."
(make-directory (file-name-directory ss/people-roster-file) t)
(unless (file-exists-p ss/people-roster-file)
- (if (file-exists-p ss/people-roster-source-file)
- (ss/people-roster--seed-from-csv)
- (with-temp-file ss/people-roster-file
- (insert "#+title: People roster\n\n"))))
+ (with-temp-file ss/people-roster-file
+ (insert "#+title: People roster\n\n")))
ss/people-roster-file)
- (defun ss/people-roster-seed-from-csv (&optional overwrite)
- "Seed the roster file from the CSV source.
-With OVERWRITE, rebuild the roster even when it already exists."
- (interactive "P")
- (when (and (file-exists-p ss/people-roster-file) (not overwrite))
- (user-error "Roster already exists; use C-u M-x ss/people-roster-seed-from-csv to rebuild it"))
- (unless (file-exists-p ss/people-roster-source-file)
- (user-error "Missing seed CSV: %s" ss/people-roster-source-file))
- (ss/people-roster--seed-from-csv)
- (ss/people-roster-reload)
- (message "Seeded people roster from CSV"))
-
(defun ss/people-roster-entries ()
"Return the structured roster entries from `ss/people-roster-file'."
(let* ((attributes (and (file-exists-p ss/people-roster-file)
@@ -975,10 +852,6 @@ directly during startup rather than creating it on demand.
(expand-file-name "areas/people/roster.org" ss/org-directory)
"Structured roster of people and role metadata.")
- (defconst ss/people-roster-source-file
- (expand-file-name "people.csv" user-emacs-directory)
- "CSV seed data for the roster.")
-
(defconst ss/org-resources-directory (expand-file-name "resources/" ss/org-directory)
"Directory for resource notes.")