GithubHelp home page GithubHelp logo

posframe's Introduction

Pop a posframe (just a frame) at point

GNU ELPA GNU-devel ELPA MELPA

What is posframe?

Posframe can pop up a frame at point, this posframe is a child-frame connected to its root window’s buffer.

The main advantages are:

  1. It is fast enough for daily usage :-)
  2. It works well with CJK languages.

NOTE:

  1. For MacOS users, posframe needs Emacs version >= 26.0.91
  2. GNOME users with GTK3 builds need Emacs 27 or later. See variable `posframe-gtk-resize-child-frames’ which auto-detects this configuration.

    More details:

    1. Fix some problems with moving and resizing child frames
    2. Emacs’s set-frame-size can not work well with gnome-shell?

./snapshots/posframe-1.png

Installation

(require 'posframe)

Usage

Create a posframe

Simple way

(when (posframe-workable-p)
  (posframe-show " *my-posframe-buffer*"
                 :string "This is a test"
                 :position (point)))

Advanced way

(defvar my-posframe-buffer " *my-posframe-buffer*")

(with-current-buffer (get-buffer-create my-posframe-buffer)
  (erase-buffer)
  (insert "Hello world"))

(when (posframe-workable-p)
  (posframe-show my-posframe-buffer
                 :position (point)))

Arguments

C-h f posframe-show

Hide a posframe

(posframe-hide " *my-posframe-buffer*")

Hide all posframes

M-x posframe-hide-all

Delete a posframe

  1. Delete posframe and its buffer
    (posframe-delete " *my-posframe-buffer*")
        
  2. Only delete the frame
    (posframe-delete-frame " *my-posframe-buffer*")
        

Delete all posframes

M-x posframe-delete-all

Note: this command will delete all posframe buffers. You probably shouldn’t use it if you are sharing a buffer between posframe and other packages.

posframe-arghandler

posframe-arghandler feature has been removed from posframe-1.1, user can use advice feature instead.

Mouse banish

Default setting will work well in most case, but for EXWM user, suggest use the below config.

(setq posframe-mouse-banish-function #'posframe-mouse-banish-simple)

posframe's People

Contributors

aaronjensen avatar akirak avatar celeritascelery avatar conao3 avatar declantsien avatar defaultxr avatar dgutov avatar ericdallo avatar hexmode avatar jingqi avatar jjpandari avatar kiennq avatar manateelazycat avatar nofmysfk avatar randomwangran avatar raxod502 avatar stepnem avatar taquangtrung avatar tarsius avatar treymerkley avatar tsuu32 avatar tttuuu888 avatar tumashu avatar wuubolin avatar yangsheng6810 avatar yqrashawn avatar yyoncho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

posframe's Issues

posframe-delete doesn't kill the posframe buffer

It seems that passing in a buffer name to posframe-delete doesn't actually kill the posframe buffer, despite what the readme suggests. I think it's because buffer-live-p (used in posframe--kill-buffer) expects a buffer object and not a string.

Environment: Emacs 26.2 on Manjaro Linux

Reproduction steps:

  • Evaluate the following with emacs -Q:
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(package-initialize)

(unless (package-installed-p 'posframe)
  (package-refresh-contents)
  (package-install 'posframe))

(require 'posframe)

;; the below is copied from the readme

(when (posframe-workable-p)
  (posframe-show " *my-posframe-buffer*"
                 :string "This is a test"
                 :position (point)))

(posframe-delete " *my-posframe-buffer*")
  • Evaluate (get-buffer " *my-posframe-buffer*"). It returns non-nil.

Custom poshandlers

This is potentially a mix of an issue and a feature request. When trying to define my own poshandler with the result of an expression, the predicate fixnump is violated when the posframe position is set.

For example the following test poshandler

(defun temp-poshandler (_info)
    '(-15 . (+ 15 (* 90 2))))

gives this error when applied to a posframe

posframe--set-frame-position: Wrong type argument: fixnump, (+ 15 (* 90 2))

Ideally, there'd be a builtin poshandler that takes an absolute x and y value within the frame and displayed a posframe at that location (and also wouldn't have strange fixnump violations for the results of integer expressions, although as I'm relatively new to Emacs Lisp I may be messing something up on my end).

More builtin poshandlers

I think that posframe-poshandler-frame-top-center should be provided by default. To me this is by far the most useful position (e.g. it's the position that most other editors use by default for C-p).

Honestly, I think it might be better to just provide a helper to construct poshandlers. The parameter list might look something like this:

posframe-generate-poshandler (x y &key align-to x-offest y-offset) ...
;; x: number, 'left, 'center, or 'right
;; y: number, 'top, 'center, or 'bottom
;; align-to: 'window or 'frame
;; x and y offsets: number offset (e.g. useful if I want to have the frame a
;; little below the top of the window)

Width and Height do not work as documented in posframe-show

Hey there,

the commit d75dc15 changed the semantics of the WIDTH and HEIGTH arguments in calls to posframe-show. The docstring of the that function claims:

Posframe's frame size can be set by WIDTH and HEIGHT.
If one of them is nil, posframe's frame size will fit the
buffer. MIN-WIDTH and MIN-HEIGHT can be useful to prevent
posframe becoming too small.

However, the call to fit-frame-to-buffer introduced in the above commit will always fit the frame's size to the displayed buffer with the additional constraint that MIN-WIDTH <= frame-width <= WIDTH (and likewise for the frame's height). That change of behaviour led to this issue in doom emacs Issue.

Is posframe's code right now working as intended and has this issue to be resolved downstream or is this a bug in posframe?

autoload posframe-workable

I think it's better autoload posframe-workable, otherwise have to (require 'posframe to check if posframe is available. That doesn't make sense. BTW, the example doesn't work if not require it.

(defun posframe-workable-p ()

对单行文本的显示可能有问题?

最近在试用 emacs-rime 的时候发现偶尔会出现候选词显示不全的情况,如图:
image

因为换用 popup 方式显示正常,所以猜测可能与 posframe 有关。

在提 issue 讨论的过程中发现特定长度的字符串在 posframe 会有显示不全,如执行如下代码:

(posframe-show "*posframe-test"
               :string "ni ni ni ni ni| 1. 你妮好好妮好妮 2. 妮妮 3. 呢呢 4. 嶷嶷 5. 你  ")

最后的“你”不显示,如图:
image

此时在字符串中增加或删除一个字就都能全部显示,如删掉一个字:
image

此时继续删字,删除到某个数量时又会出现显示不全:
image

此例共删除5个字后重现显示不全的情况,但是并没有找到规律,只是一个一个的尝试发现的。
不知是哪里的问题造成的。是调用的方式不对还是 posframe 在文本宽度计算上有问题?

又或者是我环境的问题?(有其他坛友也出现显示异常,但是表现形式和我的不一样,他的是把最后的空格给吃掉了)

我在 TG 群中请别的同学帮忙测试,有几位同学测试过后出现同样情况:
image

2020-03-16 12 00 14

2020-03-16 12 01 24

不知其他人是否可以重现类似问题,方便的同学可以多试试不同长度的字符串是否会出现此问题。

Why disable `after-make-frame-functions`?

posframe--create-posframe explicitly binds after-make-frame-functions to nil. This currently breaks persp-mode (perspective-el), which uses frame parameters extensively. These parameters are initialized in a hook it adds to after-make-frame-functions, but are always missing from posframe frames.

It would be a fairly large change to persp-mode to become more resilient to missing parameters, and I haven't run into problems with anything other than posframe. Is there a reason why posframe needs to avoid running frame creation hooks?

去掉本地变量

您指定的编码为utf-8-unix,clone到Windows上默认是crlf行尾,这样会造成clone的文件在emacs中不能正确打开:

image

如果只是编辑还好说,问题是用quelpa安装的包如果以posframe作为依赖,就会导致安装失败。

我觉得编码不如交由git自动管理。用户只要开启了autocrlf(默认开启),在Window和linux平台编辑commit都不会有什么问题。您怎么看?如果可以的话,我就提交一个PR把这个本地变量删除了。

@tumashu

`internal-border-color` doesn't show immediately.

The setting "internal-border-color" doesn't show when a posframe shows first time.
But it changes if I focus on the any other window and back.
After that, all posframes with the same name are displayed normally

Just like this:

Peek 2020-09-04 15-24

OS:Arch linux
wm:i3
Emacs Version:27.1

Terminal support?

Is it possible to have posframe support in the TTY? If not, what is missing to allow it to work?

In the GUI, I like ivy-posframe, and would love to have this working in TTY also. There are an increasing number of packages building on posframe, so if posframe supported TTY they could all benefit.

usage with exwm

  1. Currently, posframe displays under xorg windows.
  2. I see window blinking when posframe shown

Isearch in posframe

Hi,

Would it be possible to start an isearch session for text displayed in a posframe? In addtion to that I can not figure out how to select a posframe at all (interactively). Thank you for this nice library!

Ignore tab bar by default

Similar to #61, same behavior should be applied to tab-bar.

For now, when tab bar enabled, it looks like:
2020-10-23 19-44-29屏幕截图

To reproduce:

  • run emacs -Q and then eval these code:
(tab-bar-mode t)

(add-to-list 'load-path "~/.emacs.d/package/elpa/posframe-20201009.946")

(require 'posframe)
(when (posframe-workable-p)
  (posframe-show " *my-posframe-buffer*"
                :string "This is a test"
                :position (point)))

poshandler that avoids parent window cursor position

It would be useful to know which line the cursor is on in the paren window. One can then write a poshandler that adjusts the position of the posframe so that the active line isn't obscured by the posframe, e.g. posframe-poshandler-window-center-avoid-current-line.

Allow custom setup in childframe buffer

For example, it should be possible to customize display-line-numbers and other variables in the buffer that is created. A new keyword could be added to posframe-show to pass in a function to run in the buffer to do this; a keyword specifically for settings to change could also be added.

internal-border-color is delayed

border-color delayed, this problem occurred with GUI Emacs.
It will appear when you move the cursor or move the window. in addition to Carbon, it also occurred in the Mac port version.

EmacsVersion: GNU Emacs 26.2 (build 1, x86_64-apple-darwin18.5.0, Carbon Version 158 AppKit 1671.4)

Try this code.

(defun sample-show ()
  (posframe-show "*emacs-mac buffer*"
                 :string "hello"
                 :width  100
                 :height 10
                 :timeout 5
                 :internal-border-width 5
                 :internal-border-color "#ff0000"
                 :foreground-color "#000000"
                 :background-color "#FFFFFF")
  )
(sample-show)

screencast

Wery strange bug with combination of scrolling, treemacs, and emacs-parinfer-mode

Hi, this is really strange, but combination of posframe, treemacs, and parinfer-rust-mode, produces weird behavior. Reverting last commit fixes it.

What exactly happens:

  • I open lisp file with parinfer mode enabled
  • I have treemacs window on the left side of Emacs
  • I scroll upwards
  • Buffer window disappears, and treemacs window is used instead

Here's a recording: bug.zip

Reverting 04b91d5 fixes the issue.


It seems that posframe adds new post command hook, that accidentially runs after scrolling and hides current window instead of posframe one.

posframe/posframe.el

Lines 837 to 852 in 04b91d5

(defun posframe-run-hidehandler ()
"Run posframe hidehandler. this function is used in `post-command-hook'."
(while-no-input
(redisplay)
(dolist (frame (frame-list))
(let ((hidehandler (frame-parameter frame 'posframe-hidehandler))
(buffer (frame-parameter frame 'posframe-buffer))
(parent-buffer (frame-parameter frame 'posframe-parent-buffer)))
(when (and hidehandler
(funcall hidehandler
(list
:posframe-buffer buffer
:posframe-parent-buffer parent-buffer)))
(posframe--make-frame-invisible frame))))))
(add-hook 'post-command-hook #'posframe-run-hidehandler)

Add the option to disable focus redirection

I am creating a package that uses posframe to create child frames which need focus. Setting posframe-mouse-banish to nil and :accept-focus t already works as expected.

However, due to the following line focus can be redirected when emacs is e.g. refocused. Is it possible to disable this hook for certain child frames? I am currently using advice-add with :after for posframe--redirect-posframe-focus to redirect the focus back to the child frame but this is not a neat solution.

[feature request] make posframe use as a buffer displaying function

For display-buffer-alist to manage popup windows rules.
There are some functions like display-buffer-below-selected used to show buffer as bellowing:

(add-to-list 'display-buffer-alist
             '("^\\*Process List\\*" (display-buffer-below-selected)))

I hope posframe can provide similar functions with corresponding arguments to use. This will be another awesome way to show buffer content.

childframe macOS limitation; (black fullscreen, missing border)

When I run emacs in Mac OS style fullscreen app, occupying the whole screen I see a second black screen. My steps to reproduce.

Run emacs with a temp home dir;
HOME=/tmp/tmp-home emacs tmp.el

M-x package-install RET posframe RET

contents of tmp.el

(require 'posframe)
(defvar my-posframe-buffer " *my-posframe-buffer*")

(with-current-buffer (get-buffer-create my-posframe-buffer)
  (erase-buffer)
  (insert "Hello world"))

(when (posframe-workable-p)
  (posframe-show my-posframe-buffer
                 :position (point)))

M-x eval-buffer

Whenever this is evaluated the first time a new 'posframe' black fullscreen window appears with a flicker and becomes window in focus. I have to do Alt-Tab to go back to emacs and sometimes that doesn't work either and I am stuck at the black window.

next eval-buffer doesn't behave the same but the black window is always there, I am assuming thats the posframe child-window?

emacs-after-eval-buffer

fullscreen-apps

In this image you can see I have two fullscreen apps, the actual Emacs app and the *Minibuf-1*.

This doesn't happen if emacs is not fullscreen though. Not sure if this is a bug in posframe or Emacs child-window?

Hydra posframe does not initially work with ivy

This is an issue I am encountering with Doom on Emacs 27.1 and have previously reported in the hydra repo hydra/issues/339. To summarize, the hydra posframe (i.e. M-o in ivy) does not work initially. However, if I open a hydra posframe outside of ivy then the hydra posframe works properly with ivy.

One update on this is that I now get the following trace when trying M-o in ivy with hydra-posframe:

Debugger entered--Lisp error: (wrong-type-argument window-live-p #<window 24>)
  set-window-point(#<window 24> 0)
  posframe-show(" *hydra-posframe*" :string #("      | Call         | Cancel | Options | Action w..." 49 50 (face hydra-face-pink) 51 52 (face hydra-face-pink) 53 54 (face hydra-face-pink) 143 144 (face hydra-face-pink) 149 150 (face hydra-face-pink) 159 160 (face hydra-face-blue) 164 165 (face hydra-face-blue) 173 174 (face hydra-face-pink) 190 191 (face hydra-face-pink) 212 213 (face hydra-face-pink) 216 217 (face hydra-face-pink) 220 221 (face hydra-face-blue) 235 236 (face hydra-face-blue) 244 245 (face hydra-face-pink) 261 262 (face hydra-face-pink) 285 286 (face hydra-face-pink) ...) :internal-border-width 1 :internal-border-color "red" :poshandler posframe-poshandler-window-center)
  apply(posframe-show " *hydra-posframe*" :string #("      | Call         | Cancel | Options | Action w..." 49 50 (face hydra-face-pink) 51 52 (face hydra-face-pink) 53 54 (face hydra-face-pink) 143 144 (face hydra-face-pink) 149 150 (face hydra-face-pink) 159 160 (face hydra-face-blue) 164 165 (face hydra-face-blue) 173 174 (face hydra-face-pink) 190 191 (face hydra-face-pink) 212 213 (face hydra-face-pink) 216 217 (face hydra-face-pink) 220 221 (face hydra-face-blue) 235 236 (face hydra-face-blue) 244 245 (face hydra-face-pink) 261 262 (face hydra-face-pink) 285 286 (face hydra-face-pink) ...) (:internal-border-width 1 :internal-border-color "red" :poshandler posframe-poshandler-window-center))
  hydra-posframe-show(#("      | Call         | Cancel | Options | Action w..." 49 50 (face hydra-face-pink) 51 52 (face hydra-face-pink) 53 54 (face hydra-face-pink) 143 144 (face hydra-face-pink) 149 150 (face hydra-face-pink) 159 160 (face hydra-face-blue) 164 165 (face hydra-face-blue) 173 174 (face hydra-face-pink) 190 191 (face hydra-face-pink) 212 213 (face hydra-face-pink) 216 217 (face hydra-face-pink) 220 221 (face hydra-face-blue) 235 236 (face hydra-face-blue) 244 245 (face hydra-face-pink) 261 262 (face hydra-face-pink) 285 286 (face hydra-face-pink) ...))
  hydra-show-hint((format "      | Call         | Cancel | Options | Action %..." #("w" 0 1 (face hydra-face-pink)) #("s" 0 1 (face hydra-face-pink)) #("a" 0 1 (face hydra-face-pink)) (ivy-action-name) #("k" 0 1 (face hydra-face-pink)) #("f" 0 1 (face hydra-face-pink)) #("U" 0 1 (face hydra-face-blue)) #("i" 0 1 (face hydra-face-blue)) #("c" 0 1 (face hydra-face-pink)) (if ivy-calling "on" "off") #("C" 0 1 (face hydra-face-pink)) ivy-case-fold-search #("h" 0 1 (face hydra-face-pink)) #("l" 0 1 (face hydra-face-pink)) #("d" 0 1 (face hydra-face-blue)) #("o" 0 1 (face hydra-face-blue)) #("M" 0 1 (face hydra-face-pink)) (ivy--matcher-desc) #("T" 0 1 (face hydra-face-pink)) truncate-lines #("j" 0 1 (face hydra-face-pink)) #("g" 0 1 (face hydra-face-pink)) #("<" 0 1 (face hydra-face-pink)) #(">" 0 1 (face hydra-face-pink)) #("D" 0 1 (face hydra-face-blue))) hydra-ivy)
  hydra-ivy/body()
  funcall-interactively(hydra-ivy/body)
  call-interactively(hydra-ivy/body nil nil)
  command-execute(hydra-ivy/body)
  read-from-minibuffer("Find file: " nil (keymap (keymap (remap keymap (undo . counsel-find-file-undo)) (96 lambda (&optional arg) "nil (`nil')" (interactive "p") (if (string= "" ivy-text) (execute-kbd-macro (kbd "M-o b")) (self-insert-command arg))) (C-backspace . counsel-up-directory) (67108991 . counsel-up-directory)) keymap (12 . ivy-alt-done) (67108896 . ivy-call-and-recenter) (insert-state keymap "Auxiliary keymap for Insert state" (11 . previous-line) (10 . next-line)) (33554443 . scroll-down-command) (33554442 . scroll-up-command) (11 . previous-line) (26 closure (t) (&rest _) (interactive) (condition-case nil (progn (call-interactively #'undo)) (error nil))) (23 . doom/delete-backward-word) (21 . evil-delete-back-to-indentation) (1 . move-beginning-of-line) (escape . abort-recursive-edit) (19 . counsel-minibuffer-history) (36 . ivy-magic-read-file-env) (3 keymap (5 . +ivy/woccur) (19 . ivy-rotate-sort) (1 . ivy-toggle-ignore) (15 . ivy-occur)) (33554464 . ivy-restrict-to-matches) (15 . ivy-dispatching-done) (22 . yank) (prior . ivy-scroll-down-command) (next . ivy-scroll-up-command) (7 . minibuffer-keyboard-quit) (right . ivy-forward-char) (32 . self-insert-command) (18 . evil-paste-from-register) (remap keymap (doom/delete-backward-word . ivy-backward-kill-word) (describe-mode . ivy-help) (kill-ring-save . ivy-kill-ring-save) (kill-whole-line . ivy-kill-whole-line) (kill-line . ivy-kill-line) (scroll-down-command . ivy-scroll-down-command) (scroll-up-command . ivy-scroll-up-command) (end-of-buffer . ivy-end-of-buffer) (beginning-of-buffer . ivy-beginning-of-buffer) (kill-word . ivy-kill-word) (forward-char . ivy-forward-char) (delete-char . ivy-delete-char) (backward-kill-word . ivy-backward-kill-word) (backward-delete-char-untabify . ivy-backward-delete-char) (delete-backward-char . ivy-backward-delete-char) (previous-line . ivy-previous-line) (next-line . ivy-next-line)) (9 . ivy-partial-or-done) (10 . next-line) (27 keymap (1 . ivy-read-action) (15 . ivy-dispatching-call) (111 . hydra-ivy/body) (25 . ivy-insert-current-full) (105 . ivy-insert-current) (106 . ivy-yank-word) (114 . ivy-toggle-regexp-quote) (97 . ivy-toggle-marks) (16 . ivy-previous-line-and-call) (14 . ivy-next-line-and-call) (118 . ivy-scroll-down-command) (112 . ivy-previous-history-element) (110 . ivy-next-history-element) (10 . ivy-immediate-done) (13 . ivy-call)) (mouse-3 . ivy-mouse-dispatching-done) (mouse-1 . ivy-mouse-done) (down-mouse-1 . ignore) (13 . ivy-done)) nil file-name-history)
  #f(compiled-function (arg1 arg2 &rest rest) "Read a string in the minibuffer, with completion.\n\nPROMPT is a string, normally ending in a colon and a space.\n`ivy-count-format' is prepended to PROMPT during completion.\n\nCOLLECTION is either a list of strings, a function, an alist, or\na hash table, supplied for `minibuffer-completion-table'.\n\nPREDICATE is applied to filter out the COLLECTION immediately.\nThis argument is for compatibility with `completing-read'.\n\nWhen REQUIRE-MATCH is non-nil, only members of COLLECTION can be\nselected.\n\nIf INITIAL-INPUT is non-nil, then insert that input in the\nminibuffer initially.\n\nHISTORY is a name of a variable to hold the completion session\nhistory.\n\nKEYMAP is composed with `ivy-minibuffer-map'.\n\nPRESELECT, when non-nil, determines which one of the candidates\nmatching INITIAL-INPUT to select initially.  An integer stands\nfor the position of the desired candidate in the collection,\ncounting from zero.  Otherwise, use the first occurrence of\nPRESELECT in the collection.  Comparison is first done with\n`equal'.  If that fails, and when applicable, match PRESELECT as\na regular expression.\n\nDEF is for compatibility with `completing-read'.\n\nUPDATE-FN is called each time the candidate list is re-displayed.\n\nWhen SORT is non-nil, `ivy-sort-functions-alist' determines how\nto sort candidates before displaying them.\n\nACTION is a function to call after selecting a candidate.\nIt takes one argument, the selected candidate. If COLLECTION is\nan alist, the argument is a cons cell, otherwise it's a string.\n\nMULTI-ACTION, when non-nil, is called instead of ACTION when\nthere are marked candidates. It takes the list of candidates as\nits only argument. When it's nil, ACTION is called on each marked\ncandidate.\n\nUNWIND is a function of no arguments to call before exiting.\n\nRE-BUILDER is a function transforming input text into a regex\npattern.\n\nMATCHER is a function which can override how candidates are\nfiltered based on user input.  It takes a regex pattern and a\nlist of candidates, and returns the list of matching candidates.\n\nDYNAMIC-COLLECTION is a boolean specifying whether the list of\ncandidates is updated after each input by calling COLLECTION.\n\nEXTRA-PROPS is a plist that can be used to store\ncollection-specific session-specific data.\n\nCALLER is a symbol to uniquely identify the caller to `ivy-read'.\nIt is used, along with COLLECTION, to determine which\ncustomizations apply to the current completion session." #<bytecode 0x158418985969>)("Find file: " read-file-name-internal :matcher counsel--find-file-matcher :initial-input nil :action counsel-find-file-action :preselect nil :require-match confirm-after-completion :history file-name-history :keymap (keymap (remap keymap (undo . counsel-find-file-undo)) (96 lambda (&optional arg) "nil (`nil')" (interactive "p") (if (string= "" ivy-text) (execute-kbd-macro (kbd "M-o b")) (self-insert-command arg))) (C-backspace . counsel-up-directory) (67108991 . counsel-up-directory)) :caller counsel-find-file)
  apply(#f(compiled-function (arg1 arg2 &rest rest) "Read a string in the minibuffer, with completion.\n\nPROMPT is a string, normally ending in a colon and a space.\n`ivy-count-format' is prepended to PROMPT during completion.\n\nCOLLECTION is either a list of strings, a function, an alist, or\na hash table, supplied for `minibuffer-completion-table'.\n\nPREDICATE is applied to filter out the COLLECTION immediately.\nThis argument is for compatibility with `completing-read'.\n\nWhen REQUIRE-MATCH is non-nil, only members of COLLECTION can be\nselected.\n\nIf INITIAL-INPUT is non-nil, then insert that input in the\nminibuffer initially.\n\nHISTORY is a name of a variable to hold the completion session\nhistory.\n\nKEYMAP is composed with `ivy-minibuffer-map'.\n\nPRESELECT, when non-nil, determines which one of the candidates\nmatching INITIAL-INPUT to select initially.  An integer stands\nfor the position of the desired candidate in the collection,\ncounting from zero.  Otherwise, use the first occurrence of\nPRESELECT in the collection.  Comparison is first done with\n`equal'.  If that fails, and when applicable, match PRESELECT as\na regular expression.\n\nDEF is for compatibility with `completing-read'.\n\nUPDATE-FN is called each time the candidate list is re-displayed.\n\nWhen SORT is non-nil, `ivy-sort-functions-alist' determines how\nto sort candidates before displaying them.\n\nACTION is a function to call after selecting a candidate.\nIt takes one argument, the selected candidate. If COLLECTION is\nan alist, the argument is a cons cell, otherwise it's a string.\n\nMULTI-ACTION, when non-nil, is called instead of ACTION when\nthere are marked candidates. It takes the list of candidates as\nits only argument. When it's nil, ACTION is called on each marked\ncandidate.\n\nUNWIND is a function of no arguments to call before exiting.\n\nRE-BUILDER is a function transforming input text into a regex\npattern.\n\nMATCHER is a function which can override how candidates are\nfiltered based on user input.  It takes a regex pattern and a\nlist of candidates, and returns the list of matching candidates.\n\nDYNAMIC-COLLECTION is a boolean specifying whether the list of\ncandidates is updated after each input by calling COLLECTION.\n\nEXTRA-PROPS is a plist that can be used to store\ncollection-specific session-specific data.\n\nCALLER is a symbol to uniquely identify the caller to `ivy-read'.\nIt is used, along with COLLECTION, to determine which\ncustomizations apply to the current completion session." #<bytecode 0x158418985969>) ("Find file: " read-file-name-internal :matcher counsel--find-file-matcher :initial-input nil :action counsel-find-file-action :preselect nil :require-match confirm-after-completion :history file-name-history :keymap (keymap (remap keymap (undo . counsel-find-file-undo)) (96 lambda (&optional arg) "nil (`nil')" (interactive "p") (if (string= "" ivy-text) (execute-kbd-macro (kbd "M-o b")) (self-insert-command arg))) (C-backspace . counsel-up-directory) (67108991 . counsel-up-directory)) :caller counsel-find-file))
  ivy-posframe--read(#f(compiled-function (arg1 arg2 &rest rest) "Read a string in the minibuffer, with completion.\n\nPROMPT is a string, normally ending in a colon and a space.\n`ivy-count-format' is prepended to PROMPT during completion.\n\nCOLLECTION is either a list of strings, a function, an alist, or\na hash table, supplied for `minibuffer-completion-table'.\n\nPREDICATE is applied to filter out the COLLECTION immediately.\nThis argument is for compatibility with `completing-read'.\n\nWhen REQUIRE-MATCH is non-nil, only members of COLLECTION can be\nselected.\n\nIf INITIAL-INPUT is non-nil, then insert that input in the\nminibuffer initially.\n\nHISTORY is a name of a variable to hold the completion session\nhistory.\n\nKEYMAP is composed with `ivy-minibuffer-map'.\n\nPRESELECT, when non-nil, determines which one of the candidates\nmatching INITIAL-INPUT to select initially.  An integer stands\nfor the position of the desired candidate in the collection,\ncounting from zero.  Otherwise, use the first occurrence of\nPRESELECT in the collection.  Comparison is first done with\n`equal'.  If that fails, and when applicable, match PRESELECT as\na regular expression.\n\nDEF is for compatibility with `completing-read'.\n\nUPDATE-FN is called each time the candidate list is re-displayed.\n\nWhen SORT is non-nil, `ivy-sort-functions-alist' determines how\nto sort candidates before displaying them.\n\nACTION is a function to call after selecting a candidate.\nIt takes one argument, the selected candidate. If COLLECTION is\nan alist, the argument is a cons cell, otherwise it's a string.\n\nMULTI-ACTION, when non-nil, is called instead of ACTION when\nthere are marked candidates. It takes the list of candidates as\nits only argument. When it's nil, ACTION is called on each marked\ncandidate.\n\nUNWIND is a function of no arguments to call before exiting.\n\nRE-BUILDER is a function transforming input text into a regex\npattern.\n\nMATCHER is a function which can override how candidates are\nfiltered based on user input.  It takes a regex pattern and a\nlist of candidates, and returns the list of matching candidates.\n\nDYNAMIC-COLLECTION is a boolean specifying whether the list of\ncandidates is updated after each input by calling COLLECTION.\n\nEXTRA-PROPS is a plist that can be used to store\ncollection-specific session-specific data.\n\nCALLER is a symbol to uniquely identify the caller to `ivy-read'.\nIt is used, along with COLLECTION, to determine which\ncustomizations apply to the current completion session." #<bytecode 0x158418985969>) "Find file: " read-file-name-internal :matcher counsel--find-file-matcher :initial-input nil :action counsel-find-file-action :preselect nil :require-match confirm-after-completion :history file-name-history :keymap (keymap (remap keymap (undo . counsel-find-file-undo)) (96 lambda (&optional arg) "nil (`nil')" (interactive "p") (if (string= "" ivy-text) (execute-kbd-macro (kbd "M-o b")) (self-insert-command arg))) (C-backspace . counsel-up-directory) (67108991 . counsel-up-directory)) :caller counsel-find-file)
  apply(ivy-posframe--read #f(compiled-function (arg1 arg2 &rest rest) "Read a string in the minibuffer, with completion.\n\nPROMPT is a string, normally ending in a colon and a space.\n`ivy-count-format' is prepended to PROMPT during completion.\n\nCOLLECTION is either a list of strings, a function, an alist, or\na hash table, supplied for `minibuffer-completion-table'.\n\nPREDICATE is applied to filter out the COLLECTION immediately.\nThis argument is for compatibility with `completing-read'.\n\nWhen REQUIRE-MATCH is non-nil, only members of COLLECTION can be\nselected.\n\nIf INITIAL-INPUT is non-nil, then insert that input in the\nminibuffer initially.\n\nHISTORY is a name of a variable to hold the completion session\nhistory.\n\nKEYMAP is composed with `ivy-minibuffer-map'.\n\nPRESELECT, when non-nil, determines which one of the candidates\nmatching INITIAL-INPUT to select initially.  An integer stands\nfor the position of the desired candidate in the collection,\ncounting from zero.  Otherwise, use the first occurrence of\nPRESELECT in the collection.  Comparison is first done with\n`equal'.  If that fails, and when applicable, match PRESELECT as\na regular expression.\n\nDEF is for compatibility with `completing-read'.\n\nUPDATE-FN is called each time the candidate list is re-displayed.\n\nWhen SORT is non-nil, `ivy-sort-functions-alist' determines how\nto sort candidates before displaying them.\n\nACTION is a function to call after selecting a candidate.\nIt takes one argument, the selected candidate. If COLLECTION is\nan alist, the argument is a cons cell, otherwise it's a string.\n\nMULTI-ACTION, when non-nil, is called instead of ACTION when\nthere are marked candidates. It takes the list of candidates as\nits only argument. When it's nil, ACTION is called on each marked\ncandidate.\n\nUNWIND is a function of no arguments to call before exiting.\n\nRE-BUILDER is a function transforming input text into a regex\npattern.\n\nMATCHER is a function which can override how candidates are\nfiltered based on user input.  It takes a regex pattern and a\nlist of candidates, and returns the list of matching candidates.\n\nDYNAMIC-COLLECTION is a boolean specifying whether the list of\ncandidates is updated after each input by calling COLLECTION.\n\nEXTRA-PROPS is a plist that can be used to store\ncollection-specific session-specific data.\n\nCALLER is a symbol to uniquely identify the caller to `ivy-read'.\nIt is used, along with COLLECTION, to determine which\ncustomizations apply to the current completion session." #<bytecode 0x158418985969>) ("Find file: " read-file-name-internal :matcher counsel--find-file-matcher :initial-input nil :action counsel-find-file-action :preselect nil :require-match confirm-after-completion :history file-name-history :keymap (keymap (remap keymap (undo . counsel-find-file-undo)) (96 lambda (&optional arg) "nil (`nil')" (interactive "p") (if (string= "" ivy-text) (execute-kbd-macro (kbd "M-o b")) (self-insert-command arg))) (C-backspace . counsel-up-directory) (67108991 . counsel-up-directory)) :caller counsel-find-file))
  ivy-read("Find file: " read-file-name-internal :matcher counsel--find-file-matcher :initial-input nil :action counsel-find-file-action :preselect nil :require-match confirm-after-completion :history file-name-history :keymap (keymap (remap keymap (undo . counsel-find-file-undo)) (96 lambda (&optional arg) "nil (`nil')" (interactive "p") (if (string= "" ivy-text) (execute-kbd-macro (kbd "M-o b")) (self-insert-command arg))) (C-backspace . counsel-up-directory) (67108991 . counsel-up-directory)) :caller counsel-find-file)
  counsel--find-file-1("Find file: " nil counsel-find-file-action counsel-find-file)
  counsel-find-file()
  funcall-interactively(counsel-find-file)
  call-interactively(counsel-find-file nil nil)
  command-execute(counsel-find-file)

Position for font-height invalid

Problem:

Switching window configs while a posframe is open can result in posframe-show looking to set font-height using a position that is no longer valid (if the buffer sizes of these two windows are different).

One way replicate:

  1. Enable eyebrowse.
  2. Switch to window config number 1.
  3. In this window config, open up a file with, say, 500 characters.
  4. Switch to window config number 2.
  5. In this window config, open up a file with less than 500 characters.
  6. Switch to window config number 1.
  7. Move point to end of buffer.
  8. While posframe is open (e.g. a hydra-posframe that allows for eyebrowse switching), switch to window config 2.

Result:

posframe-show will be using the point value from the window of workspace 1 (position = 500), but then attempt to set font-height using the window of workspace 2 at this same position, which is invalid (since this buffer is smaller than 500).

Error message will look like :

Debugger entered--Lisp error: (args-out-of-range 52756 1 40057)
  font-at(52756)
  (progn (font-at (if (and (= position (point-max))) (- position 1) position)))
  (if (and (integerp position) (not (= position 1))) (progn (font-at (if (and (= position (point-max))) (- position 1) position))))
  (let* ((font (if (and (integerp position) (not (= position 1))) (progn (font-at (if (and ...) (- position 1) position))))) (height (if (integerp position) (progn (if (or (= position 1) (not ...)) (default-line-height) (aref (font-info font) 3)))))) (setq posframe--last-font-height-info (cons position height)) height)
  (if (eq position (car posframe--last-font-height-info)) (cdr posframe--last-font-height-info) (let* ((font (if (and (integerp position) (not (= position 1))) (progn (font-at (if ... ... position))))) (height (if (integerp position) (progn (if (or ... ...) (default-line-height) (aref ... 3)))))) (setq posframe--last-font-height-info (cons position height)) height))
  posframe--get-font-height(52756)

Possible solution:

In posframe-show, change font-height so that it is set via:

(font-height (with-current-buffer (window-buffer parent-window)
                        (posframe--get-font-height (point))))

This seems to work but I don't know much about posframe and whether is this the appropriate solution.

Version:

This is as of version 20191108.745

Misc:

If you need a hydra-posframe to test (this is using pretty-hydra), you can use this to switch between window configs while keeping a posframe open (call hydra-workspaces/body to activate):

(pretty-hydra-define hydra-workspaces
  (:foreign-keys warn
   :title "Workspaces"
   :separator " "
   :quit-key "q")
  ("Navigate"
   (("r" eyebrowse-rename-window-config "rename" :exit t :column "Edit")
    ("c" eyebrowse-close-window-config "close")
    ("[" (eyebrowse-prev-window-config 1) "prev" :column "Navigation")
    ("]" (eyebrowse-next-window-config 1) "next"))
   "Jump"
   (("1" (eyebrowse-switch-to-window-config-1) "ws 1" :column "Quick Access")
    ("2" (eyebrowse-switch-to-window-config-2) "ws 2")
    ("3" (eyebrowse-switch-to-window-config-3) "ws 3")
    ("4" (eyebrowse-switch-to-window-config-4) "ws 4")
    ("5" (eyebrowse-switch-to-window-config-5) "ws 5")
    ("6" (eyebrowse-switch-to-window-config-6) "ws 6")
    ("7" (eyebrowse-switch-to-window-config-7) "ws 7")
    ("8" (eyebrowse-switch-to-window-config-8) "ws 8")
    ("9" (eyebrowse-switch-to-window-config-9) "ws 9"))))

Ignore tab line by default

By default, posframe will display no header-line or mode-line. In case a header-line or mode-line is desired, users can set RESPECT-HEADER-LINE or RESPECT-MODE-LINE to t.

I think the same behavior should be applied to tab-line, because if global-tab-line-mode is set, the posframe also has tab-line, which is meaningless in most cases, I guess. RESPECT-TAB-LINE would be good to have.

Posframes are being selected again as of Emacs 27.1

After I submitted #54 it seemed like posframe was no longer grabbing keyboard focus under window managers that try to select posframes. However, as of Emacs 27.1, it appears the issue has returned.

Trivial reproduction case with company-posframe:

  • Window manager with focus-follows-mouse enabled.

  • Emacs 27.1, started with emacs -Q.

  • Evaluate the following:

(require 'package)
(package-initialize)
(require 'company)
(require 'posframe)
(require 'company-posframe)
(setq posframe-mouse-banish nil)
(global-company-mode 1)
(company-posframe-mode t)
  • Then, put your mouse just under your cursor and type (fra.

  • Once the company posframe appears, type more and you should see that the posframe is erroneously getting keyboard events.

This reproduction case does not have the same effect in Emacs 26.3; everything still works as expected there.

From what I can tell, it looks like focus-in-hook is simply not firing when the window manager focuses the posframe. Perhaps this is an Emacs bug?

I tried a few workarounds, including moving

(unless accept-focus
  (redirect-frame-focus posframe--frame (frame-parent posframe--frame)))

into posframe--create-posframe, under these lines:

(unless respect-tab-line
  (set-window-parameter posframe-window 'tab-line-format 'none))

...But it didn't seem to fix the issue.

Additionally I saw that focus-in-hook is deprecated and it's recommended to use after-focus-change-function via add-function instead. Unfortunately, swapping out (add-hook 'focus-in-hook 'posframe--redirect-posframe-focus) for (add-function :after after-focus-change-function 'posframe--redirect-posframe-focus) didn't seem to make a difference either.

I don't have any solution for this. To me it seems like an Emacs bug introduced in 27.1, however I'm not sure, and I wanted to open an issue here first, in case anyone who might have a better understanding of how Emacs' frame handling works would be able to assist.

Frame not tall enough if line-spacing > 0

When the default line-spacing is not 0, the posframe is not tall enough to fit the full height of the buffer. The reason is that the line-spacing was ignored when calculating the pixel-exact height.

For example, with a default char-height of 12, 6 lines to display yield a frame that's 72 pixels high, but if line-spacing is, say, 1, 6 full lines need 6 * (12+1) = 78 pixels, and the last line is cut off.

posframe--set-frame-size uses two different code paths to set the posframe's size. The fit-frame-to-buffer call has been fixed on Emacs' master, see Emacs bug#37563 and commit e3f97d73653df725322d7f2392d36f858cce5a73.

BUT there is another path calling the C function set-frame-size directly, and that also ignores the line-spacing. I think this call was introduced in posframe as an optimization to avoid the lenghty calculations on the lisp side.

I just confirmed on emacs-devel that set-frame-size behaves as it should:
https://lists.gnu.org/archive/html/emacs-devel/2019-10/msg00482.html

That means that posframe must not call set-frame-size directly, or it must calculate the pixel size itself and use the optional PIXELWISE argument. To do this correctly, it will need to duplicate the work that fit-frame-to-buffer does, anyway.

So the fix is to simply replace calls to posframe--set-frame-size by fit-frame-to-buffer (same parameters), and the var posframe--last-posframe-size can be removed.

As for issue #44, there is no answer yet to know if it will be affected.

fail to initialize Org-mode in posframe

Dear the maintainers of posframe:

Thank for writing this package, I use ivy-posframe everyday and
enjoy using it.

I am writing this issue because that I try to insert a standard
Org-mode link into posframe. I've searched the issue but could not
find anything related to it.

Following is a simple example.

(setq my-posframe-buffer " *my-posframe-buffer*")

(with-current-buffer (get-buffer-create my-posframe-buffer)
 (erase-buffer)
 (insert "* [[Org-mode link]]")
 (org-mode))

(when (posframe-workable-p)
 (posframe-show my-posframe-buffer
                :position (point)))

What I want to do is to insert a standard Org-mode link in posframe,
but it only shows the plain text on my side.

I was wondering that if this is achievable in posframe?

Thank you.

Please use unix style line ending

I'm installing posframe in background with emacs-async, an error raises:

Failed to install `posframe':
	posframe.el:0:0: error: error: (Local variables entry is missing the suffix)

I guess the line end style (windows CRLF in posframe.el) cause this problem, and Emacs got an unexpected character '\r' at the end of the first line.
Please change to Unix line end style to fix this.

Possible to add more advanced usage examples to README?

I've been trying to modify org-insert-structure-template, currently bound to C-c C-, in recent Org versions, to use a posframe instead of using another window with org-switch-to-buffer-other-window.
The function I wanted to adapt, specifically, is org-mks, defined in org-macs.el.
Despite attempts to get posframe working, I couldn't get it to show up, perhaps because of weird interactions with save-window-excursion and with-current-buffer, etc.

I was wondering whether it'd be possible to show more advanced examples in the README.md to help new users figure out how to use posframe as a drop-in replacement for creating new windows.
Alternatively, is there any other documentation or tutorials out there?

Thanks for the project

[Feature Request] allow reusing frames in more cases.

ATM the frame is reused if the last displayed frame has been created with the same set of parameters. This is very limiting for the cases when there are multiple extensions using posframe(e. g. helm-posframe, company-posframe) the frames are recreated too often and this results in poor behavior.

Proposed fix:

Introduce a flag - keep-frame. posframe will handle that flag by storing the frame in a lookup by buffer-id.

support scrolling (and other keyboard interaction) in posframe

As for now, one cannot interact with posframe with keystrokes. For example, I cannot scroll down (using keyboard) to see long content.

The workaround I use right now is to use with-selected-frame to define commands that run inside the posframe. Bind these posframe-specific commands in a separate keymaps. At the end of the posframe-show call set-transient-map to apply the bindings when the posframe appears.

I was wondering if there is any plan for posframe to provide this functionality in the future?

exception in posframe

When I was executing these in terminal on macOS with GNU Emacs 26.1, I got the execpetion below.
No such issue on GUI mode.

(defun my/youdao-dictionary-result-show (string)
  (if (fboundp 'posframe-show)
      (let ((buffer " *my/youdao-dict-query-postframe-buffer*"))
        (posframe-show
         buffer
         :string string
         :position (point)
         :left-fringe 8
         :right-fringe 8)
        (with-current-buffer buffer
          (abbrev-mode))
        (unwind-protect
            (push (read-event) unread-command-events)
          (posframe-hide buffer)))
    (youdao-dictionary--pos-tip string)))
(defun youdao-dictinary-search-at-point-posframe ()
  "Search word at point and display result with pos-tip."
  (interactive)
  (let ((word (youdao-dictionary--region-or-word)))
    (if word
        (my/youdao-dictionary-result-show (youdao-dictionary--format-result word))
      (message "Nothing to look up"))))
Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  font-info(nil)
  (aref (font-info (font-at (if (and (= position (point-max))) (- position 1) position))) 3)
  (if (= position 1) (default-line-height) (aref (font-info (font-at (if (and (= position (point-max))) (- positi$
  (progn (if (= position 1) (default-line-height) (aref (font-info (font-at (if (and (= position (point-max))) (-$
  (if (integerp position) (progn (if (= position 1) (default-line-height) (aref (font-info (font-at (if (and (= p$
  (let ((height (if (integerp position) (progn (if (= position 1) (default-line-height) (aref (font-info (font-at$
  (if (eq position (car posframe--last-font-height-info)) (cdr posframe--last-font-height-info) (let ((height (if$
  posframe--get-font-height(3925)
  (let* ((position (or position (point))) (posframe-buffer (get-buffer-create posframe-buffer)) (x-pixel-offset ($
  (progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) '(:string :position :$
  (let* ((string (car (cdr (plist-member --cl-rest-- ':string)))) (position (car (cdr (plist-member --cl-rest-- '$
  posframe-show(" *my/youdao-dict-query-postframe-buffer*" :string "youdao [nil]\n\n* Basic Explains\n- n. 有道($
  (let ((buffer " *my/youdao-dict-query-postframe-buffer*")) (posframe-show buffer :string string :position (poin$
  (if (fboundp 'posframe-show) (let ((buffer " *my/youdao-dict-query-postframe-buffer*")) (posframe-show buffer :$
  my/youdao-dictionary-result-show("youdao [nil]\n\n* Basic Explains\n- n. 有道(网易公司的搜索服务)\n\n* Web Re$
  (if word (my/youdao-dictionary-result-show (youdao-dictionary--format-result word)) (message "Nothing to look u$
  (let ((word (youdao-dictionary--region-or-word))) (if word (my/youdao-dictionary-result-show (youdao-dictionary$
  youdao-dictinary-search-at-point-posframe()

Posframe isn't working in the terminal

Issue: posframe does not work when emacs is running in the terminal. But, works fine when running in as GUI.

I almost always use emacs in the terminal. Packages like company seem to be able to create child frames in the terminal. It would be nice if posframe could do this.

Posframe is slow if emacs is built using athena/lucid toolkit

Emacs stuck for ~half second every time posframe-show is called if emacs is built with athena toolkit. However, with gtk toolkit this is not such lag.

OS: gentoo, emacs is built with flag athena which, I think, is equivilant to emacs built with --with-x-toolkit=athena.

Just thought it would be nice if it is mentioned somewhere in the readme.

posn-at-point is slow and called often

I noticed some typing lag and traced some of down to posframe calling posn-at-point. On my machine (macOS, emacs 27), each call can take 6-8ms and it is called at least twice with each keypress when using company-childframe. With fast typing it's called often and it can contribute to lag.

I experimented with naively memoizing it and it helped:

(defvar posframe-previous-position nil)
(defvar posframe-previous-window nil)
(defun posn-at-point-memo (position window)
  (if (and (eq position posframe-previous-position)
           (eq window posframe-previous-window))
      posframe-previous-posn
    (setq posframe-previous-position position
          posframe-previous-window window
          posframe-previous-posn (posn-at-point position window))))

I'm sure there's a cleaner way to write that, but you get the idea 😄

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.