| Hash | Commit message | Author | Date | Files | + | - |
1 | commit b9eae69963f6748a30a8c172102d76b9a8420164 |
2 | Author: Connor Etherington <[email protected]> |
3 | Date: Mon Oct 2 08:55:39 2023 +0200 |
4 | |
5 | Auto-Commit Update - 20231002 |
6 | --- |
7 | BUILD/.pkg.pkg.tar.xz | Bin 0 -> 78520 bytes |
8 | BUILD/.pkg/Makefile | 92 ++++ |
9 | BUILD/.pkg/README.md | 157 ++++++ |
10 | BUILD/.pkg/lfp.install | 9 + |
11 | .../lfpreviewer/X.cpython-310-x86_64-linux-gnu.so | Bin 0 -> 105296 bytes |
12 | .../lfpreviewer/X.cpython-311-x86_64-linux-gnu.so | Bin 0 -> 34696 bytes |
13 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/X.c | 36 ++ |
14 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/X.h | 7 + |
15 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/Xshm.c | 296 +++++++++++ |
16 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/Xshm.h | 7 + |
17 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/display.c | 276 ++++++++++ |
18 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/display.h | 29 ++ |
19 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/math.h | 7 + |
20 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/python.h | 11 + |
21 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/util.h | 28 + |
22 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/window.c | 316 +++++++++++ |
23 | BUILD/.pkg/lfpreviewer/lfpreviewer/X/window.h | 7 + |
24 | BUILD/.pkg/lfpreviewer/lfpreviewer/__init__.py | 7 + |
25 | BUILD/.pkg/lfpreviewer/lfpreviewer/__main__.py | 59 +++ |
26 | BUILD/.pkg/lfpreviewer/lfpreviewer/action.py | 294 +++++++++++ |
27 | BUILD/.pkg/lfpreviewer/lfpreviewer/batch.py | 267 ++++++++++ |
28 | BUILD/.pkg/lfpreviewer/lfpreviewer/conversion.py | 14 + |
29 | BUILD/.pkg/lfpreviewer/lfpreviewer/files.py | 47 ++ |
30 | BUILD/.pkg/lfpreviewer/lfpreviewer/geometry.py | 20 + |
31 | BUILD/.pkg/lfpreviewer/lfpreviewer/layer.py | 253 +++++++++ |
32 | BUILD/.pkg/lfpreviewer/lfpreviewer/lib/__init__.py | 0 |
33 | BUILD/.pkg/lfpreviewer/lfpreviewer/lib/lib.sh | 69 +++ |
34 | .../lfpreviewer/lfpreviewer/lib/v0/__init__.py | 323 ++++++++++++ |
35 | BUILD/.pkg/lfpreviewer/lfpreviewer/library.py | 8 + |
36 | BUILD/.pkg/lfpreviewer/lfpreviewer/loading.py | 494 ++++++++++++++++++ |
37 | BUILD/.pkg/lfpreviewer/lfpreviewer/parser.py | 145 ++++++ |
38 | BUILD/.pkg/lfpreviewer/lfpreviewer/pattern.py | 12 + |
39 | BUILD/.pkg/lfpreviewer/lfpreviewer/process.py | 134 +++++ |
40 | .../.pkg/lfpreviewer/lfpreviewer/query_windows.py | 99 ++++ |
41 | BUILD/.pkg/lfpreviewer/lfpreviewer/scaling.py | 264 ++++++++++ |
42 | BUILD/.pkg/lfpreviewer/lfpreviewer/terminal.py | 109 ++++ |
43 | BUILD/.pkg/lfpreviewer/lfpreviewer/thread.py | 48 ++ |
44 | BUILD/.pkg/lfpreviewer/lfpreviewer/tmux_util.py | 103 ++++ |
45 | BUILD/.pkg/lfpreviewer/lfpreviewer/ui.py | 177 +++++++ |
46 | BUILD/.pkg/lfpreviewer/lfpreviewer/version.py | 5 + |
47 | BUILD/.pkg/lfpreviewer/lfpreviewer/xutil.py | 144 +++++ |
48 | BUILD/.pkg/lfpreviewer/setup.py | 28 + |
49 | BUILD/.pkg/usr/bin/lfp | 4 + |
50 | BUILD/.pkg/usr/share/doc/lfp/README.md | 157 ++++++ |
51 | BUILD/.pkg/usr/share/lfp/cleaner | 8 + |
52 | BUILD/.pkg/usr/share/lfp/lfp | 14 + |
53 | BUILD/.pkg/usr/share/lfp/lfp-icons | 117 +++++ |
54 | BUILD/.pkg/usr/share/lfp/lfpcd | 7 + |
55 | BUILD/.pkg/usr/share/lfp/lfprc | 579 +++++++++++++++++++++ |
56 | BUILD/.pkg/usr/share/lfp/ocr/ocr.js | 56 ++ |
57 | BUILD/.pkg/usr/share/lfp/ocr/package-lock.json | 27 + |
58 | BUILD/.pkg/usr/share/lfp/ocr/package.json | 19 + |
59 | BUILD/.pkg/usr/share/lfp/ocr/tesseract/LICENSE | 21 + |
60 | .../.pkg/usr/share/lfp/ocr/tesseract/package.json | 37 ++ |
61 | BUILD/.pkg/usr/share/lfp/ocr/tesseract/readme.md | 96 ++++ |
62 | .../usr/share/lfp/ocr/tesseract/src/index.d.ts | 195 +++++++ |
63 | .../.pkg/usr/share/lfp/ocr/tesseract/src/index.js | 58 +++ |
64 | BUILD/.pkg/usr/share/lfp/ocr/yarn.lock | 8 + |
65 | BUILD/.pkg/usr/share/lfp/scope | 42 ++ |
66 | BUILD/.pkg/usr/share/licenses/lfp/LICENSE | 27 + |
67 | BUILD/.pkg/usr/share/man/man1/lfp.1.gz | Bin 0 -> 1916 bytes |
68 | BUILD/PKGBUILD | 54 ++ |
69 | BUILD/lfp.install | 9 + |
70 | BUILD/lfp/HEAD | 1 + |
71 | BUILD/lfp/config | 8 + |
72 | BUILD/lfp/description | 1 + |
73 | BUILD/lfp/hooks/applypatch-msg.sample | 15 + |
74 | BUILD/lfp/hooks/commit-msg.sample | 24 + |
75 | BUILD/lfp/hooks/fsmonitor-watchman.sample | 174 +++++++ |
76 | BUILD/lfp/hooks/post-update.sample | 8 + |
77 | BUILD/lfp/hooks/pre-applypatch.sample | 14 + |
78 | BUILD/lfp/hooks/pre-commit.sample | 49 ++ |
79 | BUILD/lfp/hooks/pre-merge-commit.sample | 13 + |
80 | BUILD/lfp/hooks/pre-push.sample | 53 ++ |
81 | BUILD/lfp/hooks/pre-rebase.sample | 169 ++++++ |
82 | BUILD/lfp/hooks/pre-receive.sample | 24 + |
83 | BUILD/lfp/hooks/prepare-commit-msg.sample | 42 ++ |
84 | BUILD/lfp/hooks/push-to-checkout.sample | 78 +++ |
85 | BUILD/lfp/hooks/sendemail-validate.sample | 77 +++ |
86 | BUILD/lfp/hooks/update.sample | 128 +++++ |
87 | BUILD/lfp/info/exclude | 6 + |
88 | ...ck-8e07188bfd62ea160e5d9f224baaab63a0e44c15.idx | Bin 0 -> 88628 bytes |
89 | ...k-8e07188bfd62ea160e5d9f224baaab63a0e44c15.pack | Bin 0 -> 56751126 bytes |
90 | ...ck-8e07188bfd62ea160e5d9f224baaab63a0e44c15.rev | Bin 0 -> 12560 bytes |
91 | BUILD/lfp/packed-refs | 2 + |
92 | BUILD/pkg/lfp/usr/bin/lfp | 4 + |
93 | BUILD/pkg/lfp/usr/bin/lfpreviewer | 33 ++ |
94 | .../lfpreviewer-0.1.0-py3.10.egg-info/PKG-INFO | 12 + |
95 | .../lfpreviewer-0.1.0-py3.10.egg-info/SOURCES.txt | 35 ++ |
96 | .../dependency_links.txt | 1 + |
97 | .../entry_points.txt | 2 + |
98 | .../lfpreviewer-0.1.0-py3.10.egg-info/requires.txt | 3 + |
99 | .../top_level.txt | 1 + |
100 | .../lfpreviewer/X.cpython-310-x86_64-linux-gnu.so | Bin 0 -> 111600 bytes |
101 | .../lib/python3.10/site-packages/lfpreviewer/X/X.c | 36 ++ |
102 | .../python3.10/site-packages/lfpreviewer/X/Xshm.c | 296 +++++++++++ |
103 | .../site-packages/lfpreviewer/X/display.c | 276 ++++++++++ |
104 | .../site-packages/lfpreviewer/X/window.c | 316 +++++++++++ |
105 | .../site-packages/lfpreviewer/__init__.py | 7 + |
106 | .../site-packages/lfpreviewer/__main__.py | 59 +++ |
107 | .../__pycache__/__init__.cpython-310.opt-1.pyc | Bin 0 -> 508 bytes |
108 | .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 508 bytes |
109 | .../__pycache__/__main__.cpython-310.opt-1.pyc | Bin 0 -> 1973 bytes |
110 | .../__pycache__/__main__.cpython-310.pyc | Bin 0 -> 1973 bytes |
111 | .../__pycache__/action.cpython-310.opt-1.pyc | Bin 0 -> 9651 bytes |
112 | .../lfpreviewer/__pycache__/action.cpython-310.pyc | Bin 0 -> 9651 bytes |
113 | .../__pycache__/batch.cpython-310.opt-1.pyc | Bin 0 -> 10837 bytes |
114 | .../lfpreviewer/__pycache__/batch.cpython-310.pyc | Bin 0 -> 10837 bytes |
115 | .../__pycache__/conversion.cpython-310.opt-1.pyc | Bin 0 -> 530 bytes |
116 | .../__pycache__/conversion.cpython-310.pyc | Bin 0 -> 530 bytes |
117 | .../__pycache__/files.cpython-310.opt-1.pyc | Bin 0 -> 1786 bytes |
118 | .../lfpreviewer/__pycache__/files.cpython-310.pyc | Bin 0 -> 1786 bytes |
119 | .../__pycache__/geometry.cpython-310.opt-1.pyc | Bin 0 -> 1121 bytes |
120 | .../__pycache__/geometry.cpython-310.pyc | Bin 0 -> 1121 bytes |
121 | .../__pycache__/layer.cpython-310.opt-1.pyc | Bin 0 -> 8537 bytes |
122 | .../lfpreviewer/__pycache__/layer.cpython-310.pyc | Bin 0 -> 8537 bytes |
123 | .../__pycache__/library.cpython-310.opt-1.pyc | Bin 0 -> 430 bytes |
124 | .../__pycache__/library.cpython-310.pyc | Bin 0 -> 430 bytes |
125 | .../__pycache__/loading.cpython-310.opt-1.pyc | Bin 0 -> 17686 bytes |
126 | .../__pycache__/loading.cpython-310.pyc | Bin 0 -> 17686 bytes |
127 | .../__pycache__/parser.cpython-310.opt-1.pyc | Bin 0 -> 5227 bytes |
128 | .../lfpreviewer/__pycache__/parser.cpython-310.pyc | Bin 0 -> 5227 bytes |
129 | .../__pycache__/pattern.cpython-310.opt-1.pyc | Bin 0 -> 795 bytes |
130 | .../__pycache__/pattern.cpython-310.pyc | Bin 0 -> 795 bytes |
131 | .../__pycache__/process.cpython-310.opt-1.pyc | Bin 0 -> 3521 bytes |
132 | .../__pycache__/process.cpython-310.pyc | Bin 0 -> 3521 bytes |
133 | .../query_windows.cpython-310.opt-1.pyc | Bin 0 -> 2661 bytes |
134 | .../__pycache__/query_windows.cpython-310.pyc | Bin 0 -> 2661 bytes |
135 | .../__pycache__/scaling.cpython-310.opt-1.pyc | Bin 0 -> 10006 bytes |
136 | .../__pycache__/scaling.cpython-310.pyc | Bin 0 -> 10006 bytes |
137 | .../__pycache__/terminal.cpython-310.opt-1.pyc | Bin 0 -> 2958 bytes |
138 | .../__pycache__/terminal.cpython-310.pyc | Bin 0 -> 2958 bytes |
139 | .../__pycache__/thread.cpython-310.opt-1.pyc | Bin 0 -> 1842 bytes |
140 | .../lfpreviewer/__pycache__/thread.cpython-310.pyc | Bin 0 -> 1842 bytes |
141 | .../__pycache__/tmux_util.cpython-310.opt-1.pyc | Bin 0 -> 3183 bytes |
142 | .../__pycache__/tmux_util.cpython-310.pyc | Bin 0 -> 3183 bytes |
143 | .../__pycache__/ui.cpython-310.opt-1.pyc | Bin 0 -> 6572 bytes |
144 | .../lfpreviewer/__pycache__/ui.cpython-310.pyc | Bin 0 -> 6572 bytes |
145 | .../__pycache__/version.cpython-310.opt-1.pyc | Bin 0 -> 303 bytes |
146 | .../__pycache__/version.cpython-310.pyc | Bin 0 -> 303 bytes |
147 | .../__pycache__/xutil.cpython-310.opt-1.pyc | Bin 0 -> 5092 bytes |
148 | .../lfpreviewer/__pycache__/xutil.cpython-310.pyc | Bin 0 -> 5092 bytes |
149 | .../python3.10/site-packages/lfpreviewer/action.py | 294 +++++++++++ |
150 | .../python3.10/site-packages/lfpreviewer/batch.py | 267 ++++++++++ |
151 | .../site-packages/lfpreviewer/conversion.py | 14 + |
152 | .../python3.10/site-packages/lfpreviewer/files.py | 47 ++ |
153 | .../site-packages/lfpreviewer/geometry.py | 20 + |
154 | .../python3.10/site-packages/lfpreviewer/layer.py | 253 +++++++++ |
155 | .../site-packages/lfpreviewer/lib/__init__.py | 0 |
156 | .../lib/__pycache__/__init__.cpython-310.opt-1.pyc | Bin 0 -> 154 bytes |
157 | .../lib/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 154 bytes |
158 | .../site-packages/lfpreviewer/lib/lib.sh | 69 +++ |
159 | .../site-packages/lfpreviewer/lib/v0/__init__.py | 323 ++++++++++++ |
160 | .../v0/__pycache__/__init__.cpython-310.opt-1.pyc | Bin 0 -> 11202 bytes |
161 | .../lib/v0/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 11202 bytes |
162 | .../site-packages/lfpreviewer/library.py | 8 + |
163 | .../site-packages/lfpreviewer/loading.py | 494 ++++++++++++++++++ |
164 | .../python3.10/site-packages/lfpreviewer/parser.py | 145 ++++++ |
165 | .../site-packages/lfpreviewer/pattern.py | 12 + |
166 | .../site-packages/lfpreviewer/process.py | 134 +++++ |
167 | .../site-packages/lfpreviewer/query_windows.py | 99 ++++ |
168 | .../site-packages/lfpreviewer/scaling.py | 264 ++++++++++ |
169 | .../site-packages/lfpreviewer/terminal.py | 109 ++++ |
170 | .../python3.10/site-packages/lfpreviewer/thread.py | 48 ++ |
171 | .../site-packages/lfpreviewer/tmux_util.py | 103 ++++ |
172 | .../lib/python3.10/site-packages/lfpreviewer/ui.py | 177 +++++++ |
173 | .../site-packages/lfpreviewer/version.py | 5 + |
174 | .../python3.10/site-packages/lfpreviewer/xutil.py | 144 +++++ |
175 | BUILD/pkg/lfp/usr/share/doc/lfp/README.md | 157 ++++++ |
176 | BUILD/pkg/lfp/usr/share/lfp/cleaner | 8 + |
177 | BUILD/pkg/lfp/usr/share/lfp/lfp | 14 + |
178 | BUILD/pkg/lfp/usr/share/lfp/lfp-icons | 117 +++++ |
179 | BUILD/pkg/lfp/usr/share/lfp/lfpcd | 7 + |
180 | BUILD/pkg/lfp/usr/share/lfp/lfprc | 579 +++++++++++++++++++++ |
181 | BUILD/pkg/lfp/usr/share/lfp/ocr/ocr.js | 56 ++ |
182 | BUILD/pkg/lfp/usr/share/lfp/ocr/package.json | 19 + |
183 | BUILD/pkg/lfp/usr/share/lfp/scope | 42 ++ |
184 | BUILD/pkg/lfp/usr/share/licenses/lfp/LICENSE | 27 + |
185 | BUILD/pkg/lfp/usr/share/man/man1/lfp.1.gz | Bin 0 -> 1916 bytes |
186 | BUILD/src/lfp | 1 + |
187 | BUILD/tmpPKGB | 45 ++ |
188 | BUILD/zst.sums | 8 + |
189 | 182 files changed, 12012 insertions(+) |
190 | |
191 | diff --git a/BUILD/.pkg.pkg.tar.xz b/BUILD/.pkg.pkg.tar.xz |
192 | new file mode 100644 |
193 | index 0000000..c9fdb8d |
194 | Binary files /dev/null and b/BUILD/.pkg.pkg.tar.xz differ |
195 | diff --git a/BUILD/.pkg/Makefile b/BUILD/.pkg/Makefile |
196 | new file mode 100644 |
197 | index 0000000..ac1b8bb |
198 | --- /dev/null |
199 | +++ b/BUILD/.pkg/Makefile |
200 | @@ -0,0 +1,92 @@ |
201 | + |
202 | +PKG = lfp |
203 | +PREVIEWER = lfpreviewer |
204 | + |
205 | +INFO = $(shell uname -a) |
206 | +OST = $(shell lsb_release -d | sed 's|Description:\s*||') |
207 | +OS = $(shell lsb_release -d | sed 's|Description:\s*||'|cut -d\ -f1) |
208 | + |
209 | +ifeq ($(OS),Ubuntu) |
210 | + PACKAGE_MANAGER = apt |
211 | + INSTALL = sudo ${PACKAGE_MANAGER}-get install |
212 | + QUERY = sudo dpkg -S >/dev/null 2>&1 |
213 | + PKGS = python3-pip python3-setuptools libxres1 |
214 | +endif |
215 | + |
216 | +ifeq ($(OS),Debian) |
217 | + PACKAGE_MANAGER = apt |
218 | + INSTALL = sudo ${PACKAGE_MANAGER}-get install |
219 | + QUERY = sudo dpkg -S >/dev/null 2>&1 |
220 | + PKGS = python3-pip python3-setuptools libxres1 |
221 | +endif |
222 | + |
223 | +ifeq ($(OS),Arch) |
224 | + PACKAGE_MANAGER = pacman |
225 | + INSTALL = sudo ${PACKAGE_MANAGER} -Syy |
226 | + QUERY = sudo ${PACKAGE_MANAGER} -Qq >/dev/null 2>&1 |
227 | + PKGS = python-pip python-setuptools libxres |
228 | +endif |
229 | + |
230 | +ifeq ($(PACKAGE_MANAGER),) |
231 | +$(error > Unsupported OS: ${OST}) |
232 | +endif |
233 | + |
234 | +all: info |
235 | + |
236 | +lfpreviewer: |
237 | + @echo -e "\n\e[1;33m[+]\e[0m Installing ${PREVIEWER}...\n" |
238 | + @rm -rf ${PREVIEWER}/build ${PREVIEWER}/${PREVIEWER}.egg-info ${PREVIEWER}/dist |
239 | + @${QUERY} ${PKGS} || ${INSTALL} ${PKGS} |
240 | + @python3 -m pip install --upgrade pip |
241 | + @python3 -m pip install --upgrade setuptools |
242 | + @cd ${PREVIEWER} && python3 ./setup.py install && cd .. || true |
243 | + @which lfpreviewer >/dev/null 2>&1 || echo -e "\n\e[1;31m[-]\e[0m Please ensure you have sufficient premission to install ${PREVIEWER}." |
244 | + |
245 | +lfp: |
246 | + @echo -e "\n\e[1;33m[+]\e[0m Installing ${PKG}...\n" |
247 | + @sudo install -Dm755 usr/bin/* -t "${PKGDIR}/usr/bin" || true |
248 | + @sudo install -Dm755 usr/share/${PKG}/{${PKG},${PKG}cd,cleaner,scope} -t "${PKGDIR}/usr/share/${PKG}" || true |
249 | + @sudo install -Dm644 usr/share/${PKG}/{${PKG}-icons,${PKG}rc} -t "${PKGDIR}/usr/share/${PKG}" || true |
250 | + @sudo install -Dm644 usr/share/licenses/${PKG}/LICENSE "${PKGDIR}/usr/share/licenses/${PKG}/LICENSE" || true |
251 | + @sudo install -Dm644 usr/share/doc/${PKG}/README.md "${PKGDIR}/usr/share/doc/${PKG}/README.md" || true |
252 | + @sudo install -Dm644 usr/share/man/man1/${PKG}.1.gz "${PKGDIR}/usr/share/man/man1/${PKG}.1.gz" || true |
253 | + @[ ! -d /usr/share/lfp ] && echo -e "\n\e[1;31m[-]\e[0m Please ensure you have sufficient premission to install ${PKG}." || true |
254 | + |
255 | +install: lfpreviewer lfp cd-on-exit |
256 | + |
257 | +clean: |
258 | + @echo -e "\n\e[1;33m[+]\e[0m Cleaning up..." |
259 | + @sudo rm -rf ${PKGDIR}/lib/python3.*/site-packages/${PREVIEWER}* |
260 | + @sudo rm -rf ${PKGDIR}/usr/bin/${PREVIEWER} |
261 | + @sudo rm -rf ${PKGDIR}/usr/share/${PKG} |
262 | + @sudo rm -rf ${PKGDIR}/usr/bin/${PKG} |
263 | + @sudo rm -rf ${PKGDIR}/usr/bin/${PKG}cd |
264 | + @sudo rm -rf ${PKGDIR}/usr/bin/cleaner |
265 | + @sudo rm -rf ${PKGDIR}/usr/bin/scope |
266 | + @sudo rm -rf ${PKGDIR}/usr/share/licenses/${PKG} |
267 | + @sudo rm -rf ${PKGDIR}/usr/share/doc/${PKG} |
268 | + @sudo rm -rf ${PKGDIR}/usr/share/man/man1/${PKG}.1.gz |
269 | + |
270 | +info: |
271 | + @echo -e "\n\e[1;33m[*]\e[0m ${INFO}" |
272 | + |
273 | +help: |
274 | + @echo -e "\n Usage: make [all|install|uninstall|clean|distclean|preview|help]\n" |
275 | + @echo " all: build $(PKG)" |
276 | + @echo " install: install $(PKG)" |
277 | + @echo " uninstall: uninstall $(PKG)" |
278 | + @echo " clean: clean $(PKG)" |
279 | + @echo " distclean: clean $(PKG) and remove $(PKG) directory" |
280 | + @echo " preview: preview $(PKG)" |
281 | + @echo " help: show this help" |
282 | + |
283 | +cd-on-exit: |
284 | + @[ -d /usr/share/lfp ] && echo -e "\n\n\033[1;32m[+]\e[0;1m For on-exit directory changing, add the following line to your bash/zshrc\e[0m :\e[36m\n\n source '/usr/share/lfp/lfpcd'\n\e[0m" || echo -e "\n\033[1;31m[!]\e[0;1m Installation Failed!" |
285 | + |
286 | +uninstall: clean |
287 | + @echo -e "\n\e[1;32m[+]\e[0m ${PKG} successfully uninstalled" |
288 | + |
289 | +remove: uninstall |
290 | + |
291 | +.PHONY: info all lfpreviewer lfp install clean help cd-on-exit uninstall remove |
292 | + |
293 | diff --git a/BUILD/.pkg/README.md b/BUILD/.pkg/README.md |
294 | new file mode 100644 |
295 | index 0000000..f3d345a |
296 | --- /dev/null |
297 | +++ b/BUILD/.pkg/README.md |
298 | @@ -0,0 +1,157 @@ |
299 | + |
300 | +# An lf wrapper, with built-in previews and on-exit directory changing. |
301 | + |
302 | +### `lfp` is a simple wrapper for the `lf` file manager, with built-in file, image, and video previews, as well as on-exit directory changing. |
303 | +### The program makes use of `ueberzug` to preview images, documents, and video thumbnails. Preview behavior can be altered by editing the *scope* file. |
304 | + |
305 | +**Version: 4.1.0** |
306 | + |
307 | +*** |
308 | + |
309 | +## Usage: |
310 | + |
311 | +Run `lfp`. Optionally, a startup directory can be specified by a second argument. By default, `lfp` will launch in your current working directory. |
312 | +Icons for relative file types can be changed by editing the lfp-icons file in *'/usr/share/lfp/lfp-icons'*. |
313 | + |
314 | +**CD on exit:** |
315 | + |
316 | +For on-exit directory changing, add the following line to your bash/zshrc: |
317 | + |
318 | + source '/usr/share/lfp/lfpcd' |
319 | + |
320 | + |
321 | +**LFP OCR:** |
322 | + |
323 | +LFP OCR is a simple OCR script that uses tesseract to extract text from images. It can be used as a standalone script, or as a lfp action. |
324 | +All detected text is copied to your clipboard. |
325 | + |
326 | + |
327 | + |
328 | + |
329 | +## Installation |
330 | + |
331 | +### Arch Linux |
332 | + |
333 | +lfp is available in the AUR as `lfp` or `lfp-git` |
334 | + |
335 | + |
336 | +### Manual Installation |
337 | + |
338 | + tmp=$(mktemp -d); |
339 | + git clone https://gitlab.com/a4to/lfp.git ${tmp} && |
340 | + cd ${tmp} && sudo make clean install && cd - && |
341 | + rm -rf ${tmp} >/dev/null 2>&1 || true |
342 | + |
343 | + |
344 | +**To uninstall lfp:** |
345 | + |
346 | + sudo make uninstall |
347 | + |
348 | + |
349 | + |
350 | +## Prerequisites: |
351 | + |
352 | +* `lf`: the file manager |
353 | +* `zsh`: for scripting |
354 | +* `ueberzug`: for image previews |
355 | +* `ghostscript`: for PDF previews |
356 | +* `graphicsmagick`: for SVG and GIF previews |
357 | +* `ffmpeg`: for video file thumbnail previews |
358 | +* `dialog`: required by many functions outside the scope of image and video previews |
359 | +* `dunst`: to receive notifications upon task completion and so forth |
360 | +* `fzf`: for lfp's *fzfp* (fuzzy-finding) and *pushto* (git push) capabilities |
361 | +* `bat`: for text file previews |
362 | +* `git`: for cloning repos from within lfp |
363 | +* `lolcat`: used in lfp's *fzfp* function |
364 | + |
365 | +## Optional Dependencies: |
366 | + |
367 | +* `nodejs`: to make use of lfps built in node actions manager |
368 | +* `python3`: to make use of lfps built in python actions manager |
369 | + |
370 | + |
371 | + |
372 | +## Keybindings |
373 | + |
374 | +### Navigation: |
375 | + |
376 | +* **h**: Left |
377 | +* **j**: Down |
378 | +* **k**: Up |
379 | +* **l**: Right |
380 | + |
381 | + |
382 | +### Main Features and Functions: |
383 | + |
384 | +* **.**: Activate NodeManager |
385 | +* **,**: Activate PyManager |
386 | +* **o**: Activate LFP OCR |
387 | +* **v**: Toggle select all file(s) |
388 | +* **y**: Copy selected file(s) |
389 | +* **c**: Cut selected file(s) |
390 | +* **d**: Delete selected file(s) |
391 | +* **p**: Paste selected file(s) |
392 | +* **d**: Delete selected file(s) |
393 | +* **s**: Edit file you're currently hovering over |
394 | +* **n**: Create new directory |
395 | +* **m**: Play with mpv |
396 | +* **f**: Activate fzfp (lfp's fuzzy-finder) |
397 | +* **b**: Open file in default browser |
398 | +* **e**: Prompts you for a filename to edit/create |
399 | +* **t**: Prompts you for a filename for blank file to create |
400 | +* **x**: Execute selected file(s) |
401 | +* **z**: Open in `sxiv` (an image viewer) |
402 | +* **q**: Quit lfp |
403 | +* **\<Space\>**: Select file(s) |
404 | +* **\<Period\>**: (.) - Activates Node Actions, various npm/yarn actions / quick command execution |
405 | + |
406 | + |
407 | +### NodeManager: |
408 | + |
409 | +The NodeManager function provides various actions to manage a Node.js project, including: |
410 | + |
411 | +* **↑ Arrow**: Initialize a package.json file. |
412 | +* **↓ Arrow**: Select a javascript file to run. |
413 | +* **← Arrow**: Specify package(s) to install from npm. |
414 | +* **→ Arrow**: Start the server (yarn start). |
415 | +* **[h|d|m]**:: Start the server in development mode (yarn dev). |
416 | +* **[b|n]**: Build the project (yarn build). |
417 | +* **[i|I|,]**: Initialize a new npm project. |
418 | +* **[r]**: Remove specified packages. |
419 | +* **.**: Update the server (yarn). |
420 | +* **/**: Create a webserver on port 3000 (requires serve). |
421 | +* **q**: Exit. |
422 | + |
423 | + |
424 | +### PyManager: |
425 | + |
426 | +The PyManager function provides various actions to manage a Python project, including: |
427 | + |
428 | +* **↑ Arrow**: Create a new Conda environment at "./.🐍". |
429 | +* **↓ Arrow**: Select a python script to run. |
430 | +* **← Arrow**: Select package(s) to install from pypi. |
431 | +* **→ Arrow**: Run the main.py script if found. |
432 | +* **q**: Exit. |
433 | + |
434 | + |
435 | +### Additional Actions and Features: |
436 | + |
437 | +* **B**: Bulk rename |
438 | +* **E**: Extract archive |
439 | +* **D**: (sudo) Delete selected file(s) |
440 | +* **L**: Symlink selected file(s) to current directory |
441 | +* **H**: Create hardlink of selected file(s) to current directory |
442 | +* **R**: Create relative symlink of selected file(s) to current directory |
443 | +* **E**: Extract archive (bz2 rar gz tar tar.* tbz2 tgz zip Z 7z deb) |
444 | +* **C**: CopyPath, this feature copies the absolute path of the file youre currently hovering over to your clipboard |
445 | +* **\<Ctrl+c\>**: Quick clone a git repository without leaving lfp |
446 | +* **\<Ctrl+g\>**: Activate pushto - select a branch to push to (only works inside a git repo) |
447 | +* **\<Ctrl+b\>**: Open file in browser |
448 | +* **\<Ctrl+6\>**: Chmod 644 selected file(s) |
449 | +* **\<Ctrl+7\>**: Chmod 755 selected file(s) |
450 | +* **\<Ctrl+8\>**: Chmod 700 selected file(s) |
451 | +* **\<Enter\>**: Enter shell command |
452 | + |
453 | + |
454 | +And many more. |
455 | + |
456 | diff --git a/BUILD/.pkg/lfp.install b/BUILD/.pkg/lfp.install |
457 | new file mode 100644 |
458 | index 0000000..6c915df |
459 | --- /dev/null |
460 | +++ b/BUILD/.pkg/lfp.install |
461 | @@ -0,0 +1,9 @@ |
462 | +post_install() { |
463 | + echo -e "\n \033[1;33m[+]\e[0;1;32m For on-exit directory changing, add the following line to your bash/zshrc\e[0m :\e[36m\n\n source '/usr/share/lfp/lfpcd'\n\n\n\e[0m" |
464 | +} |
465 | + |
466 | +post_upgrade() { |
467 | + which yarn >/dev/null 2>&1 && yarn install /usr/share/lfp/ocr || |
468 | + which npm >/dev/null 2>&1 && npm install /usr/share/lfp/ocr || |
469 | + true |
470 | +} |
471 | diff --git a/BUILD/.pkg/lfpreviewer/lfpreviewer/X.cpython-310-x86_64-linux-gnu.so b/BUILD/.pkg/lfpreviewer/lfpreviewer/X.cpython-310-x86_64-linux-gnu.so |
472 | new file mode 100755 |
473 | index 0000000..982026a |
474 | Binary files /dev/null and b/BUILD/.pkg/lfpreviewer/lfpreviewer/X.cpython-310-x86_64-linux-gnu.so differ |
475 | diff --git a/BUILD/.pkg/lfpreviewer/lfpreviewer/X.cpython-311-x86_64-linux-gnu.so b/BUILD/.pkg/lfpreviewer/lfpreviewer/X.cpython-311-x86_64-linux-gnu.so |
476 | new file mode 100755 |
477 | index 0000000..fcdf720 |
478 | Binary files /dev/null and b/BUILD/.pkg/lfpreviewer/lfpreviewer/X.cpython-311-x86_64-linux-gnu.so differ |
479 | diff --git a/BUILD/.pkg/lfpreviewer/lfpreviewer/X/X.c b/BUILD/.pkg/lfpreviewer/lfpreviewer/X/X.c |
480 | new file mode 100644 |
481 | index 0000000..ac2c09a |
482 | --- /dev/null |
483 | +++ b/BUILD/.pkg/lfpreviewer/lfpreviewer/X/X.c |
484 | @@ -0,0 +1,36 @@ |
485 | +#include "python.h" |
486 | +#include "display.h" |
487 | +#include "window.h" |
488 | +#include "Xshm.h" |
489 | + |
490 | + |
491 | +static PyModuleDef module = { |
492 | + PyModuleDef_HEAD_INIT, |
493 | + .m_name = "lfpreviewer.X", |
494 | + .m_doc = "Modul which implements the interaction with the Xshm extension.", |
495 | + .m_size = -1, |
496 | +}; |
497 | + |
498 | + |
499 | +PyMODINIT_FUNC |
500 | +PyInit_X(void) { |
501 | + PyObject *module_instance; |
502 | + if (PyType_Ready(&DisplayType) < 0 || |
503 | + PyType_Ready(&WindowType) < 0 || |
504 | + PyType_Ready(&ImageType) < 0) { |
505 | + return NULL; |
506 | + } |
507 | + |
508 | + module_instance = PyModule_Create(&module); |
509 | + if (module_instance == NULL) { |
510 | + return NULL; |
511 | + } |
512 | + |
513 | + Py_INCREF(&DisplayType); |
514 | + Py_INCREF(&WindowType); |
515 | + Py_INCREF(&ImageType); |
516 | + PyModule_AddObject(module_instance, "Display", (PyObject*)&DisplayType); |
517 | + PyModule_AddObject(module_instance, "OverlayWindow", (PyObject*)&WindowType); |
518 | + PyModule_AddObject(module_instance, "Image", (PyObject*)&ImageType); |
519 | + return module_instance; |
520 | +} |
521 | diff --git a/BUILD/.pkg/lfpreviewer/lfpreviewer/X/X.h b/BUILD/.pkg/lfpreviewer/lfpreviewer/X/X.h |
522 | new file mode 100644 |
523 | index 0000000..2523c59 |
524 | --- /dev/null |
525 | +++ b/BUILD/.pkg/lfpreviewer/lfpreviewer/X/X.h |
526 | @@ -0,0 +1,7 @@ |
527 | +#ifndef __X_H__ |
528 | +#define __X_H__ |
529 | +#include "python.h" |
530 | + |
531 | + |
532 | +PyModuleDef module; |
533 | +#endif |
534 | diff --git a/BUILD/.pkg/lfpreviewer/lfpreviewer/X/Xshm.c b/BUILD/.pkg/lfpreviewer/lfpreviewer/X/Xshm.c |
535 | new file mode 100644 |
536 | index 0000000..b68919a |
537 | --- /dev/null |
538 | +++ b/BUILD/.pkg/lfpreviewer/lfpreviewer/X/Xshm.c |
539 | @@ -0,0 +1,296 @@ |
540 | +#include "python.h" |
541 | + |
542 | +#include <stdbool.h> |
543 | +#include <sys/shm.h> |
544 | +#include <X11/Xlib.h> |
545 | +#include <X11/Xutil.h> |
546 | +#include <X11/extensions/XShm.h> |
547 | + |
548 | +#include "math.h" |
549 | +#include "util.h" |
550 | +#include "display.h" |
551 | + |
552 | +#define INVALID_SHM_ID -1 |
553 | +#define INVALID_SHM_ADDRESS (char*)-1 |
554 | +#define BYTES_PER_PIXEL 4 |
555 | + |
556 | + |
557 | +typedef struct { |
558 | + PyObject_HEAD |
559 | + int width; |
560 | + int height; |
561 | + int buffer_size; |
562 | + DisplayObject *display_pyobject; |
563 | + XShmSegmentInfo segmentInfo; |
564 | + XImage *image; |
565 | +} ImageObject; |
566 | + |
567 | + |
568 | +static inline Display * |
569 | +get_display(ImageObject *self) { |
570 | + return self->display_pyobject->event_display; |
571 | +} |
572 | + |
573 | +static bool |
574 | +Image_init_shared_memory(ImageObject *self) { |
575 | + self->segmentInfo.shmid = shmget( |
576 | + IPC_PRIVATE, |
577 | + self->buffer_size, |
578 | + IPC_CREAT | 0600); |
579 | + return self->segmentInfo.shmid != INVALID_SHM_ID; |
580 | +} |
581 | + |
582 | +static bool |
583 | +Image_map_shared_memory(ImageObject *self) { |
584 | + // Map the shared memory segment into the address space of this process |
585 | + self->segmentInfo.shmaddr = (char*)shmat(self->segmentInfo.shmid, 0, 0); |
586 | + |
587 | + if (self->segmentInfo.shmaddr != INVALID_SHM_ADDRESS) { |
588 | + self->segmentInfo.readOnly = true; |
589 | + // Mark the shared memory segment for removal |
590 | + // It will be removed even if this program crashes |
591 | + shmctl(self->segmentInfo.shmid, IPC_RMID, 0); |
592 | + return true; |
593 | + } |
594 | + |
595 | + return false; |
596 | +} |
597 | + |
598 | +static bool |
599 | +Image_create_shared_image(ImageObject *self) { |
600 | + Display *display = get_display(self); |
601 | + int screen = XDefaultScreen(display); |
602 | + // Allocate the memory needed for the XImage structure |
603 | + self->image = XShmCreateImage( |
604 | + display, XDefaultVisual(display, screen), |
605 | + DefaultDepth(display, screen), ZPixmap, 0, |
606 | + &self->segmentInfo, 0, 0); |
607 | + |
608 | + if (self->image) { |
609 | + self->image->data = (char*)self->segmentInfo.shmaddr; |
610 | + self->image->width = self->width; |
611 | + self->image->height = self->height; |
612 | + |
613 | + // Ask the X server to attach the shared memory segment and sync |
614 | + XShmAttach(display, &self->segmentInfo); |
615 | + XFlush(display); |
616 | + return true; |
617 | + } |
618 | + return false; |
619 | +} |
620 | + |
621 | +static void |
622 | +Image_destroy_shared_image(ImageObject *self) { |
623 | + if (self->image) { |
624 | + XShmDetach(get_display(self), &self->segmentInfo); |
625 | + XDestroyImage(self->image); |
626 | + self->image = NULL; |
627 | + } |
628 | +} |
629 | + |
630 | +static void |
631 | +Image_free_shared_memory(ImageObject *self) { |
632 | + if(self->segmentInfo.shmaddr != INVALID_SHM_ADDRESS) { |
633 | + shmdt(self->segmentInfo.shmaddr); |
634 | + self->segmentInfo.shmaddr = INVALID_SHM_ADDRESS; |
635 | + } |
636 | +} |
637 | + |
638 | +static void |
639 | +Image_finalise(ImageObject *self) { |
640 | + Image_destroy_shared_image(self); |
641 | + Image_free_shared_memory(self); |
642 | + Py_CLEAR(self->display_pyobject); |
643 | +} |
644 | + |
645 | +static int |
646 | +Image_init(ImageObject *self, PyObject *args, PyObject *kwds) { |
647 | + static char *kwlist[] = {"display", "width", "height", NULL}; |
648 | + PyObject *display_pyobject; |
649 | + |
650 | + if (!PyArg_ParseTupleAndKeywords( |
651 | + args, kwds, "O!ii", kwlist, |
652 | + &DisplayType, &display_pyobject, |
653 | + &self->width, &self->height)) { |
654 | + Py_INIT_RETURN_ERROR; |
655 | + } |
656 | + |
657 | + if (self->display_pyobject) { |
658 | + Image_finalise(self); |
659 | + } |
660 | + |
661 | + Py_INCREF(display_pyobject); |
662 | + self->display_pyobject = (DisplayObject*)display_pyobject; |
663 | + self->buffer_size = self->width * self->height * BYTES_PER_PIXEL; |
664 | + |
665 | + if (!Image_init_shared_memory(self)) { |
666 | + raiseInit(OSError, "could not init shared memory"); |
667 | + } |
668 | + |
669 | + if (!Image_map_shared_memory(self)) { |
670 | + raiseInit(OSError, "could not map shared memory"); |
671 | + } |
672 | + |
673 | + if (!Image_create_shared_image(self)) { |
674 | + Image_free_shared_memory(self); |
675 | + raiseInit(OSError, "could not allocate the XImage structure"); |
676 | + } |
677 | +[41m |
678 | + Py_INIT_RETURN_SUCCESS; |
679 | +} |
680 | + |
681 | +static void |
682 | +Image_dealloc(ImageObject *self) { |
683 | + Image_finalise(self); |
684 | + Py_TYPE(self)->tp_free((PyObject*)self); |
685 | +} |
686 | + |
687 | +static PyObject * |
688 | +Image_copy_to(ImageObject *self, PyObject *args, PyObject *kwds) { |
689 | + // draws the image on the surface at x, y |
690 | + static char *kwlist[] = {"drawable", "x", "y", "width", "height", NULL}; |
691 | + Drawable surface; |
692 | + GC gc; |
693 | + int x, y; |
694 | + unsigned int width, height; |
695 | + Display *display = get_display(self); |
696 | + |
697 | + if (!PyArg_ParseTupleAndKeywords( |
698 | + args, kwds, "kiiII", kwlist, |
699 | + &surface, &x, &y, &width, &height)) { |
700 | + Py_RETURN_ERROR; |
701 | + } |
702 | + |
703 | + gc = XCreateGC(display, surface, 0, NULL); |
704 | + XShmPutImage(display, surface, gc, |
705 | + self->image, 0, 0, |
706 | + x, y, width, height, false); |
707 | + XFreeGC(display, gc); |
708 | + |
709 | + Py_RETURN_NONE; |
710 | +} |
711 | + |
712 | +static PyObject * |
713 | +Image_draw(ImageObject *self, PyObject *args, PyObject *kwds) { |
714 | + // puts the pixels on the image at x, y |
715 | + static char *kwlist[] = {"x", "y", "width", "height", "pixels", NULL}; |
716 | + int offset_x, offset_y; |
717 | + int width, height; |
718 | + int pixels_per_row; |
719 | + int source_pixels_per_row; |
720 | + int destination_pixels_per_row; |
721 | + int destination_offset_x_bytes; |
722 | + char *pixels; |
723 | + Py_ssize_t pixels_size; |
724 | + |
725 | + if (!PyArg_ParseTupleAndKeywords( |
726 | + args, kwds, "iiiis#", kwlist, |
727 | + &offset_x, &offset_y, &width, &height, |
728 | + &pixels, &pixels_size)) { |
729 | + Py_RETURN_ERROR; |
730 | + } |
731 | + |
732 | + Py_BEGIN_ALLOW_THREADS |
733 | + destination_offset_x_bytes = max(0, offset_x) * BYTES_PER_PIXEL; |
734 | + source_pixels_per_row = width * BYTES_PER_PIXEL; |
735 | + destination_pixels_per_row = self->width * BYTES_PER_PIXEL; |
736 | + pixels_per_row = min(width + min(offset_x, 0), self->width - max(offset_x, 0)) * BYTES_PER_PIXEL; |
737 | + |
738 | + if (offset_x + width > 0 && offset_x < self->width) { |
739 | + // < 0 -> start y = 0, min(surface.height, height - abs(offset)) |
740 | + // > 0 -> start y = offset, height = min(surface.height, height + offset) |
741 | + for (int y = max(0, offset_y); y < min(self->height, height + offset_y); y++) { |
742 | + // < 0 -> first row = abs(offset) => n row = y + abs(offset) |
743 | + // > 0 -> first row = - offset => n row = y - offset |
744 | + // => n row = y - offset |
745 | + int pixels_y = y - offset_y; |
746 | + void *destination = |
747 | + self->image->data + y * destination_pixels_per_row |
748 | + + destination_offset_x_bytes; |
749 | + void *source = pixels + pixels_y * source_pixels_per_row; |
750 | + |
751 | + if (! ((uintptr_t)self->image->data <= (uintptr_t)destination)) { |
752 | + raise(AssertionError, |
753 | + "The destination start address calculation went wrong.\n" |
754 | + "It points to an address which is before the start address of the buffer.\n" |
755 | + "%p not smaller than %p", |
756 | + self->image->data, destination); |
757 | + } |
758 | + if (! ((uintptr_t)destination + pixels_per_row |
759 | + <= (uintptr_t)self->image->data + self->buffer_size)) { |
760 | + raise(AssertionError, |
761 | + "The destination end address calculation went wrong.\n" |
762 | + "It points to an address which is after the end address of the buffer.\n" |
763 | + "%p not smaller than %p", |
764 | + destination + pixels_per_row, |
765 | + self->image->data + self->buffer_size); |
766 | + } |
767 | + if (! ((uintptr_t)pixels <= (uintptr_t)source)) { |
768 | + raise(AssertionError, |
769 | + "The source start address calculation went wrong.\n" |
770 | + "It points to an address which is before the start address of the buffer.\n" |
771 | + "%p not smaller than %p", |
772 | + pixels, source); |
773 | + } |
774 | + if (! ((uintptr_t)source + pixels_per_row |
775 | + <= (uintptr_t)pixels + pixels_size)) { |
776 | + raise(AssertionError, |
777 | + "The source end address calculation went wrong.\n" |
778 | + "It points to an address which is after the end address of the buffer." |
779 | + "%p not smaller than %p", |
780 | + source + pixels_per_row, |
781 | + pixels + pixels_size); |
782 | + } |
783 | + |
784 | + memcpy(destination, source, pixels_per_row); |
785 | + } |
786 | + } |
787 | + Py_END_ALLOW_THREADS |
788 | + |
789 | + Py_RETURN_NONE; |
790 | +} |
791 | + |
792 | +static PyMethodDef Image_methods[] = { |
793 | + {"copy_to", (PyCFunction)Image_copy_to, |
794 | + METH_VARARGS | METH_KEYWORDS, |
795 | + "Draws the image on the surface at the passed coordinate.\n" |
796 | + "\n" |
797 | + "Args:\n" |
798 | + " drawable (int): the surface to draw on\n" |
799 | + " x (int): the x position where this image should be placed\n" |
800 | + " y (int): the y position where this image should be placed\n" |
801 | + " width (int): the width of the area\n" |
802 | + " which should be copied to the drawable\n" |
803 | + " height (int): the height of the area\n" |
804 | + " which should be copied to the drawable"}, |
805 | + {"draw", (PyCFunction)Image_draw, |
806 | + METH_VARARGS | METH_KEYWORDS, |
807 | + "Places the pixels on the image at the passed coordinate.\n" |
808 | + "\n" |
809 | + "Args:\n" |
810 | + " x (int): the x position where the pixels should be placed\n" |
811 | + " y (int): the y position where the pixels should be placed\n" |
812 | + " width (int): amount of pixels per row in the passed data\n" |
813 | + " height (int): amount of pixels per column in the passed data\n" |
814 | + " pixels (bytes): the pixels to place on the image"}, |
815 | + {NULL} /* Sentinel */ |
816 | +}; |
817 | + |
818 | +PyTypeObject ImageType = { |
819 | + PyVarObject_HEAD_INIT(NULL, 0) |
820 | + .tp_name = "lfpreviewer.X.Image", |
821 | + .tp_doc =[41m |
822 | + "An shared memory X11 Image\n" |
823 | + "\n" |
824 | + "Args:\n" |
825 | + " display (lfpreviewer.X.Display): the X11 display\n" |
826 | + " width (int): the width of this image\n" |
827 | + " height (int): the height of this image", |
828 | + .tp_basicsize = sizeof(ImageObject), |
829 | + .tp_itemsize = 0, |
830 | + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, |
831 | + .tp_new = PyType_GenericNew, |
832 | + .tp_init = (initproc)Image_init, |
833 | + .tp_dealloc = (destructor) Image_dealloc, |
834 | + .tp_methods = Image_methods, |
835 | +}; |
836 | diff --git a/BUILD/.pkg/lfpreviewer/lfpreviewer/X/Xshm.h b/BUILD/.pkg/lfpreviewer/lfpreviewer/X/Xshm.h |
837 | new file mode 100644 |
838 | index 0000000..ab61b4d |
839 | --- /dev/null |
840 | +++ b/BUILD/.pkg/lfpreviewer/lfpreviewer/X/Xshm.h |
841 | @@ -0,0 +1,7 @@ |
842 | +#ifndef __XSHM_H__ |
843 | +#define __XSHM_H__ |
844 | +#include "python.h" |
845 | + |
846 | + |
847 | +extern PyTypeObject ImageType; |
848 | +#endif |
849 | diff --git a/BUILD/.pkg/lfpreviewer/lfpreviewer/X/display.c b/BUILD/.pkg/lfpreviewer/lfpreviewer/X/display.c |
850 | new file mode 100644 |
851 | index 0000000..c9e4eee |
852 | --- /dev/null |
853 | +++ b/BUILD/.pkg/lfpreviewer/lfpreviewer/X/display.c |
854 | @@ -0,0 +1,276 @@ |
855 | +#include "python.h" |
856 | + |
857 | +#include <X11/Xlib.h> |
858 | +#include <X11/extensions/XRes.h> |
859 | +#include <X11/extensions/XShm.h> |
860 | + |
861 | +#include "util.h" |
862 | +#include "display.h" |
863 | + |
864 | + |
865 | +#define INVALID_PID (pid_t)-1 |
866 | + |
867 | + |
868 | +#define REOPEN_DISPLAY(display) \ |
869 | + if (display != NULL) { \ |
870 | + XCloseDisplay(display); \ |
871 | + } \ |
872 | + display = XOpenDisplay(NULL); |
873 | + |
874 | +#define CLOSE_DISPLAY(display) \ |
875 | + if (display != NULL) { \ |
876 | + XCloseDisplay(display); \ |
877 | + display = NULL; \ |
878 | + } |
879 | + |
880 | + |
881 | +static int |
882 | +Display_init(DisplayObject *self, PyObject *args, PyObject *kwds) { |
883 | + // Two connections are opened as |
884 | + // a death lock can occur |
885 | + // if you listen for events |
886 | + // (this will happen in parallel in asyncio worker threads) |
887 | + // and request information (e.g. XGetGeometry) |
888 | + // simultaneously. |
889 | + REOPEN_DISPLAY(self->event_display); |
890 | + REOPEN_DISPLAY(self->info_display); |
891 | + |
892 | + if (self->event_display == NULL || |
893 | + self->info_display == NULL) { |
894 | + raiseInit(OSError, "could not open a connection to the X server"); |
895 | + } |
896 | + |
897 | + int _; |
898 | + if (!XResQueryExtension(self->info_display, &_, &_)) { |
899 | + raiseInit(OSError, "the extension XRes is required"); |
900 | + } |
901 | + |
902 | + if (!XShmQueryExtension(self->event_display)) { |
903 | + raiseInit(OSError, "the extension Xext is required"); |
904 | + } |
905 | + |
906 | + int screen = XDefaultScreen(self->info_display); |
907 | + self->screen_width = XDisplayWidth(self->info_display, screen); |
908 | + self->screen_height = XDisplayHeight(self->info_display, screen); |
909 | + self->bitmap_pad = XBitmapPad(self->info_display); |
910 | + self->bitmap_unit = XBitmapUnit(self->info_display); |
911 | + |
912 | + self->wm_class = XInternAtom(self->info_display, "WM_CLASS", False); |
913 | + self->wm_name = XInternAtom(self->info_display, "WM_NAME", False); |
914 | + self->wm_locale_name = XInternAtom(self->info_display, "WM_LOCALE_NAME", False); |
915 | + self->wm_normal_hints = XInternAtom(self->info_display, "WM_NORMAL_HINTS", False); |
916 | + |
917 | + Py_INIT_RETURN_SUCCESS; |
918 | +} |
919 | + |
920 | +static void |
921 | +Display_dealloc(DisplayObject *self) { |
922 | + CLOSE_DISPLAY(self->event_display); |
923 | + CLOSE_DISPLAY(self->info_display); |
924 | + Py_TYPE(self)->tp_free((PyObject*)self); |
925 | +} |
926 | + |
927 | + |
928 | +static int |
929 | +has_property(DisplayObject *self, Window window, Atom property) { |
930 | + Atom actual_type_return; |
931 | + int actual_format_return; |
932 | + unsigned long bytes_after_return; |
933 | + unsigned char* prop_to_return = NULL; |
934 | + unsigned long nitems_return; |
935 | + |
936 | + int status = XGetWindowProperty( |
937 | + self->info_display, window, property, 0, |
938 | + 0L, False, |
939 | + AnyPropertyType, |
940 | + &actual_type_return, |
941 | + &actual_format_return, |
942 | + &nitems_return, &bytes_after_return, &prop_to_return); |
943 | + if (status == Success && prop_to_return) { |
944 | + XFree(prop_to_return); |
945 | + } |
946 | + return status == Success && !(actual_type_return == None && actual_format_return == 0); |
947 | +} |
948 | + |
949 | + |
950 | +static PyObject * |
951 | +Display_get_child_window_ids(DisplayObject *self, PyObject *args, PyObject *kwds) { |
952 | + static char *kwlist[] = {"parent_id", NULL}; |
953 | + Window parent = XDefaultRootWindow(self->info_display); |
954 | + Window _, *children; |
955 | + unsigned int children_count; |
956 | + |
957 | + if (!PyArg_ParseTupleAndKeywords( |
958 | + args, kwds, "|k", kwlist, |
959 | + &parent)) { |
960 | + Py_RETURN_ERROR; |
961 | + } |
962 | + |
963 | + if (!XQueryTree( |
964 | + self->info_display, parent, |
965 | + &_, &_, &children, &children_count)) { |
966 | + raise(OSError, "failed to query child windows of %lu", parent); |
967 | + } |
968 | + |
969 | + PyObject *child_ids = PyList_New(0); |
970 | + if (children) { |
971 | + for (unsigned int i = 0; i < children_count; i++) { |
972 | + // assume that windows without essential properties |
973 | + // like the window title aren't shown to the user |
974 | + int is_helper_window = ( |
975 | + !has_property(self, children[i], self->wm_class) && |
976 | + !has_property(self, children[i], self->wm_name) && |
977 | + !has_property(self, children[i], self->wm_locale_name) && |
978 | + !has_property(self, children[i], self->wm_normal_hints)); |
979 | + if (is_helper_window) { |
980 | + continue; |
981 | + } |
982 | + PyObject *py_window_id = Py_BuildValue("k", children[i]); |
983 | + PyList_Append(child_ids, py_window_id); |
984 | + Py_XDECREF(py_window_id); |
985 | + } |
986 | + XFree(children); |
987 | + } |
988 | + |
989 | + return child_ids; |
990 | +} |
991 | + |
992 | +static PyObject * |
993 | +Display_get_window_pid(DisplayObject *self, PyObject *args, PyObject *kwds) { |
994 | + static char *kwlist[] = {"window_id", NULL}; |
995 | + Window window; |
996 | + long num_ids; |
997 | + int num_specs = 1; |
998 | + XResClientIdValue *client_ids; |
999 | + XResClientIdSpec client_specs[1]; |