从spacemacs迁移到DOOM;company-childframe by @tumashu

先visible再move视觉上会有问题的。。我觉得可能还是得等upstream fix。。

有没有人向开发者反馈或者报告bug?

实测可以接受,和上次的移动距离不远

lsp-ui-doc应该没啥问题 但是company的话如果在不同行之间来回编辑还是挺蛋疼的。。而且第一次会从initial position出现然后再移动到正常的位置。。强迫症表示还是不太能接受。。。所以我用alpha=0来隐藏移动到位之前的frame 但是不确定这样会不会有performance issue

不知道有没。。我不大清楚提交的规则

今天在GNU Emacs 26.0.90和 macOS10.13上测试了下 child-frame,基本功能是能使用的。只是有几个小问题:

  1. 窗口边框有一条白线或者黑线,看起来很碍眼;
  2. child frame 和 desktop 不大兼容。重启发现有 error:set-frame-parameter: Invalid specification of ‘parent-frame’.
  3. company-quick-help 不能使用了。

child frame也许能解决popup窗口闪烁和格式混乱的问题,tooltip 在每个平台的表现也不一致,不给力。

这个想法赞!

1 个赞

贴个图看看,我这边没有你说的白线

这个有可能, 毕竟这个功能刚刚发掘出来,所以遇到不兼容的问题也很正常

边框线是我为了区分明显自己加的

你把frame parameter list里的internal-border改成nil就行了

花了一早上简单尝试 从 spacemacs 迁移到 doom-emacs,感觉 keybinding 好不习惯,如果要整一套符合 spacemacs 的又太麻烦了

我是觉得很多spacemacs的keybinding太麻烦。。然后干脆按自己的喜好重弄了一遍。。

嗯,是的。

我想从 spacemacs 转出的原因也类似:

  1. 感觉 spacemacs maintain 的力度越来越小了
    1. 上千个 issue,经过几年清理都没清理完
    2. 新的稳定版本发布周期越来越长
  2. layer 质量参差不齐,经常有不适合自己的地方
  3. 默认配置和 evil 的搭配也有不太好的地方,比如很多 spacemacs function 都没有经 过 evil-declare-ignore-repeat

之前用了快一年自己的设置,但是发现自己维护不过来,而且在做很多重复工作。前两天又 迁移回 spacemacs

找个周末再好好试试 doom

我发现与主题有关,如果重新加载主题边框就消失了。

所以我坚决不入 Spacemacs,一是太慢,二就是不符合个人习惯。很多按键、配置都太复杂,也不是最原汁原味的 Emacs。所以我一直使用自己的配置 GitHub - seagle0128/.emacs.d: Centaur Emacs - A Fancy and Fast Emacs Configuration.

3 个赞

原来如此~~~

有人提交了, 好像问题解决了.

https://lists.gnu.org/archive/html/bug-gnu-emacs/2018-01/msg00105.html

我创建了一个临时的包 company-childframe,专门用来测试 childframe 作为 选词菜单的可行性

https://github.com/tumashu/company-childframe/blob/master/company-childframe.el

在 window 和 linux 下, 我可以测试, 但 macos 就无能为力了, 而且 child-frame 在 macos 上似乎有许多 bug, 大家一起折腾吧, 比单打独斗更有效率, 如果你没有签 gnu 的文件, 那就提交 issue 和可能存在的问题,我慢慢改

等这个方式稳定之后,我就考虑给 company 提交一个 PR。

mac上用不了 好像位置的计算有点问题 而且光标会跳来跳去的 之前的那个code是可以用的

*** /Users/xfu/.emacs.d/modules/private/xfu/local/company-childframe.el	2018-01-05 01:23:52.000000000 +0800
--- /Users/xfu/.emacs.d/modules/private/xfu/local/test-company-childframe.el	2018-01-08 09:53:38.000000000 +0800
***************
*** 4,45 ****
  ;;
  
  ;;; Code:
