Port full MIME type guessing to Go

This commit is contained in:
Kovid Goyal 2023-03-17 11:51:05 +05:30
parent 3c550bcd28
commit bf1f0c00f4
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 46 additions and 9 deletions

View File

@ -4,6 +4,7 @@
import bz2 import bz2
import io import io
import json import json
import kitty.constants as kc
import os import os
import re import re
import struct import struct
@ -13,27 +14,24 @@ import tarfile
from contextlib import contextmanager, suppress from contextlib import contextmanager, suppress
from functools import lru_cache from functools import lru_cache
from itertools import chain from itertools import chain
from typing import Any, BinaryIO, Dict, Iterator, List, Optional, Sequence, Set, TextIO, Tuple, Union
import kitty.constants as kc
from kittens.tui.operations import Mode from kittens.tui.operations import Mode
from kittens.tui.spinners import spinners from kittens.tui.spinners import spinners
from kitty.cli import ( from kitty.cli import (
CompletionSpec, CompletionSpec, GoOption, go_options_for_seq, parse_option_spec,
GoOption,
go_options_for_seq,
parse_option_spec,
serialize_as_go_string, serialize_as_go_string,
) )
from kitty.conf.generate import gen_go_code from kitty.conf.generate import gen_go_code
from kitty.conf.types import Definition from kitty.conf.types import Definition
from kitty.guess_mime_type import text_mimes from kitty.guess_mime_type import known_extensions, text_mimes
from kitty.key_encoding import config_mod_map from kitty.key_encoding import config_mod_map
from kitty.key_names import character_key_name_aliases, functional_key_name_aliases from kitty.key_names import character_key_name_aliases, functional_key_name_aliases
from kitty.options.types import Options from kitty.options.types import Options
from kitty.rc.base import RemoteCommand, all_command_names, command_for_name from kitty.rc.base import RemoteCommand, all_command_names, command_for_name
from kitty.remote_control import global_options_spec from kitty.remote_control import global_options_spec
from kitty.rgb import color_names from kitty.rgb import color_names
from typing import (
Any, BinaryIO, Dict, Iterator, List, Optional, Sequence, Set, TextIO, Tuple, Union,
)
changed: List[str] = [] changed: List[str] = []
@ -673,6 +671,10 @@ def generate_textual_mimetypes() -> str:
for k in text_mimes: for k in text_mimes:
ans.append(f' "{serialize_as_go_string(k)}": true,') ans.append(f' "{serialize_as_go_string(k)}": true,')
ans.append('}') ans.append('}')
ans.append('var KnownExtensions = map[string]string{')
for k, v in known_extensions.items():
ans.append(f' ".{serialize_as_go_string(k)}": "{serialize_as_go_string(v)}",')
ans.append('}')
return '\n'.join(ans) return '\n'.join(ans)

View File

@ -11,6 +11,8 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"golang.org/x/sys/unix"
) )
var _ = fmt.Print var _ = fmt.Print
@ -52,6 +54,11 @@ var UserMimeMap = (&Once[map[string]string]{Run: func() map[string]string {
return ans return ans
}}).Get }}).Get
func is_rcfile(path string) bool {
name := filepath.Base(path)
return strings.HasSuffix(name, "rc") && !strings.Contains(name, ".")
}
func GuessMimeType(filename string) string { func GuessMimeType(filename string) string {
ext := filepath.Ext(filename) ext := filepath.Ext(filename)
mime_with_parameters := UserMimeMap()[ext] mime_with_parameters := UserMimeMap()[ext]
@ -62,7 +69,14 @@ func GuessMimeType(filename string) string {
only_once.Do(set_builtins) only_once.Do(set_builtins)
mime_with_parameters = builtin_types_map[ext] mime_with_parameters = builtin_types_map[ext]
if mime_with_parameters == "" { if mime_with_parameters == "" {
mime_with_parameters = builtin_types_map[strings.ToLower(ext)] lext := strings.ToLower(ext)
mime_with_parameters = builtin_types_map[lext]
if mime_with_parameters == "" {
mime_with_parameters = KnownExtensions[lext]
}
if mime_with_parameters == "" && is_rcfile(filename) {
mime_with_parameters = "text/plain"
}
if mime_with_parameters == "" { if mime_with_parameters == "" {
return "" return ""
} }
@ -74,3 +88,24 @@ func GuessMimeType(filename string) string {
} }
return ans return ans
} }
func GuessMimeTypeWithFileSystemAccess(filename string) string {
is_dir, is_exe := false, false
s, err := os.Stat(filename)
if err == nil {
is_dir = s.IsDir()
if !is_dir && s.Mode().Perm()&0o111 != 0 && unix.Access(filename, unix.X_OK) == nil {
is_exe = true
}
}
if is_dir {
return "inode/directory"
}
mt := GuessMimeType(filename)
if mt == "" {
if is_exe {
mt = "inode/executable"
}
}
return mt
}