Implement MIME aliases for clipboard
This commit is contained in:
parent
a622a149f6
commit
6422b323c6
@ -25,6 +25,16 @@ can be detected. If more than one file is specified, this option should be speci
|
||||
times, once for each specified file.
|
||||
|
||||
|
||||
--alias -a
|
||||
type=list
|
||||
Specify aliases for MIME types. Aliased MIME types are considered equivalent.
|
||||
When copying to clipboard both the original and alias are made available on the
|
||||
clipboard. When copying from clipboard if the original is not found, the alias
|
||||
is used, as a fallback. Can be specified multiple times to create multiple
|
||||
aliases. For example: :code:`--alias text/plain=text/x-rst` makes :code:`text/plain` an alias
|
||||
of :code:`text/rst`. Aliases are not used in filter mode.
|
||||
|
||||
|
||||
--wait-for-completion
|
||||
type=bool-set
|
||||
Wait till the copy to clipboard is complete before exiting. Useful if running
|
||||
|
||||
@ -239,6 +239,7 @@ class WriteRequest:
|
||||
self.currently_writing_mime = ''
|
||||
self.current_leftover_bytes = memoryview(b'')
|
||||
self.max_size = (get_options().clipboard_max_size * 1024 * 1024) if max_size < 0 else max_size
|
||||
self.aliases: Dict[str, str] = {}
|
||||
self.commited = False
|
||||
|
||||
def encode_response(self, status: str = 'OK') -> bytes:
|
||||
@ -254,6 +255,10 @@ class WriteRequest:
|
||||
self.commited = True
|
||||
cp = get_boss().primary_selection if self.is_primary_selection else get_boss().clipboard
|
||||
if cp.enabled:
|
||||
for alias, src in self.aliases.items():
|
||||
pos = self.mime_map.get(src)
|
||||
if pos is not None:
|
||||
self.mime_map[alias] = pos
|
||||
x = {mime: self.tempfile.create_chunker(pos.start, pos.size) for mime, pos in self.mime_map.items()}
|
||||
cp.set_mime(x)
|
||||
|
||||
@ -346,6 +351,13 @@ class ClipboardRequestManager:
|
||||
protocol_type=ProtocolType.osc_5522, id=sanitize_id(m.get('id', ''))
|
||||
)
|
||||
self.handle_write_request(self.in_flight_write_request)
|
||||
elif typ == 'walias':
|
||||
wr = self.in_flight_write_request
|
||||
mime = m.get('mime', '')
|
||||
if mime and wr is not None:
|
||||
aliases = base64.standard_b64decode(epayload).decode('utf-8').split()
|
||||
for alias in aliases:
|
||||
wr.aliases[alias] = mime
|
||||
elif typ == 'wdata':
|
||||
wr = self.in_flight_write_request
|
||||
w = get_boss().window_id_map.get(self.window_id)
|
||||
|
||||
@ -139,14 +139,22 @@ func (self *Output) commit() {
|
||||
self.dest = nil
|
||||
}
|
||||
|
||||
func (self *Output) assign_mime_type(available_mimes []string) (err error) {
|
||||
func (self *Output) assign_mime_type(available_mimes []string, aliases map[string][]string) (err error) {
|
||||
if self.mime_type == "." {
|
||||
self.remote_mime_type = "."
|
||||
return
|
||||
}
|
||||
if utils.Contains(available_mimes, self.mime_type) {
|
||||
self.remote_mime_type = self.mime_type
|
||||
return
|
||||
}
|
||||
if self.mime_type == "." {
|
||||
self.remote_mime_type = "."
|
||||
return
|
||||
if len(aliases[self.mime_type]) > 0 {
|
||||
for _, alias := range aliases[self.mime_type] {
|
||||
if utils.Contains(available_mimes, alias) {
|
||||
self.remote_mime_type = alias
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if images.EncodableImageTypes[self.mime_type] {
|
||||
for _, mt := range available_mimes {
|
||||
@ -242,6 +250,19 @@ func parse_escape_code(etype loop.EscapeCodeType, data []byte) (metadata map[str
|
||||
return
|
||||
}
|
||||
|
||||
func parse_aliases(raw []string) (map[string][]string, error) {
|
||||
ans := make(map[string][]string, len(raw))
|
||||
for _, x := range raw {
|
||||
k, v, found := utils.Cut(x, "=")
|
||||
if !found {
|
||||
return nil, fmt.Errorf("%s is not valid MIME alias specification", x)
|
||||
}
|
||||
ans[k] = append(ans[k], v)
|
||||
ans[v] = append(ans[v], k)
|
||||
}
|
||||
return ans, nil
|
||||
}
|
||||
|
||||
func run_get_loop(opts *Options, args []string) (err error) {
|
||||
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
|
||||
if err != nil {
|
||||
@ -253,6 +274,10 @@ func run_get_loop(opts *Options, args []string) (err error) {
|
||||
requested_mimes := make(map[string]*Output)
|
||||
reading_available_mimes := true
|
||||
outputs := make([]*Output, len(args))
|
||||
aliases, merr := parse_aliases(opts.Alias)
|
||||
if merr != nil {
|
||||
return merr
|
||||
}
|
||||
|
||||
for i, arg := range args {
|
||||
outputs[i] = &Output{arg: arg, arg_is_stream: arg == "/dev/stdout" || arg == "/dev/stderr", ext: filepath.Ext(arg)}
|
||||
@ -301,7 +326,7 @@ func run_get_loop(opts *Options, args []string) (err error) {
|
||||
return fmt.Errorf("The clipboard is empty")
|
||||
}
|
||||
for _, o := range outputs {
|
||||
err = o.assign_mime_type(available_mimes)
|
||||
err = o.assign_mime_type(available_mimes, aliases)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"kitty/tools/tui/loop"
|
||||
"kitty/tools/utils"
|
||||
@ -23,13 +24,17 @@ type Input struct {
|
||||
mime_type string
|
||||
}
|
||||
|
||||
func write_loop(inputs []*Input) (err error) {
|
||||
func write_loop(inputs []*Input, opts *Options) (err error) {
|
||||
lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var waiting_for_write loop.IdType
|
||||
var buf [4096]byte
|
||||
aliases, aerr := parse_aliases(opts.Alias)
|
||||
if aerr != nil {
|
||||
return aerr
|
||||
}
|
||||
|
||||
lp.OnInitialize = func() (string, error) {
|
||||
waiting_for_write = lp.QueueWriteString(encode(map[string]string{"type": "write"}, ""))
|
||||
@ -47,6 +52,9 @@ func write_loop(inputs []*Input) (err error) {
|
||||
}
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
if len(aliases[i.mime_type]) > 0 {
|
||||
lp.QueueWriteString(encode(map[string]string{"type": "walias", "mime": i.mime_type}, strings.Join(aliases[i.mime_type], " ")))
|
||||
}
|
||||
inputs = inputs[1:]
|
||||
if len(inputs) == 0 {
|
||||
lp.QueueWriteString(encode(map[string]string{"type": "wdata"}, ""))
|
||||
@ -151,5 +159,5 @@ func run_set_loop(opts *Options, args []string) (err error) {
|
||||
}
|
||||
to_process[i] = inputs[i]
|
||||
}
|
||||
return write_loop(to_process)
|
||||
return write_loop(to_process, opts)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user