! 
  (require 'company)
  
  (defvar company-childframe-child-frame nil)
  (defvar company-childframe-current-frame nil)
- (defun company-childframe-compute-pixel-position (pos pixel-width pixel-height)
-   "Return pixel position of POS in WINDOW, which indicates relative
- coordinates of bottom left corner of the object, its returned value is
- like (X . Y)
- 
- If PIXEL-WIDTH and PIXEL-HEIGHT are given, this function regard these
- values as the size of a small window located around the POS, for example:
- tooltip. These values are used to adjust the small window's location and
- let it not disappear by sticking out of the display.
  
! This function is shameless steal from pos-tip."
    (let* ((window (selected-window))
           (frame (window-frame window))
           (xmax (frame-pixel-width frame))
           (ymax (frame-pixel-height frame))
!          (posn (posn-at-point pos window))
!          (line (cdr (posn-actual-col-row posn)))
!          (line-height
!           (or (window-line-height line window)
!               (and (redisplay t)
!                    (window-line-height line window))))
!          (x-y (or (posn-x-y posn) '(0 . 0)))
           (x (+ (car (window-inside-pixel-edges window))
!                (car x-y)))
!          (y0 (+ (cadr (window-pixel-edges window))
!                 (or (nth 2 line-height) (cdr x-y))))
!          (y (+ y0 (car line-height))))
!     (cons (max 0 (min x (- xmax (or pixel-width 0))))
!           (max 0 (if (> (+ y (or pixel-height 0)) ymax)
!                      (- y0 (or pixel-height 0))
!                    y)))))
  
  (defun company-childframe--update-1 (string position)
    (let* ((window-min-height 1)
--- 4,48 ----
  ;;
  
  ;;; Code:
! (require 'cl-lib)
  (require 'company)
  
  (defvar company-childframe-child-frame nil)
  (defvar company-childframe-current-frame nil)
  
! (defun company-childframe-compute-pixel-position (pos tooltip-width tooltip-height)
!   "Return bottom-left-corner pixel position of POS in WINDOW.
! its returned value is like (X . Y)
! 
! If TOOLTIP-WIDTH and TOOLTIP-HEIGHT are given, this function will use
! two values to adjust its output position, make sure the *tooltip* at
! position not disappear by sticking out of the display."
    (let* ((window (selected-window))
           (frame (window-frame window))
           (xmax (frame-pixel-width frame))
           (ymax (frame-pixel-height frame))
!          (posn-top-left (posn-at-point pos window))
           (x (+ (car (window-inside-pixel-edges window))
!                (or (car (posn-x-y posn-top-left)) 0)))
!          (y-top (+ (cadr (window-pixel-edges window))
!                    (or (cdr (posn-x-y posn-top-left)) 0)))
!          (posn-next-line-beginning
!           (save-excursion
!             (goto-char pos)
!             (if (= (line-end-position) (point-max))
!                 (let (posn)
!                   (goto-char (point-max))
!                   (insert "\n")
!                   (setq posn (posn-at-point (point) window))
!                   (delete-char -1)
!                   posn)
!               (vertical-motion 1)
!               (posn-at-point (point) window))))
!          (y-buttom (or (cdr (posn-x-y posn-next-line-beginning)) 0)))
!     (cons (max 0 (min x (- xmax (or tooltip-width 0))))
!           (max 0 (if (> (+ y-buttom (or tooltip-height 0)) ymax)
!                      (- y-top (or tooltip-height 0))
!                    y-buttom)))))
  
  (defun company-childframe--update-1 (string position)
    (let* ((window-min-height 1)
***************
*** 47,71 ****
           (frame-resize-pixelwise t)
           (frame (window-frame))
           (buffer (get-buffer-create " *company-childframe*"))
!          (min-size '(1 . (+ company-tooltip-minimum-width 1)))
           x-and-y)
      (unless (and (eq frame company-childframe-current-frame)
!                  (eq (frame-live-p company-childframe-child-frame) 'ns))
        (when (frame-live-p company-childframe-child-frame)
          (delete-frame company-childframe-child-frame))
        (setq company-childframe-current-frame frame)
        (setq company-childframe-child-frame
              (let ((after-make-frame-functions nil))
                (make-frame
!                `(
!                  (parent-frame . ,frame)
!                  (left . 0)
!                  (top . 0)
                   (no-accept-focus . t)
                   (min-width  . t)
                   (min-height . t)
-                  (internal-border-width . 0)
                   (border-width . 0)
                   (vertical-scroll-bars . nil)
                   (horizontal-scroll-bars . nil)
                   (left-fringe . 0)
--- 50,71 ----
           (frame-resize-pixelwise t)
           (frame (window-frame))
           (buffer (get-buffer-create " *company-childframe*"))
!          (min-size '(2 . 10))
           x-and-y)
      (unless (and (eq frame company-childframe-current-frame)
!                  (frame-live-p company-childframe-child-frame))
        (when (frame-live-p company-childframe-child-frame)
          (delete-frame company-childframe-child-frame))
        (setq company-childframe-current-frame frame)
        (setq company-childframe-child-frame
              (let ((after-make-frame-functions nil))
                (make-frame
!                `((parent-frame . ,frame)
                   (no-accept-focus . t)
                   (min-width  . t)
                   (min-height . t)
                   (border-width . 0)
+                  (internal-border-width . 0)
                   (vertical-scroll-bars . nil)
                   (horizontal-scroll-bars . nil)
                   (left-fringe . 0)
***************
*** 79,135 ****
                   (visibility . nil)
                   (cursor-type . nil)
                   (minibuffer . nil)
!                  (width . 0)
!                  (height . 0)
                   (no-special-glyphs . t)
!                  (ns-appearance . nil)
!                  (background-color . ,(face-attribute 'default :background))
!                  ))))
!       )
!     (set-window-buffer
!      (frame-root-window company-childframe-child-frame) buffer)
      (with-current-buffer buffer
-       (setq mode-line-format nil
-             header-line-format nil)
        (erase-buffer)
        (insert string))
!     (setq x-and-y (company-childframe-compute-pixel-position
!                    position
!                    (frame-pixel-width company-childframe-child-frame)
!                    (frame-pixel-height company-childframe-child-frame)))
!     (fit-frame-to-buffer company-childframe-child-frame nil (car min-size) nil (cdr min-size))
!     (set-frame-position company-childframe-child-frame (car x-and-y) (+ (cdr x-and-y) 1))
!     (make-frame-visible company-childframe-child-frame)
!     )
!   )
  
  (defun company-childframe--update ()
    "Update contents of company tooltip."
    (let* ((height (min company-tooltip-limit company-candidates-length))
           (lines (company--create-lines company-selection height))
!          (contents (mapconcat #'identity lines "\n"))
!          ;; (contents (car lines))
!          )
      (company-childframe--update-1 contents (- (point) (length company-prefix)))))
  
  (defun company-childframe-show ()
    "Show company tooltip at point."
!   (if (frame-live-p company-childframe-child-frame)
!       (progn
!         ;; (make-frame-visible company-childframe-child-frame)
!              (company-childframe--update)
!              )
!     (company-childframe--update)
!     ))
  (defun company-childframe-hide ()
    "Hide company tooltip."
    (when (frame-live-p company-childframe-child-frame)
      (make-frame-invisible company-childframe-child-frame)))
  (defun company-childframe-kill ()
    "Kill company-childframe's frame and buffer."
    (when (frame-live-p company-childframe-child-frame)
!     (delete-frame company-childframe-child-frame)
      (setq company-childframe-child-frame nil)))
  (defun company-childframe-frontend (command)
    "`company-mode' frontend using a real X tooltip.
  COMMAND: See `company-frontends'."
--- 79,133 ----
                   (visibility . nil)
                   (cursor-type . nil)
                   (minibuffer . nil)
!                  (width . 50)
!                  (height . 1)
                   (no-special-glyphs . t)
!                  (background-color . ,(face-attribute 'company-tooltip :background))))))
!       (let ((window (frame-root-window pyim-tooltip-child-frame)))
!         ;; This method is more stable than 'setq mode/header-line-format nil'
!         (set-window-parameter window 'mode-line-format 'none)
!         (set-window-parameter window 'header-line-format 'none)
!         (set-window-buffer window buffer)))
! 
      (with-current-buffer buffer
        (erase-buffer)
        (insert string))
! 
!     (let ((child-frame company-childframe-child-frame))
!       ;; Macos can not move a child-frame when it invisible,
!       ;; the good news is that it has been fixed in emacs master
!       ;; https://lists.gnu.org/archive/html/bug-gnu-emacs/2018-01/msg00105.html
!       (make-frame-visible child-frame)
!       (fit-frame-to-buffer
!        child-frame nil (car min-size) nil (cdr min-size))
!       (setq x-and-y (company-childframe-compute-pixel-position
!                      position
!                      (frame-pixel-width child-frame)
!                      (frame-pixel-height child-frame)))
!       (set-frame-position child-frame (car x-and-y) (+ (cdr x-and-y) 1)))))
  
  (defun company-childframe--update ()
    "Update contents of company tooltip."
    (let* ((height (min company-tooltip-limit company-candidates-length))
           (lines (company--create-lines company-selection height))
!          (contents (mapconcat #'identity lines "\n")))
      (company-childframe--update-1 contents (- (point) (length company-prefix)))))
  
  (defun company-childframe-show ()
    "Show company tooltip at point."
!   (company-childframe--update))
! 
  (defun company-childframe-hide ()
    "Hide company tooltip."
    (when (frame-live-p company-childframe-child-frame)
      (make-frame-invisible company-childframe-child-frame)))
+ 
  (defun company-childframe-kill ()
    "Kill company-childframe's frame and buffer."
    (when (frame-live-p company-childframe-child-frame)
!     (delete-frame company-childframe--frame)
      (setq company-childframe-child-frame nil)))
+ 
  (defun company-childframe-frontend (command)
    "`company-mode' frontend using a real X tooltip.
  COMMAND: See `company-frontends'."
***************
*** 139,156 ****
      (hide (company-childframe-hide))
      (update (company-childframe--update))
      (post-command (company-childframe--update))))
  (defun company-childframe-enable ()
    "Replace `company-pseudo-tooltip-frontend' with `company-childframe-frontend'."
!   (kill-local-variable 'company-frontends)
!   (setq-local company-frontends
!               (remove 'company-preview-frontend (remove 'company-pseudo-tooltip-frontend
!                                                         (remove 'company-pseudo-tooltip-unless-just-one-frontend
!                                                                 company-frontends))))
!   (add-to-list 'company-frontends 'company-childframe-frontend))
! 
  
! (provide 'company-childframe)
! 
! ;; (require 'company-childframe)
! ;; (company-childframe-enable)
! ;; (setq company-childframe-child-frame nil)
--- 137,154 ----
      (hide (company-childframe-hide))
      (update (company-childframe--update))
      (post-command (company-childframe--update))))
+ 
+ ;;;autoload
  (defun company-childframe-enable ()
    "Replace `company-pseudo-tooltip-frontend' with `company-childframe-frontend'."
!   (interactive)
!   (if (< emacs-major-version 26)
!       (message "company-childframe only run emacs (version >= 26).")
!     (kill-local-variable 'company-frontends)
!     (setq-local company-frontends
!                 (remove 'company-pseudo-tooltip-frontend
!                         (remove 'company-pseudo-tooltip-unless-just-one-frontend
!                                 company-frontends)))
!     (add-to-list 'company-frontends 'company-childframe-frontend)))
  
! (provide 'test-company-childframe)

test-company-childframe.el 是你的新 code

跳来跳去? 有 gif 录像吗? 我看一下