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
|
#+TITLE: DUET — Dual-Pane File Commander for Emacs
DUET is a two-pane orthodox file manager (Midnight Commander / FileZilla
style) built on dirvish/dired. Two dired panes each show any location —
local or remote — and single-key actions on the file under point use the
opposite pane as the implied target: copy, move, delete, open. The name is
recursive: *DUET Unifies Endpoint Trees*.
*Status: pre-alpha.* The interaction model and architecture are designed;
implementation is staged (below). This repository is the skeleton.
* Why DUET
Two dirvish windows already approximate the basics. DUET's durable value is
transport reach and a community-extensible backend interface — moving files
dired cannot, through one consistent two-pane UX.
* The transport quartet
DUET ships four transfer utilities as backends, over TRAMP as the
Emacs-native substrate. They do not overlap:
- *rsync* — Unix-to-Unix and local. Block-level delta-transfer, zero remote
install, faithful Unix metadata. The default for an ssh-reachable host.
- *rclone* — cloud and object stores plus the long protocol tail (S3, B2,
GDrive, WebDAV, ...). The reach rsync lacks.
- *lftp* — FTP/FTPS/HTTP with mirroring, parallel transfers, queueing.
- *unison* — bidirectional, conflict-aware reconciliation.
One line: rclone is breadth, rsync is depth.
* Roadmap
- *Stage 1* — core commander: two-pane UX, connection wizard, rsync + TRAMP
transport, copy/move/delete/open, the keybinding scheme.
- *Stage 2* — the backend registry plus rclone and lftp. The differentiator.
- *Stage 3* — directory diff and bidirectional sync (ediff for files;
unison / rclone bisync for trees).
* Extending DUET
Transports are pluggable. A backend registers via =duet-register-backend=
with:
- a *name*;
- a *handles* predicate =(lambda (src dst) ...)= returning a numeric score
(lower preferred) or nil if it cannot handle the endpoint pair;
- a *command* builder =(lambda (src dst opts) ...)= returning a process spec;
- *capability* flags: =:async :resume :bidirectional :progress=.
=duet--transfer-spec= asks every registered backend to score an endpoint
pair and picks the lowest-cost handler. The built-in backends register
through this same API, so third parties add transports (unison, git-annex,
or anything else) without patching core.
* License
GPL-3.0-or-later.
|