diff --git a/extensions/aweshell b/extensions/aweshell index c0850fe..2089cbf 160000 --- a/extensions/aweshell +++ b/extensions/aweshell @@ -1 +1 @@ -Subproject commit c0850fef4b50e28b1e994734eca79090b592f9d1 +Subproject commit 2089cbf0e24c1a9a91b7f45075a39ee469c5811e diff --git a/extensions/awesome-pair b/extensions/awesome-pair index c49249c..867b524 160000 --- a/extensions/awesome-pair +++ b/extensions/awesome-pair @@ -1 +1 @@ -Subproject commit c49249c255d6cbbfb960ba33d62af0524ebe2b82 +Subproject commit 867b524b42ff4c28df0cdee73358ae48e2637ade diff --git a/extensions/elispfl b/extensions/elispfl index 960ccbe..7ff15a2 160000 --- a/extensions/elispfl +++ b/extensions/elispfl @@ -1 +1 @@ -Subproject commit 960ccbe6bb6e7b22cea7edca0728a586e678600b +Subproject commit 7ff15a27d62dbaae78c0be25347c17604512b2a6 diff --git a/init.el b/init.el index 74f5342..063cb38 100644 --- a/init.el +++ b/init.el @@ -73,6 +73,14 @@ (require 'init-vc) (require 'init-git) +(require 'init-lisp) +;; (require 'init-scheme) +;; (require 'init-slime) +;; (require 'init-clojure) +;; (require 'init-clojure-cider) +;; (require 'init-common-lisp) +(require 'init-paredit) + (require 'init-lsp) (require 'init-jump) ;; (require 'init-compile) @@ -93,21 +101,13 @@ ;; (require 'init-rails) ;; (require 'init-php) ;; (require 'init-sql) +(require 'init-rust) (require 'init-yaml) (require 'init-docker) (require 'init-nginx) (require 'init-lua) (require 'init-ahk) (require 'init-dotenv) - -(require 'init-paredit) -(require 'init-lisp) -;; (require 'init-scheme) -;; (require 'init-slime) -;; (require 'init-clojure) -;; (require 'init-clojure-cider) -;; (require 'init-common-lisp) - (require 'init-shell) (require 'init-chinese) diff --git a/modes/init-dired.el b/modes/init-dired.el index f9ebf8b..65decc9 100644 --- a/modes/init-dired.el +++ b/modes/init-dired.el @@ -20,7 +20,8 @@ :map ranger-mode-map ("s" . 'ranger-sort-criteria)) :config - (ranger-override-dired-mode 1)) + (ranger-override-dired-mode 1) + (push 'deer find-directory-functions)) (use-package all-the-icons-dired :after (all-the-icons ranger) diff --git a/modes/init-edit-server.el b/modes/init-edit-server.el index 26220ea..09a4887 100644 --- a/modes/init-edit-server.el +++ b/modes/init-edit-server.el @@ -7,10 +7,10 @@ :config (edit-server-start) (setq edit-server-new-frame nil - edit-server-url-major-mode-alist - '(("emacs-china\\.org" . markdown-mode) - ("github\\.com" . markdown-mode) - ("stackoverflow\\.com" . markdown-mode))) + edit-server-url-major-mode-alist + '(("emacs-china\\.org" . markdown-mode) + ("github" . markdown-mode) + ("stackoverflow\\.com" . markdown-mode))) (jester/with-minor-leader 'edit-server-edit-mode "a" 'edit-server-abort)) diff --git a/modes/init-editing-utils.el b/modes/init-editing-utils.el index f24746d..237dea6 100644 --- a/modes/init-editing-utils.el +++ b/modes/init-editing-utils.el @@ -28,10 +28,6 @@ :custom (aggressive-indent-region-function 'evil-indent "also convert tab/space when indent") :hook (after-init . aggressive-indent-global-mode)) -(require 'recentf) -(add-to-list 'recentf-exclude (list "/tmp/" "/ssh:" "COMMIT_EDITMSG\\'" - (recentf-expand-file-name package-user-dir))) - (after-init (transient-mark-mode 1)) ;;---------------------------------------------------------------------------- @@ -77,7 +73,19 @@ :states '(operator) "x" 'subword-forward "z" 'subword-backward) - :commands (subword-forward subword-backward)) + + (evil-define-text-object jester/evil-inner-subword (count &optional beg end type) + "Select a subword." + :extend-selection nil + (save-excursion (let ((start (progn (subword-backward) (point))) + (end (progn (subword-forward) (point)))) + (list start end)))) + (general-define-key + :keymaps 'evil-inner-text-objects-map + "x" 'jester/evil-inner-subword + "z" 'jester/evil-inner-subword) + + :commands (subword-forward subword-backward jester/evil-inner-subword)) (use-package electric-operator @@ -91,7 +99,6 @@ (c-mode . electric-operator-mode) (php-mode . electric-operator-mode))) - ;;---------------------------------------------------------------------------- ;; kill back to indentation ;;---------------------------------------------------------------------------- @@ -360,6 +367,7 @@ Threat is as function body when from endline before )" "Move to paragraph end, line-wise." :type line (interactive "p") + (next-line) (forward-paragraph count) (previous-line)) @@ -367,6 +375,7 @@ Threat is as function body when from endline before )" "Move to paragraph start, line-wise." :type line (interactive "p") + (previous-line) (backward-paragraph count) (next-line)) @@ -379,14 +388,6 @@ Threat is as function body when from endline before )" ;; narrow ;;---------------------------------------------------------------------------- ;; https://github.com/redguardtoo/emacs.d/blob/master/lisp/init-misc.el -(defun line-number-at-position (pos) - "Returns the line number for position `POS'." - (save-restriction - (widen) - (save-excursion - (goto-char pos) - (+ 1 (count-lines (point-min) (line-beginning-position 1)))))) - (defun narrow-to-region-indirect-buffer-maybe (start end use-indirect-buffer) "Indirect buffer could multiple widen on same file." (if (region-active-p) (deactivate-mark)) @@ -395,7 +396,7 @@ Threat is as function body when from endline before )" (clone-indirect-buffer (generate-new-buffer-name (format "%s-indirect-:%s-:%s" - (buffer-name) (line-number-at-position start) (line-number-at-position end))) + (buffer-name) (line-number-at-pos start t) (line-number-at-pos end t))) 'display) (narrow-to-region start end) (goto-char (point-min))) @@ -442,40 +443,51 @@ If use-indirect-buffer is not nil, use `indirect-buffer' to hold the widen conte ;;---------------------------------------------------------------------------- ;; do something to a comma-delimitered sentence ;;---------------------------------------------------------------------------- -(evil-define-text-object jester/evil-a-subsentence (count &optional beg end type) - "Select a subsentence(delimitered by comma)." +(evil-define-text-object jester/evil-inner-subsentence (count &optional beg end type) + "Select a subsentence(delimitered by comma), without the punctuations." :extend-selection nil (list (progn (re-search-backward "[,.] ?") (forward-char) (when (eq (char-after (point)) ? ) (forward-char)) (point)) - (re-search-forward "[,.] ?"))) + (progn (re-search-forward "[,.] ?") + (backward-char) + (when (memq (char-before) (list ?. ?,)) (backward-char)) + (point)))) -(evil-define-text-object jester/evil-inner-subsentence (count &optional beg end type) - "Select a subsentence(delimitered by comma), without the punctuations." +(evil-define-text-object jester/evil-a-subsentence (count &optional beg end type) + "Select a subsentence(delimitered by comma)." :extend-selection nil (list (progn (re-search-backward "[,.] ?") - ;; (re-search-backward "[,.] ?\\|( ?") (forward-char) (when (eq (char-after (point)) ? ) (forward-char)) (point)) - (progn (re-search-forward "[,.] ?") - (backward-char) - (when (memq (char-before) (list ?. ?,)) (backward-char)) - (point)))) + (re-search-forward "[,.] ?"))) -(general-define-key - :keymaps 'evil-outer-text-objects-map - "S" 'jester/evil-a-subsentence) (general-define-key :keymaps 'evil-inner-text-objects-map "S" 'jester/evil-inner-subsentence) +(general-define-key + :keymaps 'evil-outer-text-objects-map + "S" 'jester/evil-a-subsentence) ;;---------------------------------------------------------------------------- ;; select an argument ;;---------------------------------------------------------------------------- +(evil-define-text-object jester/evil-inner-arg (count &optional beg end type) + "Select an argument, without the punctuations." + :extend-selection nil + (list (progn + (re-search-backward "[,(] ?") + (forward-char) + (when (eq (char-after (point)) ? ) (forward-char)) + (point)) + (progn (re-search-forward "[,] ?\\| ?)") + (while (memq (char-before) (list ?, ? ?\))) (backward-char)) + (point)))) + (evil-define-text-object jester/evil-a-arg (count &optional beg end type) "Select an argument." :extend-selection nil @@ -496,17 +508,5 @@ If use-indirect-buffer is not nil, use `indirect-buffer' to hold the widen conte (point)))) (list head tail))) -(evil-define-text-object jester/evil-inner-arg (count &optional beg end type) - "Select an argument, without the punctuations." - :extend-selection nil - (list (progn - (re-search-backward "[,(] ?") - (forward-char) - (when (eq (char-after (point)) ? ) (forward-char)) - (point)) - (progn (re-search-forward "[,] ?\\| ?)") - (while (memq (char-before) (list ?, ? ?\))) (backward-char)) - (point)))) - (provide 'init-editing-utils) diff --git a/modes/init-evil.el b/modes/init-evil.el index 0d3c254..2b1b4f9 100644 --- a/modes/init-evil.el +++ b/modes/init-evil.el @@ -196,17 +196,36 @@ :demand t ;; :commands (evil-multiedit-match-all evil-multiedit-match-symbol-and-next evil-multiedit-match-symbol-and-prev) :init + (setq evil-multiedit-use-symbols t) ;; Ex command that allows you to invoke evil-multiedit with a regular expression, e.g. (evil-ex-define-cmd "ie[dit]" 'evil-multiedit-ex-match) (general-define-key :states '(normal visual) - "R" 'evil-multiedit-match-all + "R" 'jester/evil-multiedit-match-all "C-n" 'evil-multiedit-match-symbol-and-next "C-p" 'evil-multiedit-match-symbol-and-prev) + (defun jester/evil-multiedit-match-all () + "Match all occurences. with prefix arg, exclude those in comments or strings." + (interactive) + (evil-multiedit-match-all) + (when current-prefix-arg + (save-excursion + (let ((pos)) + (iedit-goto-first-occurrence) + (setq pos (point)) + (unless (jester/in-expression-area-p) + (evil-multiedit-toggle-or-restrict-region)) + (while (evil-multiedit-next) + (unless (jester/in-expression-area-p) + (evil-multiedit-toggle-or-restrict-region))))))) :config - (define-key evil-multiedit-state-map (kbd "") 'evil-multiedit-toggle-or-restrict-region) - (define-key evil-multiedit-state-map (kbd "") 'evil-multiedit-prev) - ;; these have to be loaded before company so they don't shadow tab binding in `company-active-map' + (general-define-key + :keymaps 'evil-multiedit-state-map + "" 'evil-multiedit-toggle-or-restrict-region + "" 'evil-multiedit-prev + "C-a" 'evil-multiedit--beginning-of-line + "C-e" 'evil-multiedit--end-of-line) + ;; these have to be loaded before company so they don't shadow tab bindings in `company-active-map' (define-key evil-multiedit-state-map (kbd "") 'evil-multiedit-next) (define-key evil-multiedit-insert-state-map (kbd "") 'tab-indent-or-complete) ) @@ -232,7 +251,9 @@ :custom (evil-goggles-duration 0.1) :hook (evil-mode . evil-goggles-mode) :config - (evil-goggles-use-diff-faces)) + ;; (evil-goggles-use-diff-faces) + (evil-goggles-use-diff-refine-faces) + ) (push (expand-file-name "targets" jester-submodules-dir) load-path) @@ -443,13 +464,13 @@ (defun jester/evil-visual-search (forward) "Search the region." - (let ((string (buffer-substring-no-properties (region-beginning) (region-end)))) + (let ((regex (regexp-quote (buffer-substring-no-properties (region-beginning) (region-end))))) (deactivate-mark) - (evil-push-search-history string forward) + (evil-push-search-history regex forward) ;; pushed to `regexp-search-ring' - (isearch-update-ring string evil-regexp-search) + (isearch-update-ring regex evil-regexp-search) (setq isearch-forward forward) - (evil-search string forward))) + (evil-search regex forward evil-regexp-search))) (provide 'init-evil) diff --git a/modes/init-file.el b/modes/init-file.el index 3b79985..8b3f408 100644 --- a/modes/init-file.el +++ b/modes/init-file.el @@ -1,3 +1,9 @@ +(require 'recentf) +(setq recentf-exclude + (append recentf-exclude (list "/tmp/" "/ssh:" "COMMIT_EDITMSG\\'" + ;; (recentf-expand-file-name package-user-dir) + ))) + (jester/with-leader "f f" 'find-file "f s" 'save-buffer diff --git a/modes/init-flycheck.el b/modes/init-flycheck.el index ef8840e..5cbadd7 100644 --- a/modes/init-flycheck.el +++ b/modes/init-flycheck.el @@ -6,7 +6,17 @@ (jester/with-leader "e l" 'flycheck-list-errors "e p" 'flycheck-previous-error - "e n" 'flycheck-next-error)) + "e n" 'flycheck-next-error) + (general-define-key + :states '(motion) + :keymaps 'flycheck-error-list-mode-map + "j" 'flycheck-error-list-next-error + "k" 'flycheck-error-list-previous-error + "f" 'flycheck-error-list-set-filter + "F" 'flycheck-error-list-reset-filter + "r" 'flycheck-error-list-check-source + "e" 'flycheck-error-list-explain-error + "" 'flycheck-error-list-goto-error)) (use-package flycheck-posframe :if window-system diff --git a/modes/init-gui-frames.el b/modes/init-gui-frames.el index c77d918..ac1fe07 100644 --- a/modes/init-gui-frames.el +++ b/modes/init-gui-frames.el @@ -29,18 +29,6 @@ (when (fboundp 'horizontal-scroll-bar-mode) (horizontal-scroll-bar-mode -1)) -;; I generally prefer to hide the menu bar, but doing this on OS X -;; simply makes it update unreliably in GUI frames, so we make an -;; exception. -(if *is-a-mac* - (add-hook 'after-make-frame-functions - (lambda (frame) - (set-frame-parameter frame 'menu-bar-lines - (if (display-graphic-p frame) - 1 0)))) - (when (fboundp 'menu-bar-mode) - (menu-bar-mode -1))) - (when (fboundp 'pixel-scroll-mode) (pixel-scroll-mode 1)) @@ -50,10 +38,6 @@ (setq frame-title-format "看,灰机! ✈✈✈✈✈✈✈✈✈" frame-resize-pixelwise t) -(set-frame-parameter nil 'undecorated t) -;; (set-frame-parameter nil 'fullscreen (cond ((eq window-system 'x) 'fullboth) -;; ((eq window-system 'mac) 'maximized) -;; (t 'maximized))) ;; Non-zero values for `line-spacing' can mess up ansi-term and co, ;; so we zero it explicitly in those cases. @@ -69,7 +53,8 @@ (t 'maximized))) ;; left & top are required on wsl to correctly position (left . (+ 0)) - (top . (+ 0)))) + (top . (+ 0)) + (undecorated . t))) (provide 'init-gui-frames) diff --git a/modes/init-javascript.el b/modes/init-javascript.el index 5ebd767..e86cb68 100644 --- a/modes/init-javascript.el +++ b/modes/init-javascript.el @@ -7,7 +7,10 @@ js2-global-externs '("$" "jQuery" "jquery" "_") js2-mode-show-parse-errors nil js2-mode-show-strict-warnings nil - js2-bounce-indent-p nil) + js2-bounce-indent-p nil + js-indent-align-list-continuation nil + js-chain-indent nil + js-switch-indent-offset 2) ;; "_" as word so company completes kabeb-case (modify-syntax-entry ?_ "w" js2-mode-syntax-table) diff --git a/modes/init-jump.el b/modes/init-jump.el index b208b38..d78acff 100644 --- a/modes/init-jump.el +++ b/modes/init-jump.el @@ -13,5 +13,4 @@ "g d" 'evil-goto-definition) :commands (dumb-jump-go)) - (provide 'init-jump) diff --git a/modes/init-lisp.el b/modes/init-lisp.el index 3a07215..3a9c8ab 100644 --- a/modes/init-lisp.el +++ b/modes/init-lisp.el @@ -1,10 +1,9 @@ (setq initial-scratch-message (concat ";; Happy hacking, " user-login-name " - Emacs ♥ you!\n\n")) -(general-define-key [remap eval-expression] 'pp-eval-expression) - -(when (maybe-require-package 'ipretty) - (add-hook 'after-init-hook 'ipretty-mode)) +;; (general-define-key [remap eval-expression] 'pp-eval-expression) +;; (when (maybe-require-package 'ipretty) +;; (add-hook 'after-init-hook 'ipretty-mode)) (defun jester/maybe-set-bundled-elisp-readonly () @@ -60,12 +59,12 @@ (run-hooks 'jester-elispy-modes-hook)) (defconst jester-elispy-modes - '(emacs-lisp-mode ielm-mode) + '(emacs-lisp-mode inferior-emacs-lisp-mode) "Major modes relating to elisp.") (defconst jester-lispy-modes (append jester-elispy-modes - '(lisp-mode inferior-lisp-mode lisp-interaction-mode)) + '(lisp-mode lisp-interaction-mode)) "Major modes relating to lisp.") (defconst jester-elispy-maps @@ -182,7 +181,7 @@ (add-hook! 'emacs-lisp-mode-hook (setq mode-name "ELisp")) ;; load it everywhere ;; :hook (prog-mode . lispyville-mode) - :hook ((emacs-lisp-mode ielm-mode lisp-mode inferior-lisp-mode lisp-interaction-mode) . lispyville-mode) + :hook ((emacs-lisp-mode lisp-mode inferior-emacs-lisp-mode lisp-interaction-mode) . lispyville-mode) :config (lispyville-set-key-theme '(operators @@ -198,17 +197,21 @@ (general-define-key :keymaps 'evil-inner-text-objects-map "l" 'lispyville-inner-list - "f" 'lispyville-inner-function) + "f" 'lispyville-inner-function + "c" 'lispyville-inner-comment) + ;; `lispyville-inner-atom' is bound in init-web.el (general-define-key :keymaps 'evil-outer-text-objects-map "l" 'lispyville-a-list - "f" 'lispyville-a-function) + "f" 'lispyville-a-function + "c" 'lispyville-a-comment) - ;; manually set prettify key + ;; manually set prettify and comment key (jester/with-leader - "," - (general-predicate-dispatch 'evil-indent - (memq major-mode '(emacs-lisp-mode lisp-mode)) 'lispyville-prettify)) + "," (general-predicate-dispatch 'evil-indent + (memq major-mode jester-lispy-modes) 'lispyville-prettify) + ";" (general-predicate-dispatch 'evilnc-comment-operator + (memq major-mode jester-lispy-modes) 'lispyville-comment-or-uncomment)) ;; some other lispy{,ville} keys (general-define-key diff --git a/modes/init-minibuffer.el b/modes/init-minibuffer.el index 78b36ba..c09f1ff 100644 --- a/modes/init-minibuffer.el +++ b/modes/init-minibuffer.el @@ -14,6 +14,11 @@ "H-x" 'kill-region "" 'keyboard-escape-quit) +(general-define-key + :keymaps 'evil-ex-completion-map + "M-p" 'previous-complete-history-element + "M-n" 'next-complete-history-element) + (general-define-key :keymaps 'read-expression-map "C-r" 'counsel-minibuffer-history) diff --git a/modes/init-mode-line.el b/modes/init-mode-line.el index c6d0121..90048f8 100644 --- a/modes/init-mode-line.el +++ b/modes/init-mode-line.el @@ -10,35 +10,35 @@ 'face face)) (defvar jester/flycheck-mode-line -;; (setq jester/flycheck-mode-line ;; this is for debug - '(:eval - (when (featurep 'flycheck) (pcase flycheck-last-status-change - (`not-checked nil) - (`no-checker "❄") - (`running (propertize "..." 'face 'success)) - (`errored (propertize "!" 'face 'error)) - (`finished - (let* ((error-counts (flycheck-count-errors flycheck-current-errors)) - (no-errors (cdr (assq 'error error-counts))) - (no-warnings (cdr (assq 'warning error-counts))) - (face (cond (no-errors 'error) - (no-warnings 'warning) - (t 'success)))) - (append - (if no-errors - (list - (propertize "❌" 'face '(:family "Apple Color Emoji" :height 0.7)) - (propertize (format "%s" (or no-errors 0)) - 'face 'error)) - nil) - (if no-warnings - (list - (propertize "⚠" 'face '(:family "Apple Color Emoji" :height 0.8)) - (propertize (format "%s" (or no-warnings 0)) - 'face 'warning)) - nil)))) - (`interrupted ".") - (`suspicious '(propertize "?" 'face 'warning)))))) + '(:eval + (when (featurep 'flycheck) + (pcase flycheck-last-status-change + (`not-checked nil) + (`no-checker "❄") + (`running (propertize "..." 'face 'success)) + (`errored (propertize "!" 'face 'error)) + (`finished + (let* ((error-counts (flycheck-count-errors flycheck-current-errors)) + (no-errors (cdr (assq 'error error-counts))) + (no-warnings (cdr (assq 'warning error-counts))) + (face (cond (no-errors 'error) + (no-warnings 'warning) + (t 'success)))) + (append + (if no-errors + (list + (propertize "❌" 'face '(:family "Apple Color Emoji" :height 0.7)) + (propertize (format "%s" (or no-errors 0)) + 'face 'error)) + nil) + (if no-warnings + (list + (propertize "⚠" 'face '(:family "Apple Color Emoji" :height 0.8)) + (propertize (format "%s" (or no-warnings 0)) + 'face 'warning)) + nil)))) + (`interrupted ".") + (`suspicious '(propertize "?" 'face 'warning)))))) (defvar jester/which-function-mode-line-off-modes '(web-mode scss-mode css-mode)) @@ -56,9 +56,14 @@ ;; ;; evil state ;; '(:eval evil-mode-line-tag) + "%1" + '(:eval (when (buffer-narrowed-p) + (format " %s" + (propertize "" 'face '((:family "github-octicons")))))) + "%1" '(:eval (when defining-kbd-macro - (format " %s%c " + (format " %s%c" (propertize "" 'face '((:family "FontAwesome"))) evil-this-macro))) @@ -68,16 +73,15 @@ "%1" '(:eval (when (and (featurep 'anzu) anzu--state) (concat " " (anzu--update-mode-line)))) - "%1 " + "%1" ;; the buffer name; the file name as a tool tip - '(:eval (propertize "%b " 'face 'font-lock-keyword-face + '(:eval (propertize " %b" 'face 'font-lock-keyword-face 'help-echo (buffer-file-name))) - "%1" + " %1" ;; the current major mode for the buffer. '(:eval mode-name) - '(:eval (when (and (featurep 'flycheck) flycheck-mode) " ")) "%1" jester/flycheck-mode-line diff --git a/modes/init-rust.el b/modes/init-rust.el new file mode 100644 index 0000000..14a7187 --- /dev/null +++ b/modes/init-rust.el @@ -0,0 +1,4 @@ +(use-package rust-mode + :mode "\\.rs\\'") + +(provide 'init-rust) diff --git a/modes/init-themes.el b/modes/init-themes.el index 008cf1a..14bb350 100644 --- a/modes/init-themes.el +++ b/modes/init-themes.el @@ -3,8 +3,12 @@ (require-package 'doom-themes) (require-package 'zenburn-theme) +(setq solarized-use-variable-pitch nil + solarized-scale-org-headlines nil + solarized-scale-outline-headlines nil) + ;; If you don't customize it, this is the theme you get. -(setq-default custom-enabled-themes '(solarized-light)) +(setq custom-enabled-themes '(solarized-light)) ;; Ensure that themes will be applied even if they have not been customized (defun reapply-themes () diff --git a/modes/init-ui5.el b/modes/init-ui5.el index 5cdc61b..3e8d703 100644 --- a/modes/init-ui5.el +++ b/modes/init-ui5.el @@ -1,17 +1,184 @@ -(defun jester/ui5-gen-define-callback-params () - "According to the declared classes that are imported, generate param symbols accordingly, write the callback function params." +(setq ui5-jq-ns "jquery.sap.global") + +(setq ui5-class-list (list ui5-jq-ns + "sap/base/util/ObjectPath" + "sap/base/util/UriParameters" + "sap/base/Log" + "sap/base/security/URLWhitelist" + "sap/base/util/deepEqual" + "sap/ui/util/Storage" + "sap/ui/events/KeyCodes" + "sap/ui/core/mvc/Controller" + "sap/ui/core/mvc/JSView" + "sap/base/security/encodeXML" + "sap/ui/Device" + "sap/ui/util/Mobile" + "sap/base/i18n/ResourceBundle" + "sap/base/util/uid")) + +(defun ui5-find-dependency-and-param-area () + "Find the start and end position of dependency list and callback params for sap.ui.define. +Returns a plist including these keys: +:dep-start +:dep-end +:param-start +:param-end" + (save-match-data + (let ((pos-plist)) + (goto-char (point-min)) + (re-search-forward (rx (sequence bol + "sap.ui.define(" + (0+ (not (any "\n"))) + "[" + eol))) + (setq pos-plist (plist-put pos-plist :dep-start (point))) + (search-forward "], function (") + (setq pos-plist (plist-put pos-plist :param-start (point))) + (setq pos-plist (plist-put pos-plist :dep-end (line-beginning-position))) + (search-forward ")") + (backward-char) + (setq pos-plist (plist-put pos-plist :param-end (point))) + pos-plist))) + +(defun ui5-get-dependency-list () + "Returns the current dependency list for sap.ui.define." + (let* ((area (ui5-find-dependency-and-param-area)) + (trimmed-text (replace-regexp-in-string (rx (0+ (or "\t" " " "\n"))) + "" + (buffer-substring-no-properties + (plist-get area :dep-start) + (plist-get area :dep-end))))) + (if (string-equal trimmed-text "") + '() + (mapcar (lambda (quoted) (substring quoted 1 -1)) + (s-split "," trimmed-text))))) + +(defun ui5-write-dependencies-and-params (dependency-list) + "Re-write the dependency list in sap.ui.define. `DEPENDENCY-LIST' is a list of namespace strings." + (save-excursion + (let ((area (ui5-find-dependency-and-param-area))) + (setq dependency-list + (sort (mapcar (lambda (namespace) + (unless (string-equal namespace ui5-jq-ns) + (setq namespace (s-replace "." "/" namespace))) + namespace) + dependency-list) + 'string<)) + ;; write param first. If we write dependencies first, param positions would be stale. + (goto-char (plist-get area :param-start)) + (delete-region (point) + (plist-get area :param-end)) + (insert (s-join ", " (mapcar (lambda (namespace) + (if (string-equal namespace ui5-jq-ns) + "jQuery" + (-last-item (s-split "/" namespace)))) + dependency-list))) + (goto-char (plist-get area :dep-start)) + (delete-region (point) + (plist-get area :dep-end)) + (insert (concat "\n" + (s-join ",\n" (mapcar (lambda (namespace) + (concat "'" namespace "'")) + dependency-list)) + "\n")) + (indent-region (plist-get area :dep-start) (plist-get area :dep-end))))) + +(defun ui5-organize-dependencies () + "Sort dependency list for sap.ui.define, write corresponding callback params to param list." + (interactive) + (save-excursion + (let ((dep-list (ui5-get-dependency-list))) + (ui5-write-dependencies-and-params dep-list)))) + +(defun ui5-goto-dependencies () + "Goto dependencies position, push a xref marker." + (interactive) + (xref-push-marker-stack) + (goto-char (plist-get (ui5-find-dependency-and-param-area) :dep-end)) + (beginning-of-line 0)) + +(defun ui5--import-internal (class-name) + "Import `CLASS-NAME' as dependency." + (save-excursion + (let ((dep-list (ui5-get-dependency-list))) + (print dep-list) + (unless (string-equal class-name ui5-jq-ns) + (setq class-name (s-replace "." "/" class-name))) + (add-to-list 'dep-list class-name) + (print dep-list) + (ui5-write-dependencies-and-params dep-list)))) + +(defun ui5-import () + "Select a class to import." + (interactive) + (if (region-active-p) + (ui5--import-internal (buffer-substring-no-properties (region-beginning) + (region-end))) + (ivy-read "import a class: " ui5-class-list + :initial-input (concat " " (thing-at-point 'symbol)) + :action 'ui5--import-internal + :history 'ui5-import-history + :keymap counsel-mode-map))) + +(defun ui5-import-and-shorten-region () + "Import and shorten, only in expression area." (interactive) - (let ((text (buffer-substring-no-properties (search-backward "[") (- (search-forward "]") 1))) - (fun-start-paren (search-forward "function (")) - (fun-end-paren (search-forward ")"))) - (backward-char) - (kill-region fun-start-paren (point)) - (insert (mapconcat 'identity - (jester/regexp-matches-in-string "\\/\\([^/',]+\\)',?$" text 1) - ", ")))) + (save-excursion + (let* ((target (buffer-substring-no-properties (region-beginning) (region-end))) + (short-name (-last-item (s-split "\\." target)))) + (ignore-errors + (let ((current-prefix-arg '(4))) + (call-interactively 'jester/evil-multiedit-match-all))) + (evil-multiedit--substitute) + (insert short-name) + (evil-multiedit-abort) + (ui5--import-internal target)))) + +(defun ui5--goto-suspect-internal () + "Internal function for going to next suspect." + (re-search-forward (rx (sequence word-start + "sap" + (1+ (sequence "." (1+ (or letter digit "_")))) + word-end)))) + +(defun ui5-goto-next-suspect () + "Goto next suspect looking like it needs to be shorten." + (interactive) + (save-match-data + (deactivate-mark) + (ui5--goto-suspect-internal) + ;; (while (not (jester/in-expression-area-p)) + ;; (ui5--goto-suspect-internal)) + (goto-char (match-beginning 0)) + (evil-visual-char) + (goto-char (match-end 0)) + (backward-char))) + +;; (defun ui5-import-and-shorten-semi-auto () +;; "If region active, import it and shorten every occurence in expression area. If not, try to mark next suspect and ask y/n." +;; (interactive) +;; (save-match-data +;; (while (and (re-search-forward (rx (sequence word-start +;; "sap" +;; (1+ (sequence "." (1+ letter))) +;; word-end))) +;; ;; (jester/in-expression-area-p) +;; ) +;; (let ((target (match-string 0)))) +;; (when (y-or-n-p "import the marked region?") +;; (evil-multiedit--start-regexp regexp beg end) +;; )))) (jester/with-major-leader 'js2-mode-map - "u u" 'jester/ui5-gen-define-callback-params) + "u o" 'ui5-organize-dependencies + "u g" 'ui5-goto-dependencies + "u i" 'ui5-import + "n" 'ui5-goto-next-suspect + "f" 'ui5-import-and-shorten-region) +(general-define-key + :keymaps 'js2-mode-map + "H-n" 'ui5-goto-next-suspect + "H-f" 'ui5-import-and-shorten-region) (defun jester/build-project () diff --git a/modes/init-utils.el b/modes/init-utils.el index 1d512ef..ff95526 100644 --- a/modes/init-utils.el +++ b/modes/init-utils.el @@ -121,7 +121,7 @@ with traditional regex based imenu." modes)) ;;---------------------------------------------------------------------------- -;; eval and always display in same window +;; eval and always display in same window (not used) ;;---------------------------------------------------------------------------- (defmacro jester/eval-with-display-in-same-window (&rest forms) "Eval `FORMS', with the behavior of `display-buffer' fixed to display in same window." @@ -129,6 +129,28 @@ with traditional regex based imenu." `(cl-flet ((display-buffer (buffer action) (display-buffer buffer '(display-buffer-same-window . nil)))) ,@forms)) +;;---------------------------------------------------------------------------- +;; hash table to alist +;;---------------------------------------------------------------------------- +(defun jester/hashtable-to-alist (table) + "Convert `TABLE' to an alist." + (let ((alist)) + (maphash + (lambda (k v) (push (cons k v) alist)) + table) + alist)) + +;;---------------------------------------------------------------------------- +;; am I in expression but not comment/string? +;;---------------------------------------------------------------------------- +(defun jester/in-expression-area-p () + "Am I in expression but not comment/string?" + (pcase major-mode + ('emacs-lisp-mode (not (lispy--in-string-or-comment-p))) + ('js2-mode (let ((node (js2-node-at-point))) + (and (not (js2-comment-node-p node)) + (not (js2-string-node-p node))))))) + ;;---------------------------------------------------------------------------- ;; add hook shorthand ;;---------------------------------------------------------------------------- diff --git a/modes/init-web.el b/modes/init-web.el index 74ebd2e..d8a9ed2 100644 --- a/modes/init-web.el +++ b/modes/init-web.el @@ -58,37 +58,32 @@ ;;---------------------------------------------------------------------------- ;; evil text object for html attribute ;;---------------------------------------------------------------------------- -(evil-define-text-object jester/evil-a-attribute (count &optional beg end type) - "Select an attribute, including the leading space." - :extend-selection nil - (list (- (web-mode-attribute-beginning-position) 1) - (+ (web-mode-attribute-end-position) 1))) - -(evil-define-text-object jester/evil-inner-attribute (count &optional beg end type) - "Select an attribute." - :extend-selection nil - (list (web-mode-attribute-beginning-position) - (+ (web-mode-attribute-end-position) 1))) - -(evil-define-text-object jester/evil-a-arg-or-attribute (count &optional beg end type) - "Select an arg or attribute." +(evil-define-text-object jester/evil-web-inner-attribute-or-arg (count &optional beg end type) + "Select an attribute, or arg, if not in html." :extend-selection nil (condition-case err - (cl-subseq (jester/evil-a-attribute) 0 2) - (error (cl-subseq (jester/evil-a-arg) 0 2)))) + (list (web-mode-attribute-beginning-position) + (+ (web-mode-attribute-end-position) 1)) + (error (cl-subseq (jester/evil-inner-arg) 0 2)))) -(evil-define-text-object jester/evil-inner-arg-or-attribute (count &optional beg end type) - "Select an arg or attribute." +(evil-define-text-object jester/evil-web-a-attribute-or-arg (count &optional beg end type) + "Select an attribute, including the leading space, or arg, if not in html." :extend-selection nil + ;; when not at an attribute, an error occurs (condition-case err - (cl-subseq (jester/evil-inner-attribute) 0 2) - (error (cl-subseq (jester/evil-inner-arg) 0 2)))) + (list (- (web-mode-attribute-beginning-position) 1) + (+ (web-mode-attribute-end-position) 1)) + (error (cl-subseq (jester/evil-a-arg) 0 2)))) -(general-define-key - :keymaps 'evil-outer-text-objects-map - "a" 'jester/evil-a-arg-or-attribute) (general-define-key :keymaps 'evil-inner-text-objects-map - "a" 'jester/evil-inner-arg-or-attribute) + "a" (general-predicate-dispatch 'jester/evil-inner-arg + (memq major-mode jester-lispy-modes) 'lispyville-inner-atom + (eq major-mode 'web-mode) 'jester/evil-web-inner-attribute-or-arg)) +(general-define-key + :keymaps 'evil-outer-text-objects-map + "a" (general-predicate-dispatch 'jester/evil-a-arg + (memq major-mode jester-lispy-modes) 'lispyville-a-atom + (eq major-mode 'web-mode) 'jester/evil-web-a-attribute-or-arg)) (provide 'init-web) diff --git a/snippets/emacs-lisp-mode/defun b/snippets/emacs-lisp-mode/defun index d01a0fa..8fc729f 100644 --- a/snippets/emacs-lisp-mode/defun +++ b/snippets/emacs-lisp-mode/defun @@ -4,5 +4,5 @@ # -- (defun ${1:fun} (${2:args}) "${3:docstring}" - ${4:(interactive${5: "${6:P}"})} - $0) \ No newline at end of file + ${4:(interactive${5: "${6:P}"}) + }$0) \ No newline at end of file diff --git a/snippets/js2-mode/forof b/snippets/js2-mode/forof index 45d3f40..46454cd 100755 --- a/snippets/js2-mode/forof +++ b/snippets/js2-mode/forof @@ -3,6 +3,6 @@ # name: forof # key: forof # -- -for(${1:const ${2:item}} in ${3:obj}) { +for(${1:const ${2:item}} of ${3:array}) { $0 } \ No newline at end of file diff --git a/snippets/js2-mode/sap-ui-define b/snippets/js2-mode/sap-ui-define new file mode 100644 index 0000000..9f8f3c8 --- /dev/null +++ b/snippets/js2-mode/sap-ui-define @@ -0,0 +1,6 @@ +# key: sdef +# name: sap.ui.define +# -- +sap.ui.define(${1:'${0:full.component.name}', }[ +], function () { +}); \ No newline at end of file