Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 54 additions & 18 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,61 @@

Be sure your Emacs version is 29.1 and above (built with tree-sitter support), and install the tree-sitter parsers you need.

* Positioning and Appearance
The context frame can be positioned at different locations within the current window and customized with offsets for fine-tuning.

** Position Options
- ='top-right= (default): Top-right corner of the window
- ='top-left=: Top-left corner of the window
- ='bottom-right=: Bottom-right corner of the window
- ='bottom-left=: Bottom-left corner of the window
- Custom function: You can provide your own positioning function

** Examples
#+BEGIN_SRC elisp
;; Position at top-left with 20px padding from edges
(setq treesitter-context-frame-position 'top-left
treesitter-context-frame-offset-x 20
treesitter-context-frame-offset-y 20)

;; Customize appearance
(setq treesitter-context-background-color "#2d3748"
treesitter-context-border-color "#4a5568"
treesitter-context-border-width 2
treesitter-context-frame-padding 3)

;; Custom positioning function
(setq treesitter-context-frame-position
(lambda (info)
;; Position 100px from left, 50px from top of window
(cons 100 50)))
#+END_SRC

* Customization
| Variable | Default | Description |
|-------------------------------------------------+-----------+---------------------------------------------------------------------------------------------|
| treesitter-context-idle-time | 2.0 | How many seconds to wait before refreshing context information |
| treesitter-context-show-context-always | t | Show context all the time if t, if nil only show context when outmost parent is invisible |
| treesitter-context-show-line-number | t | Show line number in the child frame |
| treesitter-context-frame-autohide-timeout | 15 | Child frame will hide itself after this many seconds |
| treesitter-context-frame-indent-offset | 4 | Indent offset in the child frame |
| treesitter-context-frame-min-width | 60 | Minimal width of the child frame |
| treesitter-context-frame-min-height | 5 | Minimal height of the child frame |
| treesitter-context-frame-font | nil | Font of the child frame |
| treesitter-context-java-show-modifiers | nil | If t, show modifiers of the classes/methods |
| treesitter-context-background-color | "#000000" | Background color of the context frame |
| treesitter-context-border-color | "#FFFFFF" | Context frame border color |
| treesitter-context-border-width | 1 | Context frame border width |
| treesitter-context-fold-ellipsis-content | "..." | Text to show in place of a folded block. |
| treesitter-context-fold-show-fringe-marks | t | Whether to show fold markers in the fringe or not. |
| treesitter-context-fold-unfold-when-fold-region | nil | When folding a region, whether unfold old foldings in this region or not. |
| treesitter-context-frame-font-fraction | nil | Fraction of font height in the child frame. Prefer this to `treesitter-context-frame-font'. |
| Variable | Default | Description |
|-------------------------------------------------+------------+---------------------------------------------------------------------------------------------|
| treesitter-context-idle-time | 2.0 | How many seconds to wait before refreshing context information |
| treesitter-context-show-context-always | t | Show context all the time if t, if nil only show context when outmost parent is invisible |
| treesitter-context-show-line-number | t | Show line number in the child frame |
| treesitter-context-frame-autohide-timeout | 15 | Child frame will hide itself after this many seconds |
| treesitter-context-frame-indent-offset | 4 | Indent offset in the child frame |
| treesitter-context-frame-min-width | 60 | Minimal width of the child frame |
| treesitter-context-frame-min-height | 5 | Minimal height of the child frame |
| treesitter-context-frame-font | nil | Font of the child frame |
| treesitter-context-java-show-modifiers | nil | If t, show modifiers of the classes/methods |
| treesitter-context-background-color | "#000000" | Background color of the context frame |
| treesitter-context-border-color | "#FFFFFF" | Context frame border color |
| treesitter-context-border-width | 1 | Context frame border width |
| treesitter-context-fold-ellipsis-content | "..." | Text to show in place of a folded block. |
| treesitter-context-fold-show-fringe-marks | t | Whether to show fold markers in the fringe or not. |
| treesitter-context-fold-unfold-when-fold-region | nil | When folding a region, whether unfold old foldings in this region or not. |
| treesitter-context-frame-font-fraction | nil | Fraction of font height in the child frame. Prefer this to `treesitter-context-frame-font'. |
| treesitter-context-frame-position | 'top-right | Position of the context frame (top-right, top-left, bottom-right, bottom-left) |
| treesitter-context-frame-max-width | nil | Maximum width of the context frame. If nil, use window width |
| treesitter-context-frame-max-height | nil | Maximum height of the context frame. If nil, no limit |
| treesitter-context-frame-padding | 2 | Padding between line numbers and content |
| treesitter-context-frame-offset-x | 0 | Horizontal offset from the position anchor point in pixels |
| treesitter-context-frame-offset-y | 0 | Vertical offset from the position anchor point in pixels |

* Commands
** treesitter-context-fold-hide
Expand Down
125 changes: 105 additions & 20 deletions treesitter-context.el
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,74 @@ If nil, show context only when the outmost parent is invisible."
:safe 'floatp
:group 'treesitter-context)

(defcustom treesitter-context-frame-position 'top-right
"Position of the context frame.
Can be window-relative positions or a custom poshandler function."
:version "29.1"
:type '(choice (const :tag "Window Top Right" top-right)
(const :tag "Window Top Left" top-left)
(const :tag "Window Bottom Right" bottom-right)
(const :tag "Window Bottom Left" bottom-left)
(function :tag "Custom poshandler function"))
:group 'treesitter-context)

(defcustom treesitter-context-frame-max-width nil
"Maximum width of the context frame. If nil, use window width."
:version "29.1"
:type '(choice (const :tag "No limit" nil)
(integer :tag "Max width"))
:group 'treesitter-context)

