;;; polymode-compat.el --- Various compatibility fixes for other packages -*- lexical-binding: t -*-
;;
;; Author: Vitalie Spinu
;; Maintainer: Vitalie Spinu
;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
;; Version: 0.1
;; URL: https://github.com/polymode/polymode
;; Keywords: emacs
;;
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 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, 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 <https://www.gnu.org/licenses/>.
;;
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Commentary:
;;
;;
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Code:
;;; emacs 25 compat
;;; Various Wrappers for Around Advice
;; advice doesn't provide named symbols. So we need to define specialized
;; wrappers for some key functions (unfinished)
;;; LSP (lsp-mode and eglot)
;;
;; Emacs modifications `after-change-functions' to LSP insertions
;; https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_didChange
;;
;; INSERT: (50 56 0) means insert 6 chars starting at pos 50
;; {"range": {"start": {"line": 1, "character": 0},
;; "end" : {"line": 1, "character": 0}},
;; "text": "insert"}
;;
;; DELETE: (50 50 6) means delete 6 chars starting at pos 50
;; {"range": {"start": {"line": 1, "character": 0},
;; "end" : {"line": 1, "character": 6}},
;; "text": ""}
;;
;; REPLACE: (50 60 6) means delete 6 chars starting at pos 50, and replace
;; them with 10 chars
;; {"range": {"start": {"line": 1, "character": 0},
;; "end" : {"line": 1, "character": 6}},
;; "text": "new-insert"}
;;
;; INSERT:
;; before-change:(obeg,oend)=(50,50)
;; after-change:(nbeg,nend,olen)=(50,56,0)
;;
;; DELETE:
;; before-change:(obeg,oend)=(50,56)
;; after-change:(nbeg,nend,len)=(50,50,6)
;;
;; REPLACE:
;; before-change:(obeg,oend)=(50,56)
;; lsp-on-change:(nbeg,nend,olen)=(50,60,6)
;; We cannot compute original change location when modifications are complex
;; (aka multiple changes are combined). In those cases we send an entire
;; document.
;; advises
;; (advice-remove 'lsp--buffer-content #'polymode-lsp-buffer-content)
;; (advice-remove 'lsp--text-document-content-change-event #'polymode-lsp-change-event)
;;; Flyspel
;;; C/C++/Java
;; (advice-remove 'c-before-context-fl-expand-region #'pm-override-output-cons)
;; (advice-remove 'c-state-semi-safe-place #'pm-override-output-position)
;; c-font-lock-fontify-region calls it directly
;; (pm-around-advice 'font-lock-default-fontify-region #'pm-substitute-beg-end)
;;; Python
;;; Core Font Lock
;;; Editing
;; (pm-around-advice 'fill-paragraph #'pm-execute-narrowed-to-span)
;; (advice-remove 'fill-paragraph #'pm-execute-narrowed-to-span)
;; Synchronization of points does not work always as expected because some low
;; level functions move indirect buffers' points when operate in the base
;; buffer. See comment in `polymode-with-current-base-buffer'.
;; (defun polymode-with-save-excursion (orig-fun &rest args)
;; "Execute ORIG-FUN surrounded with `save-excursion'.
;; This function is intended to be used in advises of functions
;; which modify the buffer in the background and thus trigger
;; `pm-switch-to-buffer' on next post-command hook in a wrong place.
;; ARGS are passed to ORIG-FUN."
;; (if polymode-mode
;; (save-excursion
;; (apply orig-fun args))
;; (apply orig-fun args)))
;;
;; `save-buffer` misbehaves because after each replacement modification hooks
;; are triggered and poly buffer is switched in unpredictable fashion (#93).
;; This happens because basic-save-buffer uses save-buffer but not
;; save-excursion. Thus if base and indirect buffer don't have same point, at
;; the end of the function inner buffer will have the point from the base
;; buffer. Can be reproduced with (add-hook 'before-save-hook
;; 'delete-trailing-whitespace nil t) in the base buffer.
;;
;; (pm-around-advice 'basic-save-buffer #'polymode-with-save-excursion)
;; (advice-remove 'basic-save-buffer #'polymode-with-save-excursion)
;; Query replace were probably misbehaving due to unsaved match data (#92). The
;; following is probably not necessary. (pm-around-advice 'perform-replace
;; 'pm-execute-inhibit-modification-hooks)
;; No longer needed. See comment at pm-switch-to-buffer.
;; (defun polymode-newline-remove-hook-in-orig-buffer (fn &rest args)
;; "`newline' temporary sets `post-self-insert-hook' and removes it in wrong buffer.
;; This ARGS are passed to `newline'."
;; (if polymode-mode
;; (let* ((cbuf (current-buffer))
;; (old-hook (buffer-local-value 'post-self-insert-hook cbuf)))
;; (prog1 (apply fn args)
;; (unless (eq cbuf (current-buffer))
;; (unless (eq old-hook (buffer-local-value 'post-self-insert-hook cbuf))
;; (with-current-buffer cbuf
;; (if old-hook
;; (setq post-self-insert-hook old-hook)
;; (kill-local-variable 'post-self-insert-hook)))))))
;; (apply fn args)))
;; (pm-around-advice 'newline #'polymode-newline-remove-hook-in-orig-buffer)
;;; DESKTOP SAVE #194 #240
;; NB: desktop-save will not save indirect buffer.
;; For base buffer, if it's hidden as per #34, we will save it unhide by removing left whitespaces.
;;; MATLAB #199
;; matlab-mode is an old non-standard mode which doesn't trigger
;; `after-change-major-mode-hook`. As a result polymode cannot detect that
;; font-lock-mode is on and sets the `poly-lock-allow-fontification` to nil.
;; Explicitly trigger font-lock as a workaround.
;;; Undo Tree (#230)
;; Not clear why this fix works, or even why the problem occurs.
;;; EVIL
;;; HL line
;;; YAS
;;; Multiple cursors
;;; polymode-compat.el ends here