From 13056acfdbe5dd8d572b906add7d94dee404eca7 Mon Sep 17 00:00:00 2001 From: Levi Olson Date: Mon, 13 Jul 2020 14:28:39 -0500 Subject: [PATCH] Latest and greatest --- .gitignore | 1 + lisp/01-custom-early-init.el | 2 +- lisp/04-custom-init.el | 2 + lisp/07-custom-ligatures.el | 5 +- lisp/07_5-custom-created-packages.el | 20 +- lisp/08-custom-packages.el | 335 +++++++++++++++++++++++++-- lisp/custom/ol-message.el | 18 ++ lisp/custom/sfdx.el | 101 +++++--- 8 files changed, 433 insertions(+), 51 deletions(-) create mode 100644 lisp/custom/ol-message.el diff --git a/.gitignore b/.gitignore index c44fe63..43ce08e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ !lisp/ !lisp/custom/* !lisp/* +!snippets/* lisp/*.el~ lisp/unused.el .DS_Store diff --git a/lisp/01-custom-early-init.el b/lisp/01-custom-early-init.el index 285de99..9b1a52d 100644 --- a/lisp/01-custom-early-init.el +++ b/lisp/01-custom-early-init.el @@ -26,7 +26,7 @@ Elements have the form ((KEY . [MAP]) CMD ORIGINAL-CMD)") (add-hook 'after-init-hook `(lambda () (setq file-name-handler-alist file-name-handler-alist-old - gc-cons-threshold 800000 + gc-cons-threshold 100000000 gc-cons-percentage 0.1 ) (garbage-collect)) t) diff --git a/lisp/04-custom-init.el b/lisp/04-custom-init.el index 1315f61..5bb9df7 100644 --- a/lisp/04-custom-init.el +++ b/lisp/04-custom-init.el @@ -72,6 +72,8 @@ (set-frame-width (selected-frame) 220)) (message "Don't configure location for other OSes")) +(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3") + (defalias 'yes-or-no-p 'y-or-n-p) (defvar browse-url-generic-program) diff --git a/lisp/07-custom-ligatures.el b/lisp/07-custom-ligatures.el index c095228..e811439 100644 --- a/lisp/07-custom-ligatures.el +++ b/lisp/07-custom-ligatures.el @@ -295,7 +295,7 @@ ("\\(\\)" #XE9DC) ("\\(<\\\\\\)" #XE9EC) ("\\(<\"\\)" #XE9ED) - ("\\(<\">\\)" #XE9DE) + ;; ("\\(<\">\\)" #XE9DE) ("\\(<:\\)" #XE9EE) ("\\(<:>\\)" #XE9DF) ("\\(<->\\)" #XE9EF) @@ -355,7 +355,8 @@ ("[^~<]\\(~>\\)" #XEA71) ("\\(~~>\\)" #XEA72) ("\\(~>>\\)" #XEA73) - ("[^<]\\(\">\\)" #XEA90)))) + ("[^<]\\(\">\\)" #XEA90) + ))) (defun add-pragmatapro-symbol-keywords () "Add the symbols to font-lock." diff --git a/lisp/07_5-custom-created-packages.el b/lisp/07_5-custom-created-packages.el index 0e63232..fce55f9 100644 --- a/lisp/07_5-custom-created-packages.el +++ b/lisp/07_5-custom-created-packages.el @@ -13,6 +13,10 @@ :demand t :load-path "custom/ol-dired") +(use-package ol-message + :demand t + :load-path "custom/ol-message") + (use-package ol-sflogin :demand t :load-path "custom/ol-sflogin") @@ -24,8 +28,20 @@ ("C-x C-l s" . sfdx/transient-action)) (use-package json - :ensure t - :straight (:host github :repo "ryancrum/json.el" :branch "master")) + :straight ( + :type git + :host github + :repo "ryancrum/json.el" + :branch "master") + :commands (json-read json-read-from-string json-encode)) + +(use-package gcode + :straight ( + :type git + :host github + :repo "jasapp/gcode-emacs" + :branch "master") + :commands gcode-mode) (use-package vlocitemacs :load-path "custom/vlocitemacs" diff --git a/lisp/08-custom-packages.el b/lisp/08-custom-packages.el index 23c1b25..8c93e11 100644 --- a/lisp/08-custom-packages.el +++ b/lisp/08-custom-packages.el @@ -57,13 +57,35 @@ (("C-c SPC" . just-one-space) ("M-SPC" . ace-jump-mode))) +;; https://github.com/jacktasia/dumb-jump +(use-package dumb-jump + :disabled + :hook js-mode + :bind ( + ("M-." . dumb-jump-go) + ("M-," . dumb-jump-back) + ("M->" . dumb-jump-quick-look) + ) + :config + (setq dumb-jump-selector 'ivy) + (setq dumb-jump-force-searcher 'rg)) + ;; https://github.com/NicolasPetton/zerodark-theme (use-package zerodark-theme :demand t + :init + (setq max-specpdl-size 3000) + (setq max-lisp-eval-depth 3000) :config (load-theme 'zerodark t) (zerodark-setup-modeline-format)) +;; ;; https://github.com/belak/base16-emacs +;; (use-package base16-theme +;; :disabled +;; :config +;; (load-theme 'base16-tomorrow t)) + ;; https://github.com/Malabarba/beacon (use-package beacon :commands beacon-mode @@ -99,6 +121,34 @@ :keybinding "m") (engine-mode 1)) +(use-package excorporate + :disabled + :defer 5 + :straight (:host github :repo "emacsmirror/excorporate" :branch "master") + :config + (setq-default excorporate-configuration (quote ("lolson@eaglecrk.com" . "https://outlook.office365.com/EWS/Exchange.asmx")) + org-agenda-include-diary t) + + (add-hook 'diary-mark-entries-hook 'diary-mark-included-diary-files) + + (defun my/agenda-update-diary () + "Update exchange diary." + (interactive) + (exco-diary-diary-advice + (calendar-current-date) + (calendar-current-date) + #'message "Diary updated")) + + ;; Update diary each time the agenda is refreshed + ;; (add-hook 'org-agenda-cleanup-fancy-diary-hook 'my/agenda-update-diary) + + ;; activate excorporate and request un/pw + (excorporate) + + ;; enable diary integration + (excorporate-diary-enable) + ) + ;; https://github.com/Fanael/rainbow-delimiters (use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode)) @@ -128,7 +178,7 @@ (setq dashboard-startup-banner 1) (setq dashboard-show-shortcuts t) (setq show-week-agenda-p t) - (setq dashboard-org-agenda-categories '("work" "tasks")) + (setq dashboard-org-agenda-categories '("eaglecrk")) :config (dashboard-setup-startup-hook)) @@ -191,28 +241,56 @@ ;; https://github.com/skeeto/elfeed (use-package elfeed :bind - (("C-x C-l e" . elfeed) - :map elfeed-search-mode-map - ("a" . (lambda () (interactive) (elfeed-search-set-filter ""))) - ("e" . (lambda () (interactive) (elfeed-search-set-filter "+emacs"))) - ("d" . (lambda () (interactive) (elfeed-search-set-filter "+daily"))) - ("x" . (lambda () (interactive) (elfeed-search-set-filter "xkcd")))) + ("C-x C-l e" . elfeed) + (:map elfeed-search-mode-map + ("a" . (lambda () (interactive) (elfeed-search-set-filter ""))) + ("e" . (lambda () (interactive) (elfeed-search-set-filter "+emacs"))) + ("x" . (lambda () (interactive) (elfeed-search-set-filter "xkcd"))) + ("=" . elfeed-search-set-filter)) :init (setq elfeed-feeds '( + ("https://insideevs.com/rss/make/tesla/" news tesla ev) + ("https://insideevs.com/rss/make/rivian/" news rivian ev) + ("https://insideevs.com/rss/category/battery-tech/" news battery ev) + ("https://www.google.com/alerts/feeds/13353713273807811484/17577790586956417498" news google cybertruck tesla ev) + ("https://www.google.com/alerts/feeds/13353713273807811484/2710948715805064535" news google tesla ev) + ("https://www.google.com/alerts/feeds/13353713273807811484/17638090915837343269" news google pixel4) + + ("https://teslapodcast.libsyn.com/rss" podcast tesla ev) + ("http://feeds.twit.tv/sn.xml" podcast security twit) + ("https://feeds.fireside.fm/linuxunplugged/rss" podcast linux) + ("https://latenightlinux.com/feed/all" podcast linux) + + ("https://www.youtube.com/feeds/videos.xml?channel_id=UCbgBDBrwsikmtoLqtpc59Bw" youtube 3dp) + + ("http://www.reddit.com/r/emacs/.rss" emacs) + ("http://telescoper.wordpress.com/feed/" daily) ("http://xkcd.com/rss.xml" daily) - ("http://timharford.com/feed/" daily) - ("http://understandinguncertainty.org/rss.xml" daily) ("http://pragmaticemacs.com/feed/" emacs) ("http://endlessparentheses.com/atom.xml" emacs) ("http://feeds.feedburner.com/XahsEmacsBlog" emacs) ("http://emacs.stackexchange.com/feeds" emacs) - ("https://www.google.com/alerts/feeds/13353713273807811484/2710948715805064535" tesla) - ("https://www.google.com/alerts/feeds/13353713273807811484/17638090915837343269" pixel4) - ("https://www.google.com/alerts/feeds/13353713273807811484/14416938028701328804" stadia) )) :config + (defun yt-dl-it (url) + "Downloads the URL in an async shell" + (let ((default-directory "~/Videos")) + (async-shell-command (format "youtube-dl %s" url)))) + + (defun elfeed-youtube-dl (&optional use-generic-p) + "Youtube-DL link" + (interactive "P") + (let ((entries (elfeed-search-selected))) + (cl-loop for entry in entries + do (elfeed-untag entry 'unread) + when (elfeed-entry-link entry) + do (yt-dl-it it)) + (mapc #'elfeed-search-update-entry entries) + (unless (use-region-p) (forward-line)))) + + (define-key elfeed-search-mode-map (kbd "d") 'elfeed-youtube-dl) (elfeed-update)) ;; https://github.com/rmuslimov/browse-at-remote @@ -229,7 +307,7 @@ ;; https://github.com/lewang/fic-mode (use-package fic-mode - :hook (prog-mode js-mode javascript-mode) + ;; :hook (prog-mode js-mode) :custom-face (fic-face ((t :foreground "red" :weight bold))) (fic-author-face ((t :foreground "red" :underline t)))) @@ -247,7 +325,10 @@ (use-package company :defer 25 :commands company-mode - :hook (prog-mode . company-mode) + :hook ( + (prog-mode . company-mode) + (ledger-mode . company-mode) + ) :bind (:map company-active-map ("M-n" . nil) @@ -294,6 +375,24 @@ :config (projectile-mode 1)) +;; https://github.com/ledger/ledger-mode +(use-package ledger-mode + :mode ("\\.dat\\'" "\\.ledger\\'") + :bind + (("C-x C-l l" . (lambda () (interactive) (find-file "~/Documents/finance-records/ledger.dat"))) + :map ledger-mode-map + ("M-q" . leo/kill-this-buffer-unless-scratch) + ("C-" . ledger-mode-clean-buffer) + ("" . ledger-post-align-dwim) + ) + :hook + (ledger-mode . (lambda () + (setq tab-always-indent 'complete) + (setq-local completion-cycle-threshold t) + (setq-local ledger-complete-in-steps t) + )) + ) + ;; https://github.com/magit/git-modes (use-package gitignore-mode :mode ("\\.gitignore\\'")) @@ -304,7 +403,61 @@ ;; http://web-mode.org/ (use-package web-mode - :hook (html-mode xml-mode)) + :hook (html-mode nxml-mode)) + +;; JAVASCRIPT SECTION +(use-package lsp-mode + :straight (:host github :repo "emacs-lsp/lsp-mode" :branch "master") + ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l") + :init (setq lsp-keymap-prefix "C-c l") + :hook (;; replace XXX-mode with concrete major-mode(e. g. python-mode) + (js-mode . lsp) + (css-mode . lsp) + (yaml-mode . lsp) + ;; if you want which-key integration + (lsp-mode . lsp-enable-which-key-integration)) + :bind + ( + :map js-mode-map + ("M-." . lsp-find-definition) + ) + :commands lsp) + +(use-package lsp-ui + :straight (:host github :repo "emacs-lsp/lsp-ui" :branch "master") + :commands lsp-ui-mode) +(use-package company-lsp + :straight (:host github :repo "tigersoldier/company-lsp" :branch "master") + :commands company-lsp) +(use-package lsp-ivy + :straight (:host github :repo "emacs-lsp/lsp-ivy" :branch "master") + :commands lsp-ivy-workspace-symbol) +(use-package lsp-treemacs + :straight (:host github :repo "emacs-lsp/lsp-treemacs" :branch "master") + :commands lsp-treemacs-errors-list) + +(use-package js2-mode + :disabled + :mode ("\\.js\\'")) +(use-package typescript-mode + :disabled + :mode ("\\.js\\'")) +(use-package tide + :disabled + :ensure t + :after (typescript-mode company flycheck) + :hook ((typescript-mode . tide-setup) + (typescript-mode . tide-hl-identifier-mode) + (before-save . tide-format-before-save)) + :bind ( + ("M-?" . tide-references) + ("M-r" . tide-rename-symbol) + ("M-/" . tide-jsdoc-template) + ("M-o" . tide-organize-imports) + )) + + + ;; https://github.com/smihica/emmet-mode (use-package emmet-mode @@ -349,6 +502,141 @@ (setq flycheck-emacs-lisp-load-path 'inherit) (global-flycheck-mode)) +;; Mu4e +(use-package mu4e + :load-path "/usr/local/share/emacs/site-lisp/mu/mu4e" + :commands mu4e + :bind + ( + ("C-x C-l m" . mu4e) + ;; :map mu4e-headers-mode-map + ) + :config + (setq mu4e-maildir "/Users/leviolson/Maildir" + mu4e-mu-binary "/usr/local/bin/mu" + mail-user-agent 'mu4e-user-agent + mu4e-change-filenames-when-moving t ;; Rename files when moving (required by mbsync) + mu4e-compose-in-new-frame t ;; New compose gets new frame + mu4e-context-policy 'pick-first + mu4e-get-mail-command "true" ; /Users/leviolson/scripts/bash/get-email.sh + ;; Get mail automatically (outside emacs) via brew services + ;; "mbsync -a && mu index && open bitbar://refreshPlugin?name=mail.sh" + ;; MBSYNC is the mail cmd + mu4e-html2text-command "/usr/local/bin/w3m -T text/html" ;; HTML to text command + mu4e-headers-include-related nil ;; Stop threading in INBOX + mu4e-sent-messages-behavior 'delete ;; Delete sent messages + mu4e-update-interval 60 ;; 1 min + mu4e-use-fancy-chars t ;; use 'fancy' chars + mu4e-user-mail-address-list '("lolson@eaglecrk.com") + + mu4e-view-show-images t ;; attempt to show images + mu4e-view-image-max-width 400 ;; max image size + + message-citation-line-format "On %a %d %b %Y at %R, %f wrote:\n" ;; customize the reply-quote-string + message-citation-line-function 'message-insert-formatted-citation-line ;; choose to use the formatted string + message-kill-buffer-on-exit t ;; don't keep messages around + + send-mail-function 'smtpmail-send-it ;; Default email send function + smtpmail-default-smtp-server "smtp.office365.com" + smtpmail-smtp-service 587 + ) + + (setq mu4e-contexts + `( + ,(make-mu4e-context + :name "EagleCreek" + :enter-func (lambda () (mu4e-message "Entering EagleCreek")) + :leave-func (lambda () (mu4e-message "Leaving EagleCreek")) + ;; we match based on the contact-fields of the message + :match-func (lambda (msg) + (when msg + (string= (mu4e-message-field msg :maildir) "/eaglecrk"))) + :vars '( ( user-mail-address . "lolson@eaglecrk.com" ) + ( smtpmail-mail-address . "lolson@eaglecrk.com" ) + ( smtpmail-smtp-user . "lolson@eaglecrk.com" ) + ( smtpmail-smtp-server . "smtp.office365.com" ) + ( user-full-name . "Levi Olson" ) + ( mu4e-compose-signature . + (concat + "Levi Olson\n" + "Eagle Creek Software Services\n" + "Senior Application Developer Consultant\n")) + ( mu4e-sent-folder . "/eaglecrk/Sent Items" ) + ( mu4e-refile-folder . "/eaglecrk/Archive" ) + ( mu4e-drafts-folder . "/eaglecrk/Drafts" ) + ( mu4e-trash-folder . "/eaglecrk/Deleted Items" ) + ( mu4e-maildir-shortcuts . (("/eaglecrk/Inbox" . ?i) + ("/eaglecrk/Sent Items" . ?s) + ("/eaglecrk/Deleted Items" . ?t) + ("/eaglecrk/Archive" . ?a) + )))) + ;; ,(make-mu4e-context + ;; :name "Gmail" + ;; :enter-func (lambda () (mu4e-message "Entering Gmail")) + ;; :leave-func (lambda () (mu4e-message "Leaving Gmail")) + ;; ;; this matches maildir /Arkham and its sub-directories + ;; :match-func (lambda (msg) + ;; (when msg + ;; (string= (mu4e-message-field msg :maildir) "/gmail"))) + ;; :vars '( ( user-mail-address . "olson.levi@gmail.com" ) + ;; ( smtpmail-mail-address . "olson.levi@gmail.com" ) + ;; ( smtpmail-smtp-user . "olson.levi@gmail.com" ) + ;; ( smtpmail-smtp-server . "smtp.gmail.com" ) + ;; ( user-full-name . "Levi Olson" ) + ;; ( mu4e-compose-signature . + ;; (concat + ;; "Levi\n")) + ;; ( mu4e-sent-folder . "/gmail/[Gmail]/Sent Mail" ) + ;; ( mu4e-refile-folder . "/gmail/[Gmail]/All Mail" ) + ;; ( mu4e-drafts-folder . "/gmail/[Gmail]/Drafts" ) + ;; ( mu4e-trash-folder . "/gmail/[Gmail]/Trash" ) + ;; ( mu4e-maildir-shortcuts . (("/gmail/Inbox" . ?i) + ;; ("/gmail/[Gmail]/Sent Mail" . ?s) + ;; ("/gmail/[Gmail]/Trash" . ?t) + ;; ("/gmail/[Gmail]/All Mail" . ?a) + ;; )))) + )) + + ;; Add option to view HTML in browser + (add-to-list 'mu4e-headers-actions + '("in browser" . mu4e-action-view-in-browser) t) + (add-to-list 'mu4e-view-actions + '("in browser" . mu4e-action-view-in-browser) t) + + (defun my-message-current-line-cited-p () + "Indicate whether the line at point is a cited line." + (save-match-data + (string-match (concat "^" message-cite-prefix-regexp) + (buffer-substring (line-beginning-position) (line-end-position))))) + + (defun my-message-says-attachment-p () + "Return t if the message suggests there can be an attachment." + (save-excursion + (goto-char (point-min)) + (save-match-data + (let (search-result) + (while + (and (setq search-result (re-search-forward "\\(attach\\|pdf\\|file\\)" nil t)) + (my-message-current-line-cited-p))) + search-result)))) + + (defun my-message-has-attachment-p () + "Return t if the message has an attachment." + (save-excursion + (goto-char (point-min)) + (save-match-data + (re-search-forward "<#part" nil t)))) + + (defun my-message-pre-send-check-attachment () + (when (and (my-message-says-attachment-p) + (not (my-message-has-attachment-p))) + (unless + (y-or-n-p "No attachment, send anyway? ") + (error "It seems that an attachment is needed, but none was found. Aborting sending")))) + + (add-hook 'message-send-hook 'my-message-pre-send-check-attachment)) + + ;; https://orgmode.org/elpa.html (use-package org :commands org-capture @@ -370,18 +658,21 @@ (defvar org-capture-templates) :init (setq org-agenda-files '("~/Dropbox/Org/todo.org" - ;; "~/Dropbox/Org/projects.org" + "~/Dropbox/Org/diary/eaglecrk.org" "~/Dropbox/Org/archive.org" - ;; "~/Dropbox/Org/diary/eaglecrk.org" + "~/Projects/vlocity/cmt-training-org/LightningWebComponents/README.org" + ;; "~/.emacs.d/excorporate/diary-excorporate-today" )) + (setq org-agenda-include-diary t) (add-to-list 'safe-local-variable-values '(eval leo/deft-insert-boilerplate)) (setq org-todo-keywords '((sequence "TODO(t)" "|" "DONE(d)") (sequence "BUG(b)" "INPROGRESS(i)" "|" "FIXED(f)") (sequence "TEST(T)" "NOTEST(N)" "|" "COMPLETE(C)") + (sequence "QUESTION(Q)" "|" "ANSWERED(A)") (sequence "|" "CANCELED(c)") (sequence "|" "NEEDCLARIFICATION(n)") (sequence "|" "PROVIDEUPDATE(p)") - (sequence "|" "WAITING(w)")) + (sequence "WAITING(w)" "|")) org-refile-targets '((nil :maxlevel . 3) (org-agenda-files :maxlevel . 3)) org-directory "~/Dropbox/Org" @@ -466,6 +757,11 @@ (add-hook 'org-mode-hook 'add-checkbox-symbol-keywords) ) +;; https://github.com/seanohalpin/org-link-minor-mode +(use-package org-link-minor-mode + :straight (:host github :repo "seanohalpin/org-link-minor-mode" :branch "master") + :commands org-link-minor-mode) + (use-package ob-restclient :disabled :ensure t @@ -563,7 +859,8 @@ ("M-p" . leo/jump-to-prev-symbol) ("M-u" . upcase-dwim) ("M-c" . capitalize-dwim) - ("M-l" . downcase-dwim)) + ("M-l" . downcase-dwim) + ) ;; https://github.com/nflath/sudo-edit (use-package sudo-edit diff --git a/lisp/custom/ol-message.el b/lisp/custom/ol-message.el new file mode 100644 index 0000000..1c0587a --- /dev/null +++ b/lisp/custom/ol-message.el @@ -0,0 +1,18 @@ +;;; ol-message.el --- Support for links to mail message + +;;; Commentary: + +;;; Code: + +(require 'ol) + +(defun org-message-command (link) + "The Emacs command to be used to open a message in Mail via LINK." + (shell-command (format "open \"message:%s\"" link)) + (message "Opening message in Mail...")) + +(org-link-set-parameters "message" + :follow #'org-message-command) + +(provide 'ol-message) +;;; ol-message.el ends here diff --git a/lisp/custom/sfdx.el b/lisp/custom/sfdx.el index c35d3b1..e268f5b 100644 --- a/lisp/custom/sfdx.el +++ b/lisp/custom/sfdx.el @@ -40,6 +40,14 @@ ;; (find-file project-path) (message project-path)) +(defun sfdx/exec-process (cmd name &optional comint) + "Execute CMD as a process in a buffer NAME, optionally passing COMINT as non-nil to put buffer in `comint-mode'." + (let ((compilation-buffer-name-function + (lambda (mode) + (format "*%s*" name)))) + (message (concat "Running " cmd)) + (compile cmd comint))) + (defun sfdx/create-project () "Create a new 'standard' SFDX project." (interactive) @@ -63,36 +71,43 @@ ) (message "You must be in an SFDX project to run that command!"))) +(defun sfdx/fetch-component () + "Fetch a Lightning Web Component from Org." + (interactive) + (if (locate-dominating-file buffer-file-name "force-app") + (let ((process "sfdx-fetch-component") + (cd-dir (concat (locate-dominating-file buffer-file-name "force-app") "force-app/main/default/lwc/")) + (comp-name (read-string "Component Name: ")) + ) + (sfdx/exec-process (format "sh -c \"cd %s; sfdx force:source:retrieve -m LightningComponentBundle:%s\"" cd-dir comp-name) "sfdx:retrieve_component" t) + ;; (async-start-process process "sh" (lambda (result) (message (concat "Component Retrieved: \"" comp-name "\""))) "-c" (concat "sfdx force:source:retrieve -m LightningComponentBundle:" comp-name)) + ) + (message "You must be in an SFDX project to run that command!"))) + (defun sfdx--deploy (component comp-name) - "Internal function to deploy COMP-NAME asyncronously or project if COMPONENT is nil after validations." + "Internal function to deploy COMP-NAME asyncronously or whole project if COMPONENT is nil after validations." + (let ((process "sfdx-deploy") + (buffer "*sfdx-output*") + (cd-dir (expand-file-name (locate-dominating-file buffer-file-name "force-app"))) + (output-path (concat (locate-dominating-file buffer-file-name "force-app") "force-app/main/default"))) + (if component + (sfdx/exec-process (format "sh -c \"cd %s; sfdx force:source:deploy --sourcepath ./force-app/main/default/lwc/%s --loglevel fatal\"" cd-dir comp-name) "sfdx:deploy_component" t) + (sfdx/exec-process (format "sh -c \"cd %s; sfdx force:source:deploy --sourcepath ./force-app/main/default/ --loglevel fatal\"" cd-dir) "sfdx:deploy_project" t)))) + +(defun sfdx--retrieve (component comp-name) + "Internal function to retrieve COMP-NAME asyncronously or whole project if COMPONENT is nil after validations." (let ((process "sfdx-deploy") (buffer "*sfdx-output*") (cd-dir (expand-file-name (locate-dominating-file buffer-file-name "force-app"))) (output-path (concat (locate-dominating-file buffer-file-name "force-app") "force-app/main/default"))) (if component - (progn - (delete-other-windows) - (split-window-below 40) - (other-window 1) - (switch-to-buffer buffer) - (erase-buffer) - (local-set-key (kbd "q") 'delete-window) - (insert (format "Starting deployment of %s...\n" comp-name)) - (start-process process buffer "sh" "-c" (concat "cd " cd-dir "; sfdx force:source:deploy --sourcepath ./force-app/main/default/lwc/" comp-name " --loglevel fatal")) - ) + (sfdx/exec-process (format "sh -c \"cd %s; sfdx force:source:retrieve --sourcepath ./force-app/main/default/lwc/%s --loglevel fatal\"" cd-dir comp-name) "sfdx:retrieve_component" t) (progn - (delete-other-windows) - (split-window-below 40) - (other-window 1) - (switch-to-buffer buffer) - (erase-buffer) - (local-set-key (kbd "q") 'delete-window) - (insert "Starting deployment of project...\n") - (start-process process buffer "sh" "-c" (concat "cd " cd-dir "; sfdx force:source:deploy --sourcepath ./force-app/main/default/ --loglevel fatal")) - ) - ) - ) - ) + (if (yes-or-no-p "Are you sure? This will completely overwrite any local changes! ") + (sfdx/exec-process (format "sh -c \"cd %s; sfdx force:source:retrieve --sourcepath ./force-app/main/default/ --loglevel fatal\"" cd-dir) "sfdx:retrieve_project" t) + (message "Cancelled") + ))))) + (defun sfdx/deploy-component-or-project () "Deploy the current component or project to target." @@ -131,16 +146,48 @@ (defun sfdx/retrieve-component () "Retrieve the source for the current component (destructively overwrites)." (interactive) - (message "can't do that yet, i'm still learning")) + (let ((current-folder (file-name-nondirectory + (directory-file-name + (file-name-directory (buffer-file-name)))))) + (if (locate-dominating-file buffer-file-name "lwc") + (prog1 + ;; Possibly in a component folder, but lets makes sure its not just the LWC folder. + (if (string= current-folder "lwc") + (prog1 + ;; Not in a component, retrieve project. + ;; (message "Retrieving Project...") + (sfdx--retrieve nil current-folder)) + ;; In a component, retrieve component. + ;; (message "Retrieving Component...") + (sfdx--retrieve t current-folder))) + + (prog1 + ;; Are we in a project? + (if (locate-dominating-file buffer-file-name "force-app") + (prog1 + ;; In project, retrieve project. + ;; (message "Retrieving Project...") + (sfdx--retrieve nil current-folder)) + (prog1 + ;; Not in an SFDX project. + (message "You are not in a component folder or an SFDX project!")) + ) + ) + ) + ) + ) (define-transient-command sfdx/transient-action () "SFDX CLI Actions" ["Project Specific" ("P" "Create New Project" sfdx/create-project)] - ["Component Level" - ("c" "create new" sfdx/create-component) + ["Create Component" + ("n" "create new" sfdx/create-component)] + ["Actions for this Component" ("d" "deploy" sfdx/deploy-component-or-project) - ("r" "retrieve" sfdx/retrieve-component)]) + ("r" "retrieve" sfdx/retrieve-component)] + ["Download Component" + ("f" "fetch by component name" sfdx/fetch-component)]) (provide 'sfdx) ;;; sfdx.el ends here