summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Gonzalez <roger@rogs.me>2022-08-09 15:20:11 -0300
committerRoger Gonzalez <roger@rogs.me>2022-08-09 15:20:11 -0300
commit269c2695f989c68c2aadff12c7f57741c0363c64 (patch)
treee4a401b4101bea0c844f21ec2ff9b2ea91757c6c
parent11110f25c9a214e15566e04af6ff989a96fdd53f (diff)
Added extra doom emacs scripts
-rw-r--r--.doom.d/custom-packages/ox-slack.el366
-rw-r--r--.doom.d/custom-packages/screenshot.el460
-rw-r--r--.doom.d/scripts/ics-to-org.el1
-rwxr-xr-x.doom.d/scripts/ics-to-org.sh22
4 files changed, 849 insertions, 0 deletions
diff --git a/.doom.d/custom-packages/ox-slack.el b/.doom.d/custom-packages/ox-slack.el
new file mode 100644
index 00000000..7f930277
--- /dev/null
+++ b/.doom.d/custom-packages/ox-slack.el
@@ -0,0 +1,366 @@
+;;; ox-slack.el --- Slack Exporter for org-mode -*- lexical-binding: t; -*-
+
+
+;; Copyright (C) 2018 Matt Price
+
+;; Author: Matt Price
+;; Keywords: org, slack, outlines
+;; Package-Version: 0.1.1
+;; Package-Requires: ((emacs "24") (org "9.1.4") (ox-gfm "1.0"))
+;; URL: https://github.com/titaniumbones/ox-slack
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library implements a Slack backend for the Org
+;; exporter, based on the `md' and `gfm' back-ends.
+
+;;; Code:
+
+(require 'ox-gfm)
+
+(org-export-define-derived-backend 'slack 'gfm
+ ;; for now, I just have this commented out
+ ;; might be better to create a defcustom to
+ ;; decide whether to add this to the export dispatcher
+ ;; :menu-entry
+ ;; '(?s "Export to Slack syntax"
+ ;; ((?s "To temporary buffer"
+ ;; (lambda (a s v b) (org-slack-export-as-slack a s v)))
+ ;; (?S "To file" (lambda (a s v b) (org-slack-export-to-slack a s v)))
+ ;; (?o "To file and open"
+ ;; (lambda (a s v b)
+ ;; (if a (org-slack-export-to-slack t s v)
+ ;; (org-open-file (org-slack-export-to-slack nil s v)))))))
+ :translate-alist
+ '(
+ (bold . org-slack-bold)
+ (code . org-slack-code)
+ (headline . org-slack-headline)
+ (inner-template . org-slack-inner-template)
+ (italic . org-slack-italic)
+ (link . org-slack-link)
+ (plain-text . org-slack-plain-text)
+ (src-block . org-slack-src-block)
+ (strike-through . org-slack-strike-through)
+ (timestamp . org-slack-timestamp)))
+
+;; timestamp
+(defun org-slack-timestamp (timestamp contents info)
+ "Transcode TIMESTAMP element into Slack format.
+CONTENTS is the timestamp contents. INFO is a plist used as a
+ocmmunications channel."
+ (org-html-plain-text (org-timestamp-translate timestamp) info))
+
+;; headline
+(defun org-slack-headline (headline contents info)
+ "Transcode HEADLINE element into Markdown format.
+CONTENTS is the headline contents. INFO is a plist used as
+a communication channel."
+ (unless (org-element-property :footnote-section-p headline)
+ (let* ((level (org-export-get-relative-level headline info))
+ (title (org-export-data (org-element-property :title headline) info))
+ (todo (and (plist-get info :with-todo-keywords)
+ (let ((todo (org-element-property :todo-keyword
+ headline)))
+ (and todo (concat (org-export-data todo info) " ")))))
+ (tags (and (plist-get info :with-tags)
+ (let ((tag-list (org-export-get-tags headline info)))
+ (and tag-list
+ (concat " " (org-make-tag-string tag-list))))))
+ (priority
+ (and (plist-get info :with-priority)
+ (let ((char (org-element-property :priority headline)))
+ (and char (format "[#%c] " char)))))
+ ;; Headline text without tags.
+ (heading (concat todo priority title)))
+ (format "*%s*\n\n%s" title contents)
+ )))
+
+;; link
+(defun org-slack-link (link contents info)
+ "Transcode LINK object into Markdown format.
+ CONTENTS is the link's description. INFO is a plist used as
+ a communication channel."
+ (let ((link-org-files-as-md
+ (lambda (raw-path)
+ ;; Treat links to `file.org' as links to `file.md'.
+ (if (string= ".org" (downcase (file-name-extension raw-path ".")))
+ (concat (file-name-sans-extension raw-path) ".md")
+ raw-path)))
+ (type (org-element-property :type link)))
+ (cond
+ ;; Link type is handled by a special function.
+ ((org-export-custom-protocol-maybe link contents 'md))
+ ((member type '("custom-id" "id" "fuzzy"))
+ (let ((destination (if (string= type "fuzzy")
+ (org-export-resolve-fuzzy-link link info)
+ (org-export-resolve-id-link link info))))
+ (pcase (org-element-type destination)
+ (`plain-text ; External file.
+ (let ((path (funcall link-org-files-as-md destination)))
+ (if (not contents) (format "%s>" path)
+ (format "[%s](%s)" contents path))))
+ (`headline
+ (format
+ ;; "[%s](#%s)"
+ "[%s]"
+ ;; Description.
+ (cond ((org-string-nw-p contents))
+ ((org-export-numbered-headline-p destination info)
+ (mapconcat #'number-to-string
+ (org-export-get-headline-number destination info)
+ "."))
+ (t (org-export-data (org-element-property :title destination)
+ info)))
+ ;; Reference.
+ ;; (or (org-element-property :CUSTOM_ID destination)
+ ;; (org-export-get-reference destination info))
+ ))
+ (_
+ (let ((description
+ (or (org-string-nw-p contents)
+ (let ((number (org-export-get-ordinal destination info)))
+ (cond
+ ((not number) nil)
+ ((atom number) (number-to-string number))
+ (t (mapconcat #'number-to-string number ".")))))))
+ (when description
+ (format "[%s]"
+ description
+ ;; (org-export-get-reference destination info)
+ )))))))
+ ((org-export-inline-image-p link org-html-inline-image-rules)
+ (let ((path (let ((raw-path (org-element-property :path link)))
+ (cond ((not (equal "file" type)) (concat type ":" raw-path))
+ ((not (file-name-absolute-p raw-path)) raw-path)
+ (t (expand-file-name raw-path)))))
+ (caption (org-export-data
+ (org-export-get-caption
+ (org-export-get-parent-element link)) info)))
+ (format "![img](%s)"
+ (if (not (org-string-nw-p caption)) path
+ (format "%s \"%s\"" path caption)))))
+ ((string= type "coderef")
+ (let ((ref (org-element-property :path link)))
+ (format (org-export-get-coderef-format ref contents)
+ (org-export-resolve-coderef ref info))))
+ ((equal type "radio") contents)
+ (t (let* ((raw-path (org-element-property :path link))
+ (path
+ (cond
+ ((member type '("http" "https" "ftp" "mailto"))
+ (concat type ":" raw-path))
+ ((string= type "file")
+ (org-export-file-uri (funcall link-org-files-as-md raw-path)))
+ (t raw-path))))
+ (if (not contents) (format "%s" path)
+ (format "[%s](%s)" contents path)))))))
+
+(defun org-slack-verbatim (_verbatim contents _info)
+ "Transcode VERBATIM from Org to Slack.
+ CONTENTS is the text with bold markup. INFO is a plist holding
+ contextual information."
+ (format "`%s`" contents))
+
+(defun org-slack-code (code _contents info)
+ "Return a CODE object from Org to SLACK.
+ CONTENTS is nil. INFO is a plist holding contextual
+ information."
+ (format "`%s`"
+ (org-element-property :value code)))
+
+ ;;;; Italic
+
+(defun org-slack-italic (_italic contents _info)
+ "Transcode italic from Org to SLACK.
+ CONTENTS is the text with italic markup. INFO is a plist holding
+ contextual information."
+ (format "_%s_" contents))
+
+ ;;; Bold
+(defun org-slack-bold (_bold contents _info)
+ "Transcode bold from Org to SLACK.
+ CONTENTS is the text with bold markup. INFO is a plist holding
+ contextual information."
+ (format "*%s*" contents))
+
+
+;;;; Strike-through
+(defun org-slack-strike-through (_strike-through contents _info)
+ "Transcode STRIKE-THROUGH from Org to SLACK.
+ CONTENTS is text with strike-through markup. INFO is a plist
+ holding contextual information."
+ (format "~%s~" contents))
+
+
+(defun org-slack-inline-src-block (inline-src-block _contents info)
+ "Transcode an INLINE-SRC-BLOCK element from Org to SLACK.
+ CONTENTS holds the contents of the item. INFO is a plist holding
+ contextual information."
+ (format "`%s`"
+ (org-element-property :value inline-src-block)))
+
+;;;; Src Block
+(defun org-slack-src-block (src-block contents info)
+ "Transcode SRC-BLOCK element into Github Flavored Markdown format.
+ CONTENTS is nil. INFO is a plist used as a communication
+ channel."
+ (let* ((lang (org-element-property :language src-block))
+ (code (org-export-format-code-default src-block info))
+ (prefix (concat "```" "\n"))
+ (suffix "```"))
+ (concat prefix code suffix)))
+
+;;;; Quote Block
+(defun org-slack-quote-block (_quote-block contents info)
+ "Transcode a QUOTE-BLOCK element from Org to SLACK.
+ CONTENTS holds the contents of the block. INFO is a plist
+ holding contextual information."
+ (org-slack--indent-string contents (plist-get info :slack-quote-margin)))
+
+
+(defun org-slack-inner-template (contents info)
+ "Return body of document after converting it to Markdown syntax.
+ CONTENTS is the transcoded contents string. INFO is a plist
+ holding export options."
+ ;; Make sure CONTENTS is separated from table of contents and
+ ;; footnotes with at least a blank line.
+ (concat
+ ;; Table of contents.
+ ;; (let ((depth (plist-get info :with-toc)))
+ ;; (when depth
+ ;; (concat (org-md--build-toc info (and (wholenump depth) depth)) "\n")))
+ ;; Document contents.
+ contents
+ "\n"
+ ;; Footnotes section.
+ (org-md--footnote-section info)))
+
+;;;; Plain text
+(defun org-slack-plain-text (text info)
+ "Transcode a TEXT string into Markdown format.
+ TEXT is the string to transcode. INFO is a plist holding
+ contextual information."
+ ;; (when (plist-get info :with-smart-quotes)
+ ;; (setq text (org-export-activate-smart-quotes text :html info)))
+ ;; The below series of replacements in `text' is order sensitive.
+ ;; Protect `, *, _, and \
+ ;; (setq text (replace-regexp-in-string "[`*_\\]" "\\\\\\&" text))
+ ;; Protect ambiguous #. This will protect # at the beginning of
+ ;; a line, but not at the beginning of a paragraph. See
+ ;; `org-md-paragraph'.
+ (setq text (replace-regexp-in-string "\n#" "\n\\\\#" text))
+ ;; Protect ambiguous !
+ (setq text (replace-regexp-in-string "\\(!\\)\\[" "\\\\!" text nil nil 1))
+ ;; ;; Handle special strings, if required.
+ ;; (when (plist-get info :with-special-strings)
+ ;; (setq text (org-html-convert-special-strings text)))
+ ;; Handle break preservation, if required.
+ (when (plist-get info :preserve-breaks)
+ (setq text (replace-regexp-in-string "[ \t]*\n" " \n" text)))
+ ;; Return value.
+ text)
+
+;;; End-user functions
+
+;;;###autoload
+(defun org-slack-export-as-slack
+ (&optional async subtreep visible-only body-only ext-plist)
+ "Export current buffer to a text buffer.
+
+ If narrowing is active in the current buffer, only export its
+ narrowed part.
+
+ If a region is active, export that region.
+
+ A non-nil optional argument ASYNC means the process should happen
+ asynchronously. The resulting buffer should be accessible
+ through the `org-export-stack' interface.
+
+ When optional argument SUBTREEP is non-nil, export the sub-tree
+ at point, extracting information from the headline properties
+ first.
+
+ When optional argument VISIBLE-ONLY is non-nil, don't export
+ contents of hidden elements.
+
+ When optional argument BODY-ONLY is non-nil, strip title and
+ table of contents from output.
+
+ EXT-PLIST, when provided, is a property list with external
+ parameters overriding Org default settings, but still inferior to
+ file-local settings.
+
+ Export is done in a buffer named \"*Org SLACK Export*\", which
+ will be displayed when `org-export-show-temporary-export-buffer'
+ is non-nil."
+ (interactive)
+ (org-export-to-buffer 'slack "*Org SLACK Export*"
+ async subtreep visible-only body-only ext-plist (lambda () (text-mode))))
+
+;;;###autoload
+(defun org-slack-export-to-slack
+ (&optional async subtreep visible-only body-only ext-plist)
+ "Export current buffer to a text file.
+
+ If narrowing is active in the current buffer, only export its
+ narrowed part.
+
+ If a region is active, export that region.
+
+ A non-nil optional argument ASYNC means the process should happen
+ asynchronously. The resulting file should be accessible through
+ the `org-export-stack' interface.
+
+ When optional argument SUBTREEP is non-nil, export the sub-tree
+ at point, extracting information from the headline properties
+ first.
+
+ When optional argument VISIBLE-ONLY is non-nil, don't export
+ contents of hidden elements.
+
+ When optional argument BODY-ONLY is non-nil, strip title and
+ table of contents from output.
+
+ EXT-PLIST, when provided, is a property list with external
+ parameters overriding Org default settings, but still inferior to
+ file-local settings.
+
+ Return output file's name."
+ (interactive)
+ (let ((file (org-export-output-file-name ".txt" subtreep)))
+ (org-export-to-file 'slack file
+ async subtreep visible-only body-only ext-plist)))
+
+;;;###autoload
+(defun org-slack-export-to-clipboard-as-slack ()
+ "Export region to slack, and copy to the kill ring for pasting into other programs."
+ (interactive)
+ (let* ((org-export-with-toc nil)
+ (org-export-with-smart-quotes nil))
+ (kill-new (org-export-as 'slack) ))
+ )
+
+;; (org-export-register-backend 'slack)
+(provide 'ox-slack)
+
+;; Local variables:
+;; coding: utf-8
+;; End:
+
+;;; ox-slack.el ends here
diff --git a/.doom.d/custom-packages/screenshot.el b/.doom.d/custom-packages/screenshot.el
new file mode 100644
index 00000000..f16f0247
--- /dev/null
+++ b/.doom.d/custom-packages/screenshot.el
@@ -0,0 +1,460 @@
+;;; screenshot.el --- Swiftly grab images of your code -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020 TEC
+
+;; Author: TEC <http://github/tecosaur>
+;; Maintainer: TEC <tec@tecosaur.com>
+;; Homepage: https://github.com/tecosaur/screenshot
+;; Version: 0.1.0
+;; Keywords: convenience, screenshot
+;; Package-Requires: ((emacs "27") (transient "0.2.0") (posframe "0.8.3"))
+
+;; This file is not part of GNU Emacs.
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Convenience package for creating images of the current region or buffer.
+;; Requires `imagemagick' for some visual post-processing, and `xclip' for
+;; copying images to the clipboard.
+
+;;; Code:
+
+(require 'transient)
+(require 'posframe)
+
+(defgroup screenshot ()
+ "Customise group for Screenshot."
+ :group 'convenience)
+
+(defvar screenshot--buffer nil
+ "The buffer last used to create a screenshot.")
+
+(defcustom screenshot-buffer-creation-hook nil
+ "Hook run after creating a buffer for screenshots.
+Run after hardcoded setup, but before the screenshot is captured."
+ :type 'hook
+ :group 'screenshot)
+
+(defvar screenshot--region-beginning nil
+ "Start of the region forming the screenshot.")
+(defvar screenshot--region-end nil
+ "End of the region forming the screenshot.")
+
+(defvar screenshot--tmp-file nil
+ "An intermediate target file for the screenshot.")
+
+(defvar screenshot--first-line-number nil
+ "The first line contained in the screenshot.")
+
+(defvar screenshot--total-lines nil
+ "The total number of lines contained in the screenshot.")
+
+;;; Generated variables
+
+;;; Screenshot parameters
+
+(eval-when-compile
+ (defmacro screenshot--define-infix (key name description type default
+ &rest reader)
+ "Define infix with KEY, NAME, DESCRIPTION, TYPE, DEFAULT and READER as arguments."
+ `(progn
+ (defcustom ,(intern (concat "screenshot-" name)) ,default
+ ,description
+ :type ,type
+ :group 'screenshot)
+ (transient-define-infix ,(intern (concat "screenshot--set-" name)) ()
+ "Set `screenshot--theme' from a popup buffer."
+ :class 'transient-lisp-variable
+ :variable ',(intern (concat "screenshot-" name))
+ :key ,key
+ :description ,description
+ :argument ,(concat "--" name)
+ :reader (lambda (&rest _) ,@reader))))
+
+ (screenshot--define-infix
+ "-l" "line-numbers-p" "Show line numbers"
+ 'boolean nil
+ (not screenshot-line-numbers-p))
+
+ (screenshot--define-infix
+ "-L" "relative-line-numbers-p" "Relative line numbers within the screenshot"
+ 'boolean nil
+ (not screenshot-relative-line-numbers-p))
+
+ (screenshot--define-infix
+ "-t" "text-only-p" "Use a text-only version of the buffer"
+ 'boolean nil
+ (not screenshot-text-only-p))
+
+ (screenshot--define-infix
+ "-T" "truncate-lines-p" "Truncate lines beyond the screenshot width"
+ 'boolean nil
+ (not screenshot-truncate-lines-p))
+
+ (declare-function counsel-fonts "ext:counsel-fonts")
+
+ (declare-function ivy-read "ext:ivy-read")
+
+ (screenshot--define-infix
+ "-ff" "font-family" "Font family to use"
+ 'string (let ((font (face-attribute 'default :font)))
+ (if (eq font 'unspecified) "monospace"
+ (symbol-name (font-get font :family))))
+ (if (fboundp #'counsel-fonts)
+ (ivy-read "Font: " (delete-dups (font-family-list))
+ :preselect screenshot-font-family
+ :require-match t
+ :history 'counsel-fonts-history
+ :caller 'counsel-fonts)
+ (completing-read "Font: " (delete-dups (font-family-list)))))
+
+ (screenshot--define-infix
+ "-fs" "font-size" "Font size (pt)"
+ 'number 14
+ (read-number "Font size in pt: " screenshot-font-size))
+
+;;;; Frame
+
+ (screenshot--define-infix
+ "-b" "border-width" "Border width in pixels"
+ 'integer 20
+ (read-number "Border width in px: " screenshot-border-width))
+
+ (screenshot--define-infix
+ "-r" "radius" "Rounded corner radius"
+ 'integer 10
+ (read-number "Border radius in px: " screenshot-radius))
+
+ (screenshot--define-infix
+ "-w" "min-width" "Minimum width, in columns"
+ 'integer 40
+ (read-number "Minimum width (columns): " screenshot-min-width))
+
+ (screenshot--define-infix
+ "-W" "max-width" "Maximum width, in columns"
+ 'integer 120
+ (read-number "Maximum width (columns): " screenshot-max-width))
+
+;;;; Shadow
+
+ (screenshot--define-infix
+ "-s" "shadow-radius" "Radius of the shadow in pixels"
+ 'integer 12
+ (read-number "Shadow width in px: " screenshot-shadow-radius))
+
+ (screenshot--define-infix
+ "-i" "shadow-intensity" "Intensity of the shadow"
+ 'integer 80
+ (read-number "Shadow intensity: " screenshot-shadow-intensity))
+
+ (screenshot--define-infix
+ "-c" "shadow-color" "Color of the shadow"
+ 'color "#333"
+ (read-string "Shadow color: " screenshot-shadow-color))
+
+ (screenshot--define-infix
+ "-x" "shadow-offset-horizontal" "Shadow horizontal offset"
+ 'integer -8
+ (read-number "Shadow horizontal offset in px: " screenshot-shadow-offset-horizontal))
+
+ (screenshot--define-infix
+ "-y" "shadow-offset-vertical" "Shadow vertical offset"
+ 'integer 5
+ (read-number "Shadow vertical offset in px: " screenshot-shadow-offset-vertical)))
+
+;;; Main function
+
+;;;###autoload
+(defun screenshot (beg end &optional upload-text)
+ "Take a screenshot of the current region or buffer.
+
+Region included in screenshot is the active selection, interactively,
+or given by BEG and END. Buffer is used if region spans 0-1 characters.
+
+When a universal argument is given, UPLOAD-TEXT is non-nil.
+Then the text of the region/buffer is uploaded, and the URL is copied to clipboard."
+ (interactive (if (region-active-p)
+ (list (region-beginning) (region-end) (when current-prefix-arg t))
+ (list (point-min) (point-max) (when current-prefix-arg t))))
+
+ (if upload-text
+ (screenshot-text-upload beg end)
+ (deactivate-mark)
+ (screenshot--set-screenshot-region beg end)
+ (setq screenshot--tmp-file
+ (make-temp-file "screenshot-" nil ".png"))
+ (call-interactively #'screenshot-transient)))
+
+(defvar screenshot-text-upload-function #'screenshot-ixio-upload
+ "Function to use to upload text.
+
+Must take a start and end position for the current buffer, and
+return a URL.")
+
+(defun screenshot-text-upload (beg end)
+ "Upload the region from BEG to END, and copy the upload URL to the clipboard."
+ (message "Uploading text...")
+ (let ((url
+ (funcall screenshot-text-upload-function beg end)))
+ (gui-select-text url)
+ (message "Screenshot uploaded, link copied to clipboard (%s)" url)))
+
+(defun screenshot-ixio-upload (beg end)
+ "Upload the region from BEG to END to ix.io, and return the URL."
+ (let ((output (generate-new-buffer "ixio")) url)
+ (shell-command-on-region beg end
+ (format "curl -F 'ext:1=%s' -F 'f:1=<-' ix.io 2>/dev/null"
+ (file-name-extension (or (buffer-file-name) " .txt")))
+ output)
+ (setq url (string-trim-right (with-current-buffer output (buffer-string))))
+ (kill-buffer output)
+ url))
+
+;;; Screenshot capturing
+
+(defun screenshot--set-screenshot-region (beg end)
+ "Use the region from BEG to END to determine the relevant region to capture.
+Also records useful information like the total number of lines contained,
+and the line number of the first line of the region."
+ (when (or (= beg end) (= (1+ beg) end))
+ (setq beg (point-min)
+ end (point-max)))
+ (save-excursion
+ (goto-char beg)
+ (when (string-match-p "\\`\\s-*$" (thing-at-point 'line))
+ (forward-line 1)
+ (setq beg (line-beginning-position)))
+ (back-to-indentation)
+ (when (= beg (point))
+ (setq beg (line-beginning-position)))
+ (goto-char end)
+ (when (string-match-p "\\`\\s-*$" (thing-at-point 'line))
+ (forward-line -1)
+ (setq end (line-end-position))))
+ (setq screenshot--region-beginning beg
+ screenshot--region-end end
+ screenshot--first-line-number (line-number-at-pos beg)
+ screenshot--total-lines (- (line-number-at-pos end) (line-number-at-pos beg) -1)))
+
+(defun screenshot--setup-buffer ()
+ "Modify the current buffer to make it appropriate for screenshotting."
+ (setq-local face-remapping-alist '((line-number-current-line line-number)
+ (show-paren-match nil)
+ (region nil))
+ line-spacing 0.1)
+ (when (bound-and-true-p hl-line-mode) (hl-line-mode -1))
+ (when (bound-and-true-p solaire-mode) (solaire-mode -1))
+ (run-hooks 'screenshot-buffer-creation-hook))
+
+(defvar screenshot--text-only-buffer
+ (with-current-buffer (generate-new-buffer " *screenshot")
+ (screenshot--setup-buffer)
+ (when prettify-symbols-mode
+ (prettify-symbols-mode -1))
+ (current-buffer))
+ "A text-only buffer for use in creating screenshots.")
+
+(defun screenshot--format-text-only-buffer (beg end)
+ "Insert text from BEG to END in the current buffer, into the screenshot text-only buffer."
+ ;; include indentation if `beg' is where indentation starts
+ (let ((s (string-trim-right (buffer-substring beg end))))
+ (with-current-buffer (setq screenshot--buffer screenshot--text-only-buffer)
+ (buffer-face-set :family screenshot-font-family
+ :height (* 10 screenshot-font-size))
+ (erase-buffer)
+ (insert s)
+ (indent-rigidly (point-min) (point-max)
+ (- (indent-rigidly--current-indentation
+ (point-min) (point-max))))
+ (current-buffer))))
+
+(defun screenshot--narrowed-clone-buffer (beg end)
+ "Create a clone of the current buffer, narrowed to the region from BEG to END.
+This buffer then then set up to be used for a screenshot."
+ (with-current-buffer (clone-indirect-buffer " *screenshot-clone" nil t)
+ (narrow-to-region beg end)
+ (screenshot--setup-buffer)
+ (buffer-face-set :family screenshot-font-family
+ :height (* 10 screenshot-font-size))
+ (current-buffer)))
+
+;;; Screenshot processing
+
+(defun screenshot--process ()
+ "Perform the screenshot process.
+
+Create a buffer for the screenshot, use `x-export-frames' to create the image,
+and process it."
+ (setq screenshot--buffer
+ (if screenshot-text-only-p
+ (screenshot--format-text-only-buffer screenshot--region-beginning screenshot--region-end)
+ (screenshot--narrowed-clone-buffer screenshot--region-beginning screenshot--region-end)))
+
+ (let ((frame (posframe-show
+ screenshot--buffer
+ :position (point-min)
+ :internal-border-width screenshot-border-width
+ :min-width screenshot-min-width
+ :width screenshot-max-width
+ :min-height screenshot--total-lines
+ :lines-truncate screenshot-truncate-lines-p
+ :poshandler #'posframe-poshandler-point-bottom-left-corner
+ :hidehandler #'posframe-hide)))
+ (with-current-buffer screenshot--buffer
+ (setq-local display-line-numbers screenshot-line-numbers-p)
+ (when screenshot-text-only-p
+ (setq-local display-line-numbers-offset
+ (if screenshot-relative-line-numbers-p
+ 0 (1- screenshot--first-line-number))))
+ (font-lock-ensure (point-min) (point-max))
+ (redraw-frame frame)
+ (with-temp-file screenshot--tmp-file
+ (insert (x-export-frames frame 'png))))
+ (posframe-hide screenshot--buffer))
+ (unless screenshot-text-only-p
+ (kill-buffer screenshot--buffer))
+ (screenshot--post-process screenshot--tmp-file))
+
+(defcustom screenshot-post-process-hook
+ (when (executable-find "pngquant")
+ (list (defun screenshot--compress-file (file)
+ (call-process "pngquant" nil nil nil "-f" "-o" file file))))
+ "Functions to be called on the output file after processing.
+Must take a single argument, the file name, and operate in-place."
+ :type 'function
+ :group 'screenshot)
+
+(defun screenshot--post-process (file)
+ "Apply any image post-processing to FILE."
+ (when (or (> screenshot-radius 0)
+ (> screenshot-shadow-radius 0))
+ (let ((result
+ (shell-command-to-string
+ (format "convert '%1$s' \\( +clone -alpha extract \\
+\\( -size %2$dx%2$d xc:black -draw 'fill white circle %2$d,%2$d %2$d,0' -write mpr:arc +delete \\) \\
+\\( mpr:arc \\) -gravity northwest -composite \\
+\\( mpr:arc -flip \\) -gravity southwest -composite \\
+\\( mpr:arc -flop \\) -gravity northeast -composite \\
+\\( mpr:arc -rotate 180 \\) -gravity southeast -composite \\) \\
+-alpha off -compose CopyOpacity -composite -compose over \\
+\\( +clone -background '%3$s' -shadow %4$dx%5$d+%6$d+%7$d \\) \\
++swap -background none -layers merge '%1$s'"
+ file
+ screenshot-radius
+ screenshot-shadow-color
+ screenshot-shadow-intensity
+ screenshot-shadow-radius
+ screenshot-shadow-offset-horizontal
+ screenshot-shadow-offset-vertical))))
+ (unless (string= result "")
+ (error "Could not apply imagemagick commands to image:\n%s" result))))
+ (run-hook-with-args 'screenshot-post-process-hook file))
+
+;;; Screenshot actions
+
+(eval-when-compile
+ (defmacro screenshot--def-action (name &rest body)
+ "Define action NAME to be performed from the transient interface.
+BODY is executed after `screenshot-process' is called."
+ `(defun ,(intern (concat "screenshot-" name)) (&optional _args)
+ "Screenshot action to be performed from the transient interface."
+ (interactive
+ (list (transient-args 'screenshot-transient)))
+ (screenshot--process)
+ ,@body))
+
+ (screenshot--def-action
+ "save"
+ (rename-file
+ screenshot--tmp-file
+ (concat (file-name-sans-extension
+ (or (buffer-file-name)
+ (expand-file-name "screenshot")))
+ ".png")
+ t)
+ (message "Screenshot saved"))
+
+ (screenshot--def-action
+ "save-as"
+ (rename-file
+ screenshot--tmp-file
+ (read-file-name "Save as: " (file-name-directory (or (buffer-file-name) default-directory)))
+ 1)
+ (message "Screenshot saved"))
+
+ (screenshot--def-action
+ "copy"
+ (call-process "xclip" nil nil nil
+ "-selection" "clipboard"
+ "-target" "image/png"
+ "-in" screenshot--tmp-file)
+ (delete-file screenshot--tmp-file)
+ (message "Screenshot copied"))
+
+ (defcustom screenshot-upload-fn nil
+ "Function or string which provides a method to upload a file.
+If a function, it must take a filename and returns a URL to it.
+If a string, it is formatted with the file name, and run as a shell command.
+
+Note: you have to define this yourself, there is no default."
+ :type '(choice function string)
+ :group 'screenshot)
+
+ (screenshot--def-action
+ "upload"
+ (if (not screenshot-upload-fn)
+ (error "No upload function defined")
+ (message "Uploading...")
+ (let ((url
+ (pcase screenshot-upload-fn
+ ((pred functionp) (funcall screenshot-upload-fn screenshot--tmp-file))
+ ((pred stringp) (string-trim-right (shell-command-to-string (format screenshot-upload-fn screenshot--tmp-file))))
+ (_ (error "Upload function is not a function or string!")))))
+ (gui-select-text url)
+ (message "Screenshot uploaded, link copied to clipboard (%s)" url)))
+ (delete-file screenshot--tmp-file)))
+
+;;; Screenshot transient
+
+(transient-define-prefix screenshot-transient ()
+ ["Code"
+ (screenshot--set-line-numbers-p)
+ (screenshot--set-relative-line-numbers-p)
+ (screenshot--set-text-only-p)
+ (screenshot--set-truncate-lines-p)
+ (screenshot--set-font-family)
+ (screenshot--set-font-size)]
+ ["Frame"
+ (screenshot--set-border-width)
+ (screenshot--set-radius)
+ (screenshot--set-min-width)
+ (screenshot--set-max-width)]
+ ["Shadow"
+ (screenshot--set-shadow-radius)
+ (screenshot--set-shadow-intensity)
+ (screenshot--set-shadow-color)
+ (screenshot--set-shadow-offset-horizontal)
+ (screenshot--set-shadow-offset-vertical)]
+ ["Action"
+ ("s" "Save" screenshot-save)
+ ("S" "Save as" screenshot-save-as)
+ ("c" "Copy" screenshot-copy)
+ ("u" "Upload" screenshot-upload)])
+
+(provide 'screenshot)
+;;; screenshot.el ends here
diff --git a/.doom.d/scripts/ics-to-org.el b/.doom.d/scripts/ics-to-org.el
new file mode 100644
index 00000000..bf42c535
--- /dev/null
+++ b/.doom.d/scripts/ics-to-org.el
@@ -0,0 +1 @@
+(icalendar-import-file "/tmp/calendar/personal-calendar.ics" "~/.emacs.d/.local/cache/diary")
diff --git a/.doom.d/scripts/ics-to-org.sh b/.doom.d/scripts/ics-to-org.sh
new file mode 100755
index 00000000..7cf8f600
--- /dev/null
+++ b/.doom.d/scripts/ics-to-org.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# This is a cron that runs every 15 mins and populates my emacs diary file with my calendar items
+
+# Downloading calendar
+echo "Downloading Calendar"
+mkdir -p /tmp/calendar
+cd /tmp/calendar
+wget "https://cloud.rogs.me/remote.php/dav/public-calendars/kRMMJ2CArQeCPzRi/?export" -O "personal-calendar.ics" -c
+wget "https://files-f1.motorsportcalendars.com/f1-calendar_qualifying_sprint_gp.ics" -O "f1.ics" -c
+
+# Merge the calendars
+cat f1.ics >> personal-calendar.ics
+
+#Generating the file
+
+echo "#Generating the file"
+rm ~/.emacs.d/.local/cache/diary
+emacs --batch -l ~/.doom.d/scripts/ics-to-org.el
+
+echo "#Deleting everything"
+#Deleting everything
+rm -r /tmp/calendar