(defcustom treesitter-context-frame-max-height nil
"Maximum height of the context frame. If nil, no limit."
:version "29.1"
:type '(choice (const :tag "No limit" nil)
(integer :tag "Max height"))
:group 'treesitter-context)

(defcustom treesitter-context-frame-padding 2
"Padding between line numbers and content."
:version "29.1"
:type 'integer
:safe 'integerp
:group 'treesitter-context)

(defcustom treesitter-context-frame-offset-x 0
"Horizontal offset from the position anchor point in pixels."
:version "29.1"
:type 'integer
:group 'treesitter-context)

(defcustom treesitter-context-frame-offset-y 0
"Vertical offset from the position anchor point in pixels."
:version "29.1"
:type 'integer
:group 'treesitter-context)

(defvar treesitter-context--buffer-name "*treesitter-context*"
"Name of buffer used to show context.")

(defvar treesitter-context--indent-level 0
(defcustom treesitter-context--indent-level 0
"Indent level used to generate context information.")

(defvar treesitter-context-background-color "#000000"
"Background color for treesitter-context posframe")
(defcustom treesitter-context-background-color "#000000"
"Background color for treesitter-context posframe."
:version "29.1"
:type 'color
:group 'treesitter-context)

(defvar treesitter-context-border-color "#FFFFFF"
"Border color for treesitter-context posframe")
(defcustom treesitter-context-border-color "#FFFFFF"
"Border color for treesitter-context posframe."
:version "29.1"
:type 'color
:group 'treesitter-context)

(defvar treesitter-context-border-width 1
"Border width for treesitter-context posframe")
(defcustom treesitter-context-border-width 1
"Border width for treesitter-context posframe."
:version "29.1"
:type 'integer
:safe 'integerp
:group 'treesitter-context)

(defvar-local treesitter-context--refresh-timer nil
"Idle timer for refreshing context.")
Expand Down Expand Up @@ -139,6 +193,33 @@ See `posframe-show' for more infor about hidehandler and INFO ."
(let ((extra (max 0 (- len (length s)))))
(concat s (make-string extra ?\s))))

(defun treesitter-context--poshandler-with-offset (base-handler)
"Wrap a base poshandler to add offset support."
(lambda (info)
(let* ((base-pos (funcall base-handler info))
(offset-x treesitter-context-frame-offset-x)
(offset-y treesitter-context-frame-offset-y))
(cons (+ (car base-pos) offset-x)
(+ (cdr base-pos) offset-y)))))

(defun treesitter-context--get-poshandler ()
"Get the appropriate poshandler based on customization."
(cond
;; Window-relative positions with offset support
((eq treesitter-context-frame-position 'top-right)
(treesitter-context--poshandler-with-offset #'posframe-poshandler-window-top-right-corner))
((eq treesitter-context-frame-position 'top-left)
(treesitter-context--poshandler-with-offset #'posframe-poshandler-window-top-left-corner))
((eq treesitter-context-frame-position 'bottom-right)
(treesitter-context--poshandler-with-offset #'posframe-poshandler-window-bottom-right-corner))
((eq treesitter-context-frame-position 'bottom-left)
(treesitter-context--poshandler-with-offset #'posframe-poshandler-window-bottom-left-corner))
;; Custom function
((functionp treesitter-context-frame-position)
treesitter-context-frame-position)
;; Default fallback
(t (treesitter-context--poshandler-with-offset #'posframe-poshandler-window-top-right-corner))))

(defun treesitter-context--show-context ()
"Show context in a child frame."
(let* ((buffer (get-buffer-create treesitter-context--buffer-name))
Expand All @@ -148,7 +229,7 @@ See `posframe-show' for more infor about hidehandler and INFO ."
(prefix-len 0)
(line-no-prefix "")
(blank-prefix "")
(padding " ")
(padding (make-string treesitter-context-frame-padding ?\s))
(font-height (face-attribute 'default :height))
first-line-p)
(when treesitter-context-show-line-number
Expand Down Expand Up @@ -178,18 +259,22 @@ See `posframe-show' for more infor about hidehandler and INFO ."
(> treesitter-context-frame-font-fraction 0.0))
(setq treesitter-context-frame-font nil)
(setq font-height (round (* font-height treesitter-context-frame-font-fraction))))
(setq treesitter-context--child-frame (posframe-show buffer
:poshandler #'posframe-poshandler-window-top-right-corner
:font treesitter-context-frame-font
:border-width treesitter-context-border-width
:background-color treesitter-context-background-color
:internal-border-color treesitter-context-border-color
:internal-border-width treesitter-context-border-width
:min-width (min (max treesitter-context-frame-min-width (/ (window-width) 2)) (window-width))
:min-height treesitter-context-frame-min-height
:accept-focus nil
:hidehandler #'treesitter-context--posframe-hidehandler-when-buffer-change
:timeout treesitter-context-frame-autohide-timeout))
(setq treesitter-context--child-frame
(posframe-show buffer
:poshandler (treesitter-context--get-poshandler)
:font treesitter-context-frame-font
:border-width treesitter-context-border-width
:background-color treesitter-context-background-color
:internal-border-color treesitter-context-border-color
:internal-border-width treesitter-context-border-width
:min-width (min (max treesitter-context-frame-min-width (/ (window-width) 2))
(or treesitter-context-frame-max-width (window-width)))
:max-width treesitter-context-frame-max-width
:min-height treesitter-context-frame-min-height
:max-height treesitter-context-frame-max-height
:accept-focus nil
:hidehandler #'treesitter-context--posframe-hidehandler-when-buffer-change
:timeout treesitter-context-frame-autohide-timeout))
(when font-height
(set-face-attribute 'default treesitter-context--child-frame :height font-height)))
nil)
Expand Down