-
Notifications
You must be signed in to change notification settings - Fork 12
/
sidebar-utils.el
160 lines (134 loc) · 5.71 KB
/
sidebar-utils.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
;;; sidebar-utils.el --- sidebar-utils -*- lexical-binding: t; -*-
;; Copyright (C) 2017 Sebastien Chapuis
;; Author: Sebastien Chapuis <[email protected]>
;; URL: https://github.com/sebastiencs/sidebar.el
;; Keywords: files, convenience, frames
;; Version: 0.0.1
;; Package-Requires: ((emacs "25") (dash "2.11.0") (projectile "0.10.0"))
;;; License
;;
;; 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 this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;; Commentary:
;;
;; Functions needed in files sidebar.el and sidebar-select.el
;;
;;; Code:
(require 'frame-local)
(defvar sidebar-width)
(defmacro sidebar-get (var &optional frame)
"Get VAR in the current frame."
(let ((var-name (intern (format "sidebar-%s" var))))
`(frame-local-get ',var-name (or ,frame (selected-frame)))))
(defmacro sidebar-set (var val &optional frame)
"Set VAR to VAL in the current frame.
Return VAL."
(declare (indent 1))
(let ((var-name (intern (format "sidebar-%s" var))))
`(frame-local-set ',var-name ,val (or ,frame (selected-frame)))))
(defmacro sidebar-set1 (var val)
"Set VAR to VAL in the current frame.
The difference with `sidebar-set' is that the var parameter is
evaluated.
VAR need to be prefixed with 'sidebar-'."
`(frame-local-set ,var ,val (selected-frame)))
(defmacro sidebar-content-provider (name arglist &rest args)
"Make a content provider NAME with arguments ARGLIST.
The function should return a list of strings that will be
display in the sidebar.
ARGS is the function body with an optional doc."
(declare (doc-string 3) (indent 2))
(let* ((doc (when (stringp (car args))
(prog1 (car args)
(setq args (cdr args)))))
(body args))
`(progn
(defun ,(intern (format "sidebar-content-%s" name)) ,arglist
,doc
(-map (sidebar-get item-builder-function) (progn ,@body))))))
(defmacro sidebar-print-function (name arglist &rest args)
"NAME ARGLIST ARGS."
(declare (doc-string 3) (indent 2)
(debug (form args)))
(let* ((doc (when (stringp (car args))
(prog1 (car args)
(setq args (cdr args)))))
(body args))
`(progn
(defun ,(intern (format "sidebar-print-%s" name)) ,arglist
,doc
(-when-let (line (progn ,@body))
(add-text-properties 0 (length line) (list 'sidebar-item ,(car arglist)) line)
(insert line))))))
(defun sidebar-gui-p ()
"Return non-nil if we're on a graphic instance."
(display-graphic-p))
(defun sidebar-goto-line (line &optional force)
"Go to LINE.
The function checks to not go at the last line (there is no
filename on this line)
if FORCE is non-nil, there is no check."
(if force
(forward-line (- line (line-number-at-pos)))
(let ((max (count-lines (point-min) (point-max))))
(when (> line max)
(setq line max))
(forward-line (- line (line-number-at-pos))))))
(defvar it)
(defun sidebar-cons-buffer-name (&optional suffix)
"Construct the buffer name from 'SIDEBAR' and the frame name.
The return value should be unique for each frame.
On terminals instance, we use the frame parameter `name'
On Graphics ones, the name isn't unique for each frame, so we use
`window-id' that isn't available on terminals instance.
SUFFIX is an optional string to append."
(or (unless suffix (sidebar-get buffer-name))
(--> (concat " *SIDEBAR-" (or (frame-parameter nil 'window-id)
(frame-parameter nil 'name))
suffix "*")
(if suffix it (sidebar-set buffer-name it)))))
;;(ignore-errors (kill-buffer (sidebar-cons-buffer-name)))
(defun sidebar-set-window (&optional width)
"Display the sidebar buffer in a side window.
It can also be used to resize the window with WIDTH."
(let ((w (or width (sidebar-get default-width) sidebar-width)))
(display-buffer (sidebar-get-buffer)
`(display-buffer-in-side-window . ((side . left) (window-width . ,w))))))
(defun sidebar-get-window (&optional no-creation)
"Return the created/existing window displaying the sidebar buffer.
If NO-CREATION is non-nil, the window is not created."
(let ((sidebar-window (get-buffer-window (sidebar-cons-buffer-name))))
(unless (or sidebar-window no-creation)
(setq sidebar-window (sidebar-set-window))
(set-window-dedicated-p sidebar-window t)
(set-window-parameter sidebar-window 'no-delete-other-windows t))
sidebar-window))
(defun sidebar-file-struct (file)
"Return an association list from FILE.
The parameter FILE is a path.
In this project (sidebar.el) every parameters named 'file' are
object using this structure.
- 'path is the FILE's path
- 'dir is non-nil if FILE is a directory
- 'line is the number line where FILE is printed on the sidebar
- 'opened is non-nil it it's a directory and is expanded.
Example: (('path . \"/tmp/dir1/dir2\") ('dir . t) ('line . 8) ('opened . nil))"
(list (cons 'path file)
(cons 'dir (file-directory-p file))
(cons 'line 0)
(cons 'opened nil)))
(defun sidebar-get-buffer ()
"Return the existing/created sidebar buffer for the current frame."
(get-buffer-create (sidebar-cons-buffer-name)))
(provide 'sidebar-utils)
;;; sidebar-utils.el ends here