diff --git a/user/app/doom-emacs/config.el b/user/app/doom-emacs/config.el index 5cc5cf9..3e9c6ab 100644 --- a/user/app/doom-emacs/config.el +++ b/user/app/doom-emacs/config.el @@ -431,25 +431,6 @@ same directory as the org-buffer and insert a link to this file." ; :desc "Simple print region in web browser" ; "r" 'org-simple-print-region) -;; Custom function to convert org mode to ODP presentation -;; Depends on bash, libreoffice, and pandoc -(defun my-ox-odp () - "Convert an org mode file to an ODP presentation." - (interactive) - (setq file-name (buffer-file-name)) - (setq output-pptx-file-name (replace-regexp-in-string "\.org" "\.pptx" (buffer-file-name))) - (setq output-odp-file-name (replace-regexp-in-string "\.org" "\.odp" (buffer-file-name))) - (setq odp-style-file-name (completing-read "Choose style: " - '("/home/emmet/.doom.d/scripts/ox-odp/styles/water.odp" - "/home/emmet/.doom.d/scripts/ox-odp/styles/dark.odp" - ) nil t)) - (shell-command (concat "~/.doom.d/scripts/ox-odp/ox-odp.sh \"" (buffer-file-name) "\" \"" odp-style-file-name "\" > /dev/null")) - ) - -(map! :leader - :desc "Convert org document to odp presentation" - "e p" 'my-ox-odp) - ;;;------ Org roam configuration ------;;; (require 'org-roam) diff --git a/user/app/doom-emacs/doom.org b/user/app/doom-emacs/doom.org index 87fa2ad..6698462 100644 --- a/user/app/doom-emacs/doom.org +++ b/user/app/doom-emacs/doom.org @@ -522,243 +522,6 @@ exit ; :desc "Simple print region in web browser" ; "r" 'org-simple-print-region) -#+END_SRC -*** Org -> ODP Presentation Export -#+BEGIN_SRC emacs-lisp :tangle config.el -;; Custom function to convert org mode to ODP presentation -;; Depends on bash, libreoffice, and pandoc -(defun my-ox-odp () - "Convert an org mode file to an ODP presentation." - (interactive) - (setq file-name (buffer-file-name)) - (setq output-pptx-file-name (replace-regexp-in-string "\.org" "\.pptx" (buffer-file-name))) - (setq output-odp-file-name (replace-regexp-in-string "\.org" "\.odp" (buffer-file-name))) - (setq odp-style-file-name (completing-read "Choose style: " - '("/home/emmet/.doom.d/scripts/ox-odp/styles/water.odp" - "/home/emmet/.doom.d/scripts/ox-odp/styles/dark.odp" - ) nil t)) - (shell-command (concat "~/.doom.d/scripts/ox-odp/ox-odp.sh \"" (buffer-file-name) "\" \"" odp-style-file-name "\" > /dev/null")) - ) - -(map! :leader - :desc "Convert org document to odp presentation" - "e p" 'my-ox-odp) - -#+END_SRC -**** Org -> ODP Helper Scripts -These are helper scripts for =my-ox-odp= (defined above), which converts an org document to an ODP presentation. This fundamentally functions by running a shell script ([[./scripts/ox-odp/ox-odp.sh][ox-odp.sh]]), which also calls a Python script ([[./scripts/ox-odp/ox-odp-xml-parse.py][ox-odp-xml-parse.py]]). -***** [[./scripts/ox-odp/ox-odp.sh][ox-odp.sh]] -#+BEGIN_SRC shell :tangle ./scripts/ox-odp/ox-odp.sh :tangle-mode (identity #o755) -#!/bin/sh - -filename=$1 -echo $filename -stylefile=$2 -echo $stylefile - -filenamebase=$(basename "$filename") -filenameext="${filenamebase##*.}" -echo $filenameext - -if [ $filenameext = "org" ]; then - stylefilebase=$(basename "$stylefile") - stylefileext="${stylefilebase##*.}" - - if [ $stylefileext = "odp" ]; then - output="${filename//\.org/\.pptx}" - finaloutput="${filename//\.org/\.odp}" - pandoc "$filename" -o "$output" - soffice --convert-to odp "$output" - unzip "$finaloutput" content.xml - unzip "$stylefile" styles.xml - - sed 's~~~g' content.xml - sed 's~~~g' content.xml - - python3 ~/.doom.d/scripts/ox-odp/ox-odp-xml-parse.py - - zip -d $finaloutput styles.xml - zip -m $finaloutput styles.xml - - zip -d $finaloutput content.xml - zip -m $finaloutput content.xml - - rm $output - - exit - - else - echo "Style file is not an odp file." - fi -else - echo "Base file is not an org file." - exit -fi - -exit - -#+END_SRC -***** [[./scripts/ox-odp/ox-odp-xml-parse.py][ox-odp-xml-parse.py]] -This script parses through the raw LibreOffice XML to fix some common formatting errors with the standard Org to pptx to odp conversion strategy. -#+BEGIN_SRC python :tangle ./scripts/ox-odp/ox-odp-xml-parse.py :tangle-mode (identity #o755) -#!/usr/bin/env python3 - -import xml.etree.ElementTree as ET -import copy - -# Read content.xml into parser -mytree = ET.parse('./content.xml') -myroot = mytree.getroot() - -# Read styles.xml into parser -styletree = ET.parse('./styles.xml') -styleroot = styletree.getroot() - -# Remove direct-formatting from text:style-name attributes in text:p elements -counter = 0 -for text in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}p'): - if '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name' in text.keys(): - stylename = text.attrib['{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name'] - if stylename[0] == "P": - counter += 1 - text.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name') -print('Deleted '+str(counter)+' text:style-name attributes in text:p elements.') - -# Remove direct-formatting from text:style-name attributes in text:span elements -counter = 0 -for span in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}span'): - if '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name' in span.keys(): - span.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name') -print('Deleted '+str(counter)+' text:style-name attributes in text:span elements.') - -# Remove direct-formatting from draw:text-style-name attributes in draw:frame elements -counter = 0 -for drawing in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}frame'): - if '{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}text-style-name' in drawing.keys(): - stylename = drawing.attrib['{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}text-style-name'] - if stylename[0] == "P": - counter += 1 - drawing.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}text-style-name') -print('Deleted '+str(counter)+' draw:text-style-name attributes in text:p elements.') - -# Redefine default styles (style:style elements) and purge unnecessary ones -counter = 0 -kounter = 0 -for style in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}style'): - if '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name' in style.keys(): - stylename = style.attrib['{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name'] - if stylename == "pr1": - counter += 1 - style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-title') - elif stylename == "pr2": - counter += 1 - style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-subtitle') - elif stylename == "pr3": - counter += 1 - style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-notes') - elif stylename == "pr4": - counter += 1 - style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-outline1') -print('Redefined '+str(counter)+' style:parent-style-name attributes in style:style elements.') -print('Deleted '+str(kounter)+' style:style elements.') - -# Search for automatic-styles element -i = 0 -col1 = 0 -while (i < len(myroot)): - print(myroot[i].tag) - if myroot[i].tag=="{urn:oasis:names:tc:opendocument:xmlns:office:1.0}automatic-styles": - col1 = i - i += 1 - -# Remove unnecessary style:style and test:list-style elements underneath automatic-styles -i = 0 -while (i < len(myroot[col1])): - if (myroot[col1][i].tag == "{urn:oasis:names:tc:opendocument:xmlns:style:1.0}style"): - if ("{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name" in myroot[col1][i].keys()): - if myroot[col1][i].attrib["{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name"] in ["pr5","pr6","pr7","pr8","pr9"]: - print("Removing "+myroot[col1][i].tag) - myroot[col1].remove(myroot[col1][i]) - i -= 1 - elif myroot[col1][i].attrib["{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name"][0] == "P": - print("Removing "+myroot[col1][i].tag) - myroot[col1].remove(myroot[col1][i]) - i -= 1 - if (myroot[col1][i].tag == "{urn:oasis:names:tc:opendocument:xmlns:text:1.0}list-style"): - print("Removing "+myroot[col1][i].tag) - myroot[col1].remove(myroot[col1][i]) - i -= 1 - i += 1 - -#i = 0 -#while (i < len(myroot[col1])): -# print(myroot[col1][i].attrib) -# i += 1 - -# Find ML1 in styles.xml and copy it into L1 in content.xml -# Search for automatic-styles element -i = 0 -stylecol1 = 0 -while (i < len(styleroot)): - print(styleroot[i].tag) - if styleroot[i].tag=="{urn:oasis:names:tc:opendocument:xmlns:office:1.0}automatic-styles": - stylecol1 = i - i += 1 - -# Remove unnecessary style:style and test:list-style elements underneath automatic-styles -i = 0 -while (i < len(styleroot[stylecol1])): - if (styleroot[stylecol1][i].tag == "{urn:oasis:names:tc:opendocument:xmlns:text:1.0}list-style"): - if (styleroot[stylecol1][i].attrib["{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name"] == "ML1"): - liststyle_copy = copy.deepcopy(styleroot[stylecol1][i]) - myroot[col1].append(liststyle_copy) - myroot[col1][-1].attrib['{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name'] = "L1" - i += 1 - -# Update presentation:style-name attribute of all draw:frame elements -counter = 0 -for frame in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}frame'): - if '{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}class' in frame.keys(): - classname = frame.attrib['{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}class'] - if classname == "title": - counter += 1 - frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr1') - elif classname == "subtitle": - counter += 1 - frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr2') - elif classname == "notes": - counter += 1 - frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr3') - elif classname == "outline": - counter += 1 - frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr4') -print("Updated "+str(counter)+" draw:frame elements") - -# Update draw:master-page-name attributes in all draw:page elements -# Also delete all presentation:presentation-page-layout attributes -counter = 0 -for page in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}page'): - if '{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}master-page-name' in page.keys(): - page.set('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}master-page-name','DefaultTheme') - counter += 1 - if '{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}presentation-page-layout' in page.keys(): - page.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}presentation-page-layout') - -print("Updated "+str(counter)+" draw:page elements") - -# Update all text:list elements to have text:style-name = L1 -counter = 0 -for page in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}list'): - if '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name' in page.keys(): - page.set('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name','L1') - counter += 1 - -print("Updated "+str(counter)+" text:list elements") - -#mytree.canonicalize(out='content.xml') -mytree.write('content.xml') -styletree.write('styles.xml') - #+END_SRC ** Org Roam Configuration *** Standard Org Roam Configuration diff --git a/user/app/doom-emacs/scripts/ox-odp/ox-odp-xml-parse.py b/user/app/doom-emacs/scripts/ox-odp/ox-odp-xml-parse.py deleted file mode 100755 index e4f34e0..0000000 --- a/user/app/doom-emacs/scripts/ox-odp/ox-odp-xml-parse.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env python3 - -import xml.etree.ElementTree as ET -import copy - -# Read content.xml into parser -mytree = ET.parse('./content.xml') -myroot = mytree.getroot() - -# Read styles.xml into parser -styletree = ET.parse('./styles.xml') -styleroot = styletree.getroot() - -# Remove direct-formatting from text:style-name attributes in text:p elements -counter = 0 -for text in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}p'): - if '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name' in text.keys(): - stylename = text.attrib['{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name'] - if stylename[0] == "P": - counter += 1 - text.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name') -print('Deleted '+str(counter)+' text:style-name attributes in text:p elements.') - -# Remove direct-formatting from text:style-name attributes in text:span elements -counter = 0 -for span in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}span'): - if '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name' in span.keys(): - span.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name') -print('Deleted '+str(counter)+' text:style-name attributes in text:span elements.') - -# Remove direct-formatting from draw:text-style-name attributes in draw:frame elements -counter = 0 -for drawing in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}frame'): - if '{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}text-style-name' in drawing.keys(): - stylename = drawing.attrib['{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}text-style-name'] - if stylename[0] == "P": - counter += 1 - drawing.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}text-style-name') -print('Deleted '+str(counter)+' draw:text-style-name attributes in text:p elements.') - -# Redefine default styles (style:style elements) and purge unnecessary ones -counter = 0 -kounter = 0 -for style in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}style'): - if '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name' in style.keys(): - stylename = style.attrib['{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name'] - if stylename == "pr1": - counter += 1 - style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-title') - elif stylename == "pr2": - counter += 1 - style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-subtitle') - elif stylename == "pr3": - counter += 1 - style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-notes') - elif stylename == "pr4": - counter += 1 - style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-outline1') -print('Redefined '+str(counter)+' style:parent-style-name attributes in style:style elements.') -print('Deleted '+str(kounter)+' style:style elements.') - -# Search for automatic-styles element -i = 0 -col1 = 0 -while (i < len(myroot)): - print(myroot[i].tag) - if myroot[i].tag=="{urn:oasis:names:tc:opendocument:xmlns:office:1.0}automatic-styles": - col1 = i - i += 1 - -# Remove unnecessary style:style and test:list-style elements underneath automatic-styles -i = 0 -while (i < len(myroot[col1])): - if (myroot[col1][i].tag == "{urn:oasis:names:tc:opendocument:xmlns:style:1.0}style"): - if ("{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name" in myroot[col1][i].keys()): - if myroot[col1][i].attrib["{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name"] in ["pr5","pr6","pr7","pr8","pr9"]: - print("Removing "+myroot[col1][i].tag) - myroot[col1].remove(myroot[col1][i]) - i -= 1 - elif myroot[col1][i].attrib["{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name"][0] == "P": - print("Removing "+myroot[col1][i].tag) - myroot[col1].remove(myroot[col1][i]) - i -= 1 - if (myroot[col1][i].tag == "{urn:oasis:names:tc:opendocument:xmlns:text:1.0}list-style"): - print("Removing "+myroot[col1][i].tag) - myroot[col1].remove(myroot[col1][i]) - i -= 1 - i += 1 - -#i = 0 -#while (i < len(myroot[col1])): -# print(myroot[col1][i].attrib) -# i += 1 - -# Find ML1 in styles.xml and copy it into L1 in content.xml -# Search for automatic-styles element -i = 0 -stylecol1 = 0 -while (i < len(styleroot)): - print(styleroot[i].tag) - if styleroot[i].tag=="{urn:oasis:names:tc:opendocument:xmlns:office:1.0}automatic-styles": - stylecol1 = i - i += 1 - -# Remove unnecessary style:style and test:list-style elements underneath automatic-styles -i = 0 -while (i < len(styleroot[stylecol1])): - if (styleroot[stylecol1][i].tag == "{urn:oasis:names:tc:opendocument:xmlns:text:1.0}list-style"): - if (styleroot[stylecol1][i].attrib["{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name"] == "ML1"): - liststyle_copy = copy.deepcopy(styleroot[stylecol1][i]) - myroot[col1].append(liststyle_copy) - myroot[col1][-1].attrib['{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name'] = "L1" - i += 1 - -# Update presentation:style-name attribute of all draw:frame elements -counter = 0 -for frame in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}frame'): - if '{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}class' in frame.keys(): - classname = frame.attrib['{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}class'] - if classname == "title": - counter += 1 - frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr1') - elif classname == "subtitle": - counter += 1 - frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr2') - elif classname == "notes": - counter += 1 - frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr3') - elif classname == "outline": - counter += 1 - frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr4') -print("Updated "+str(counter)+" draw:frame elements") - -# Update draw:master-page-name attributes in all draw:page elements -# Also delete all presentation:presentation-page-layout attributes -counter = 0 -for page in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}page'): - if '{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}master-page-name' in page.keys(): - page.set('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}master-page-name','DefaultTheme') - counter += 1 - if '{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}presentation-page-layout' in page.keys(): - page.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}presentation-page-layout') - -print("Updated "+str(counter)+" draw:page elements") - -# Update all text:list elements to have text:style-name = L1 -counter = 0 -for page in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}list'): - if '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name' in page.keys(): - page.set('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name','L1') - counter += 1 - -print("Updated "+str(counter)+" text:list elements") - -#mytree.canonicalize(out='content.xml') -mytree.write('content.xml') -styletree.write('styles.xml') diff --git a/user/app/doom-emacs/scripts/ox-odp/ox-odp.sh b/user/app/doom-emacs/scripts/ox-odp/ox-odp.sh deleted file mode 100755 index 47dc7ce..0000000 --- a/user/app/doom-emacs/scripts/ox-odp/ox-odp.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh - -filename=$1 -echo $filename -stylefile=$2 -echo $stylefile - -filenamebase=$(basename "$filename") -filenameext="${filenamebase##*.}" -echo $filenameext - -if [ $filenameext = "org" ]; then - stylefilebase=$(basename "$stylefile") - stylefileext="${stylefilebase##*.}" - - if [ $stylefileext = "odp" ]; then - output="${filename//\.org/\.pptx}" - finaloutput="${filename//\.org/\.odp}" - pandoc "$filename" -o "$output" - soffice --convert-to odp "$output" - unzip "$finaloutput" content.xml - unzip "$stylefile" styles.xml - - sed 's~~~g' content.xml - sed 's~~~g' content.xml - - python3 ~/.doom.d/scripts/ox-odp/ox-odp-xml-parse.py - - zip -d $finaloutput styles.xml - zip -m $finaloutput styles.xml - - zip -d $finaloutput content.xml - zip -m $finaloutput content.xml - - rm $output - - exit - - else - echo "Style file is not an odp file." - fi -else - echo "Base file is not an org file." - exit -fi - -exit