diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..9fb3f39 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,56 @@ +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events but only for the master branch + push: + branches: + - '*' + pull_request: + branches: [ master ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + emacs_version: + - '25.3' + - '26.3' + - '27.1' + - 'snapshot' + cask_version: + - 'snapshot' + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.9' + architecture: 'x64' + - uses: purcell/setup-emacs@master + with: + version: ${{ matrix.emacs_version }} + + - uses: conao3/setup-cask@master + with: + version: 'snapshot' + + - name: Run tests + env: + COVERALLS_FLAG_NAME: Emacs ${{ matrix.emacs_version }} + COVERALLS_PARALLEL: 1 + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + make install + make test + send-coverage-report: + runs-on: ubuntu-latest + if: always() + needs: test + steps: + - run: curl "https://coveralls.io/webhook?repo_name=$GITHUB_REPOSITORY&repo_token=${{ secrets.GITHUB_TOKEN }}" -d "payload[build_num]=$GITHUB_RUN_NUMBER&payload[status]=done" diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3ac3b63..0000000 --- a/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: emacs-lisp - -script: - - emacs --version - - make test - -env: - matrix: - - EVM_EMACS=emacs-26.1-travis - - EVM_EMACS=emacs-25.3-travis - # don't need 25.2 because it's the same 25.3 - - EVM_EMACS=emacs-25.1-travis - - EVM_EMACS=emacs-24.5-travis - - EVM_EMACS=emacs-24.4-travis - # - EVM_EMACS=emacs-git-snapshot-travis -# matrix: -# fast_finish: true -# # allow_failures: -# # - env: EVM_EMACS=emacs-git-snapshot-travis - -sudo: no -before_install: - - curl -fsSkL https://gist.github.com/rejeep/ebcd57c3af83b049833b/raw > travis.sh && source ./travis.sh - - evm install $EVM_EMACS --use --skip - - cask - -# notifications: -# email: false diff --git a/window-purpose-configuration.el b/window-purpose-configuration.el index fb18019..0794ffb 100644 --- a/window-purpose-configuration.el +++ b/window-purpose-configuration.el @@ -129,7 +129,7 @@ purpose of a buffer. The user configuration and extended configuration are used anyway." :group 'purpose :type 'boolean - :package-version "1.2") + :package-version '(window-purpose . "1.2")) (defcustom purpose-user-mode-purposes nil "User configured alist mapping of modes to purposes. @@ -143,7 +143,7 @@ If you set this variable in elisp-code, you should call the function (prog1 (set-default symbol value) (purpose-compile-user-configuration))) :initialize 'custom-initialize-default - :package-version "1.2") + :package-version '(window-purpose . "1.2")) (defcustom purpose-user-name-purposes nil "User configured alist mapping of names to purposes. @@ -157,7 +157,7 @@ If you set this variable in elisp-code, you should call the function (prog1 (set-default symbol value) (purpose-compile-user-configuration))) :initialize 'custom-initialize-default - :package-version "1.2") + :package-version '(window-purpose . "1.2")) (defcustom purpose-user-regexp-purposes nil "User configured alist mapping of regexps to purposes. @@ -171,7 +171,7 @@ If you set this variable in elisp-code, you should call the function (prog1 (set-default symbol value) (purpose-compile-user-configuration))) :initialize 'custom-initialize-default - :package-version "1.2") + :package-version '(window-purpose . "1.2")) (defvar purpose-extended-configuration nil "A plist containing `purpose-conf' objects. diff --git a/window-purpose-core.el b/window-purpose-core.el index b3be2f9..faef925 100644 --- a/window-purpose-core.el +++ b/window-purpose-core.el @@ -33,19 +33,19 @@ "purpose-mode configuration" :group 'windows :prefix "purpose-" - :package-version "1.2") + :package-version '(window-purpose . "1.2")) (defcustom default-purpose 'general "The default purpose for buffers which didn't get another purpose." :group 'purpose :type 'symbol - :package-version "1.2") + :package-version '(window-purpose . "1.2")) (defcustom default-file-purpose 'edit "The default purpose for buffers visiting a file which didn't get a purpose." :group 'purpose :type 'symbol - :package-version "1.6.1") + :package-version '(window-purpose . "1.6.1")) ;;; utilities diff --git a/window-purpose-fixes.el b/window-purpose-fixes.el index 2137165..9c722e8 100644 --- a/window-purpose-fixes.el +++ b/window-purpose-fixes.el @@ -29,7 +29,33 @@ (require 'window-purpose-switch) (require 'window-purpose-configuration) - +(defun purpose--fix-edebug () + "Integrates Edebug with Purpose." + + (with-eval-after-load 'edebug + (defun purpose--edebug-pop-to-buffer-advice (buffer &optional window) + "Reimplements `edebug-pop-to-buffer' using `pop-to-buffer' + +Since `edebug-pop-to-buffer' simply splits the last selected +window before the minibuffer was popped up, the window it picks +to display a edebug buffer does not respect `window-purpose' as +all. This advice reimplements it by replacing the window +spliting logic with `pop-to-buffer'." + (setq window + (cond + ((and (edebug-window-live-p window) + (eq (window-buffer window) buffer)) + window) + ((eq (window-buffer) buffer) + (selected-window)) + ((get-buffer-window buffer 0)) + (t (get-buffer-window (pop-to-buffer buffer))))) + (set-window-buffer window buffer) + (select-window window) + (unless (memq (framep (selected-frame)) '(nil t pc)) + (x-focus-frame (selected-frame))) + (set-window-hscroll window 0)) + (advice-add 'edebug-pop-to-buffer :override 'purpose--edebug-pop-to-buffer-advice))) ;;; `compilation-next-error-function' sometimes hides the compilation buffer ;;; when Purpose is on. Solution: make the buffer's window dedicated while @@ -58,6 +84,23 @@ Prevents `isearch-describe-*' commands from bypassing purpose." (setq isearch--display-help-action '(purpose--action-function . nil)))) +(defun purpose--fix-next-error () + "Integrate `window-purpose' and `next-error'. + +Under `next-error-follow-minor-mode', `next-error-no-select' will +override window-purpose's `display-buffer-overriding-action'. +This will result in source buffers not displaying in the +purpose-dedicated window for source code in complex window +layouts. This fix makes sure `next-error' works with +window-purpose." + (defun purpose--next-error (oldfun &rest args) + "Make sure `next-error' respects `purspose--action-function'." + (interactive (lambda (spec) (advice-eval-interactive-spec spec))) + (let ((display-buffer-overriding-action '(purpose--action-function . nil))) + (apply oldfun args))) + (advice-add 'next-error :around 'purpose--next-error)) + + ;;; Hydra's *LV* buffer should be ignored by Purpose (defun purpose--fix-hydra-lv () "Add hydra's LV buffer to Purpose's ignore list." @@ -254,28 +297,49 @@ Don't call this function before `popwin' is loaded." (add-to-list 'purpose-special-action-sequences '(Zone display-buffer-same-window)))) + +(defun purpose--fix-whitespace () + "Integrate `window-purpose' with `whitespace'." + (with-eval-after-load 'whitespace + (defun purpose--whitespace-display-window-advice (buffer) + "Stops `whitespace-display-window' from splitting and shrinking windows." + (with-current-buffer buffer + (special-mode) + (goto-char (point-min))) + (switch-to-buffer buffer)) + (advice-add 'whitespace-display-window :override + 'purpose--whitespace-display-window-advice))) + + ;;; install fixes (defun purpose-fix-install (&rest exclude) "Install fixes for integrating Purpose with other features. EXCLUDE is a list of integrations to skip. Known members of EXCLUDE are: +- 'edebug : don't integrate with edebug - 'compilation-next-error-function : don't integrate with `compilation-next-error-function'. - 'isearch : don't integrate with isearch +- 'next-error : don't integrate with `next-error' - 'lv : don't integrate with lv (hydra) - 'helm : don't integrate with helm - 'neotree : don't integrate with neotree - 'org : don't integrate with org - 'popwin : don't integrate with popwin - 'guide-key : don't integrate with guide-key -- 'which-key : don't integrate with which-key" +- 'which-key : don't integrate with which-key +- 'whitespace : don't integrate with whitespace" (interactive) + (unless (member 'edebug exclude) + (purpose--fix-edebug)) (unless (member 'compilation-next-error-function exclude) (advice-add 'compilation-next-error-function :around #'purpose--fix-compilation-next-error)) (unless (member 'isearch exclude) (purpose--fix-isearch)) + (unless (member 'next-error exclude) + (purpose--fix-next-error)) (unless (member 'lv exclude) (purpose--fix-hydra-lv)) (unless (member 'helm exclude) @@ -293,7 +357,9 @@ are: (unless (member 'magit-popup exclude) (purpose--fix-magit-popup)) (unless (member 'zone exclude) - (purpose--fix-zone))) + (purpose--fix-zone)) + (unless (member 'whitespace exclude) + (purpose--fix-whitespace))) (provide 'window-purpose-fixes) ;;; window-purpose-fixes.el ends here diff --git a/window-purpose-layout.el b/window-purpose-layout.el index bf58325..11403db 100644 --- a/window-purpose-layout.el +++ b/window-purpose-layout.el @@ -40,21 +40,21 @@ "If nil, don't use layouts from `purpose--built-in-layouts-dir'." :group 'purpose :type 'boolean - :package-version "1.6") + :package-version '(window-purpose . "1.6")) (defcustom purpose-default-layout-file (concat user-emacs-directory ".purpose-layout") "Default file for saving/loading purpose layout." :group 'purpose :type 'file - :package-version "1.2") + :package-version '(window-purpose . "1.2")) (defcustom purpose-layout-dirs (list (locate-user-emacs-file "layouts/")) "List of directories containing layout files." :group 'purpose :type '(repeat file) - :package-version "1.5") + :package-version '(window-purpose . "1.5")) (defcustom purpose-get-extra-window-params-functions nil "If non-nil, this variable should be a list of functions. @@ -62,7 +62,7 @@ This variable is used by `purpose-window-params'. See `purpose-window-params' for more details." :group 'purpose :type 'hook - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-set-window-properties-functions nil "Hook to run after calling `purpose-set-window-properties'. @@ -75,7 +75,7 @@ WINDOW is nil, your function should act on the selected window instead." :group 'purpose :type 'hook - :package-version "1.2") + :package-version '(window-purpose . "1.2")) (defvar purpose-recent-window-layouts (make-ring 50) "Most recently used window layouts. diff --git a/window-purpose-switch.el b/window-purpose-switch.el index 16766bf..703fa9f 100644 --- a/window-purpose-switch.el +++ b/window-purpose-switch.el @@ -55,20 +55,20 @@ Any other value is treated the same as nil." (const error) (const nil) function) - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-display-buffer-functions nil "Hook to run after displaying a buffer with `purpose--action-function'. This hook is called with one argument - the window used for display." :group 'purpose :type 'hook - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-select-buffer-hook nil "Hook to run after selecting a buffer with `purpose-select-buffer'." :group 'purpose :type 'hook - :package-version "1.2") + :package-version '(window-purpose . "1.2")) (defvar purpose--active-p nil "When nil, Purpose's advices and `purpose--action-function' are not @@ -139,7 +139,7 @@ case, `purpose-display-at-top-height' is ignored." :group 'purpose :type '(choice number (const nil)) - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-display-at-bottom-height 8 "Height for new windows created by `purpose-display-at-bottom'. @@ -153,7 +153,7 @@ this case, `purpose-display-at-bottom-height' is ignored." :group 'purpose :type '(choice number (const nil)) - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-display-at-left-width 32 "Width for new windows created by `purpose-display-at-left'. @@ -166,7 +166,7 @@ case, `purpose-display-at-left-width' is ignored." :group 'purpose :type '(choice number (const nil)) - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-display-at-right-width 32 "Width for new windows created by `purpose-display-at-right'. @@ -180,7 +180,7 @@ this case, `purpose-display-at-right-width' is ignored." :group 'purpose :type '(choice number (const nil)) - :package-version "1.4") + :package-version '(window-purpose . "1.4")) diff --git a/window-purpose-utils.el b/window-purpose-utils.el index 3a19c86..ebd6532 100644 --- a/window-purpose-utils.el +++ b/window-purpose-utils.el @@ -32,7 +32,7 @@ Toggling this on will cause Purpose to produce some debug messages." :group 'purpose :type 'boolean - :package-version "1.2") + :package-version '(window-purpose . "1.2")) (defun purpose-message (format-string &rest args) "Produce a message if `purpose-message-on-p' is non-nil. diff --git a/window-purpose-x.el b/window-purpose-x.el index 6045997..1661566 100644 --- a/window-purpose-x.el +++ b/window-purpose-x.el @@ -215,22 +215,40 @@ imenu." (magit-wazzup-mode . magit-wazzup))) "Configuration that gives each magit major mode its own purpose.") +(defvar purpose-x-old-magit-display-buffer-function nil + "Stores `magit-display-buffer-function'. + +The value of `magit-display-buffer-function' at the time +`purpose-x-magit-single-on' or `purpose-x-magit-multi-on' is +invoked.") + +(defun purpose-x-magit-display-buffer-function (buffer) + "Integrate `magit' with `window-purpose'." + (let ((display-buffer-overriding-action '(purpose--action-function . nil))) + (funcall purpose-x-old-magit-display-buffer-function buffer))) + ;;;###autoload (defun purpose-x-magit-single-on () "Turn on magit-single purpose configuration." (interactive) + (setq purpose-x-old-magit-display-buffer-function magit-display-buffer-function + magit-display-buffer-function 'purpose-x-magit-display-buffer-function) (purpose-set-extension-configuration :magit purpose-x-magit-single-conf)) ;;;###autoload (defun purpose-x-magit-multi-on () "Turn on magit-multi purpose configuration." (interactive) + (setq purpose-x-old-magit-display-buffer-function magit-display-buffer-function + magit-display-buffer-function 'purpose-x-magit-display-buffer-function) (purpose-set-extension-configuration :magit purpose-x-magit-multi-conf)) (defun purpose-x-magit-off () "Turn off magit purpose configuration (single or multi)." (interactive) - (purpose-del-extension-configuration :magit)) + (purpose-del-extension-configuration :magit) + (setq magit-display-buffer-function purpose-x-old-magit-display-buffer-function + purpose-x-old-magit-display-buffer-function nil)) ;;; --- purpose-x-magit ends here --- @@ -302,7 +320,7 @@ compatible with `display-buffer'." (const left) (const right) function) - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-x-popwin-width 0.4 "Width of popup window when displayed at left or right. @@ -311,7 +329,7 @@ Can have the same values as `purpose-display-at-left-width' and :group 'purpose :type '(choice number (const nil)) - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-x-popwin-height 0.35 "Height of popup window when displayed at top or bottom. @@ -320,7 +338,7 @@ Can have the same values as `purpose-display-at-top-height' and :group 'purpose :type '(choice number (const nil)) - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-x-popwin-major-modes '(help-mode compilation-mode @@ -334,7 +352,7 @@ When changing the value of this variable in elisp code, you should call (prog1 (set-default symbol value) (purpose-x-popwin-update-conf))) :initialize 'custom-initialize-default - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-x-popwin-buffer-names '("*Shell Command Output*") "List of buffer names that should be opened as popup windows. @@ -348,7 +366,7 @@ When changing the value of this variable in elisp code, you should call (prog1 (set-default symbol value) (purpose-x-popwin-update-conf))) :initialize 'custom-initialize-default - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defcustom purpose-x-popwin-buffer-name-regexps nil "List of regexp that should be opened as popup windows. @@ -362,7 +380,7 @@ When changing the value of this variable in elisp code, you should call (prog1 (set-default symbol value) (purpose-x-popwin-update-conf))) :initialize 'custom-initialize-default - :package-version "1.4") + :package-version '(window-purpose . "1.4")) (defun purpose-x-popupify-purpose (purpose &optional display-fn) "Set up a popup-like behavior for buffers with purpose PURPOSE.