mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-24 06:19:37 +00:00
Start rebuilding with a cleanly-separated UI framework
This commit is contained in:
commit
b400449a58
13 changed files with 1863 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
.DS_Store
|
938
Cargo.lock
generated
Normal file
938
Cargo.lock
generated
Normal file
|
@ -0,0 +1,938 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
|
||||
dependencies = [
|
||||
"concurrent-queue",
|
||||
"event-listener",
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-executor"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146"
|
||||
dependencies = [
|
||||
"async-task",
|
||||
"concurrent-queue",
|
||||
"fastrand",
|
||||
"futures-lite",
|
||||
"once_cell",
|
||||
"vec-arena",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-fs"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b3ca4f8ff117c37c278a2f7415ce9be55560b846b5bc4412aaa5d29c1c3dae2"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"blocking",
|
||||
"futures-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd"
|
||||
dependencies = [
|
||||
"concurrent-queue",
|
||||
"fastrand",
|
||||
"futures-lite",
|
||||
"libc",
|
||||
"log",
|
||||
"nb-connect",
|
||||
"once_cell",
|
||||
"parking",
|
||||
"polling",
|
||||
"vec-arena",
|
||||
"waker-fn",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1996609732bde4a9988bc42125f55f2af5f3c36370e27c778d5191a4a1b63bfb"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-net"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06de475c85affe184648202401d7622afb32f0f74e02192857d0201a16defbe5"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"blocking",
|
||||
"fastrand",
|
||||
"futures-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-process"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef37b86e2fa961bae5a4d212708ea0154f904ce31d1a4a7f47e1bbc33a0c040b"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"blocking",
|
||||
"cfg-if 1.0.0",
|
||||
"event-listener",
|
||||
"futures-lite",
|
||||
"once_cell",
|
||||
"signal-hook",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "blocking"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-task",
|
||||
"atomic-waker",
|
||||
"fastrand",
|
||||
"futures-lite",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cache-padded"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"core-foundation",
|
||||
"core-graphics",
|
||||
"foreign-types 0.3.2",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa-foundation"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
"core-foundation",
|
||||
"core-graphics-types",
|
||||
"foreign-types 0.3.2",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
|
||||
dependencies = [
|
||||
"cache-padded",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.22.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "269f35f69b542b80e736a20a89a05215c0ce80c2c03c514abb2e318b78379d86"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-graphics-types",
|
||||
"foreign-types 0.3.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-types"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"foreign-types 0.3.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-text"
|
||||
version = "19.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"
|
||||
dependencies = [
|
||||
"core-foundation",
|
||||
"core-graphics",
|
||||
"foreign-types 0.3.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bae8f328835f8f5a6ceb6a7842a7f2d0c03692adb5c889347235d59194731fe3"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if 1.0.0",
|
||||
"lazy_static",
|
||||
"loom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "142995ed02755914747cc6ca76fc7e4583cd18578746716d0508ea6ed558b9ff"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "2.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared 0.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
|
||||
dependencies = [
|
||||
"foreign-types-macros",
|
||||
"foreign-types-shared 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-macros"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63f713f8b2aa9e24fec85b0e290c56caee12e3b6ae0aeeda238a75b28251afd6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7684cf33bb7f28497939e8c7cf17e3e4e3b8d9a0080ffa4f8ae2f515442ee855"
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65"
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
version = "1.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4481d0cd0de1d204a4fa55e7d45f07b1d958abcb06714b3446438e2eff695fb"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"memchr",
|
||||
"parking",
|
||||
"pin-project-lite",
|
||||
"waker-fn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generator"
|
||||
version = "0.6.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cdc09201b2e8ca1b19290cf7e65de2246b8e91fb6874279722189c4de7b94dc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"log",
|
||||
"rustc_version",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gpui"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cocoa",
|
||||
"core-foundation",
|
||||
"core-text",
|
||||
"foreign-types 0.5.0",
|
||||
"log",
|
||||
"metal",
|
||||
"objc",
|
||||
"pathfinder_color",
|
||||
"pathfinder_geometry",
|
||||
"smol",
|
||||
"tree-sitter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d44c73b4636e497b4917eb21c33539efa3816741a2d3ff26c6316f1b529481a4"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"generator",
|
||||
"scoped-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
|
||||
[[package]]
|
||||
name = "metal"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4598d719460ade24c7d91f335daf055bf2a7eec030728ce751814c50cdd6a26c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"foreign-types 0.3.2",
|
||||
"log",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb-connect"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670361df1bc2399ee1ff50406a0d422587dd3bb0da596e1978fe8e05dabddf4f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"socket2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
"objc_exception",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_exception"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
|
||||
|
||||
[[package]]
|
||||
name = "pathfinder_color"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69bdc0d277d559e35e1b374de56df9262a6b71e091ca04a8831a239f8c7f0c62"
|
||||
dependencies = [
|
||||
"pathfinder_simd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathfinder_geometry"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pathfinder_simd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathfinder_simd"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b451513912d6b3440e443aa75a73ab22203afedc4a90df8526d008c0f86f7cb3"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827"
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"log",
|
||||
"wepoll-sys",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"rust-argon2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"blake2b_simd",
|
||||
"constant_time_eq",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7f3f92a1da3d6b1d32245d0cbcbbab0cfc45996d8df619c42bccfa6d2bbb5f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simplelog"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bc0ffd69814a9b251d43afcabf96dad1b29f5028378056257be9e3fecc9f720"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"log",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smol"
|
||||
version = "1.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85cf3b5351f3e783c1d79ab5fc604eeed8b8ae9abd36b166e8b87a089efd85e4"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-executor",
|
||||
"async-fs",
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"async-net",
|
||||
"async-process",
|
||||
"blocking",
|
||||
"futures-lite",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d18dcb776d3affaba6db04d11d645946d34a69b3172e588af96ce9fecd20faac"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "vec-arena"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d"
|
||||
|
||||
[[package]]
|
||||
name = "waker-fn"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wepoll-sys"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "zed"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
"gpui",
|
||||
"libc",
|
||||
"log",
|
||||
"simplelog",
|
||||
]
|
2
Cargo.toml
Normal file
2
Cargo.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
[workspace]
|
||||
members = ["zed", "gpui"]
|
21
gpui/Cargo.toml
Normal file
21
gpui/Cargo.toml
Normal file
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
authors = ["Nathan Sobo <nathansobo@gmail.com>"]
|
||||
edition = "2018"
|
||||
name = "gpui"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
pathfinder_color = "0.5"
|
||||
pathfinder_geometry = "0.5"
|
||||
smol = "1.2"
|
||||
tree-sitter = "0.17"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
anyhow = "1"
|
||||
cocoa = "0.24"
|
||||
core-foundation = "0.9"
|
||||
core-text = "19.2"
|
||||
foreign-types = "0.5"
|
||||
log = "0.4"
|
||||
metal = "0.21"
|
||||
objc = "0.2"
|
502
gpui/src/keymap.rs
Normal file
502
gpui/src/keymap.rs
Normal file
|
@ -0,0 +1,502 @@
|
|||
use anyhow::anyhow;
|
||||
use std::{
|
||||
any::Any,
|
||||
collections::{HashMap, HashSet},
|
||||
};
|
||||
use tree_sitter::{Language, Node, Parser};
|
||||
|
||||
extern "C" {
|
||||
fn tree_sitter_zed_context_predicate() -> Language;
|
||||
}
|
||||
|
||||
pub struct Matcher {
|
||||
pending: HashMap<usize, Pending>,
|
||||
keymap: Keymap,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Pending {
|
||||
keystrokes: Vec<Keystroke>,
|
||||
context: Option<Context>,
|
||||
}
|
||||
|
||||
pub struct Keymap(Vec<Binding>);
|
||||
|
||||
pub struct Binding {
|
||||
keystrokes: Vec<Keystroke>,
|
||||
action: String,
|
||||
action_arg: Option<Box<dyn ActionArg>>,
|
||||
context: Option<ContextPredicate>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Keystroke {
|
||||
pub ctrl: bool,
|
||||
pub alt: bool,
|
||||
pub shift: bool,
|
||||
pub cmd: bool,
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Context {
|
||||
pub set: HashSet<String>,
|
||||
pub map: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
enum ContextPredicate {
|
||||
Identifier(String),
|
||||
Equal(String, String),
|
||||
NotEqual(String, String),
|
||||
Not(Box<ContextPredicate>),
|
||||
And(Box<ContextPredicate>, Box<ContextPredicate>),
|
||||
Or(Box<ContextPredicate>, Box<ContextPredicate>),
|
||||
}
|
||||
|
||||
trait ActionArg {
|
||||
fn boxed_clone(&self) -> Box<dyn Any>;
|
||||
}
|
||||
|
||||
impl<T> ActionArg for T
|
||||
where
|
||||
T: 'static + Any + Clone,
|
||||
{
|
||||
fn boxed_clone(&self) -> Box<dyn Any> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MatchResult {
|
||||
None,
|
||||
Pending,
|
||||
Action {
|
||||
name: String,
|
||||
arg: Option<Box<dyn Any>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Matcher {
|
||||
pub fn new(keymap: Keymap) -> Self {
|
||||
Self {
|
||||
pending: HashMap::new(),
|
||||
keymap,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_keymap(&mut self, keymap: Keymap) {
|
||||
self.pending.clear();
|
||||
self.keymap = keymap;
|
||||
}
|
||||
|
||||
pub fn add_bindings<T: IntoIterator<Item = Binding>>(&mut self, bindings: T) {
|
||||
self.pending.clear();
|
||||
self.keymap.add_bindings(bindings);
|
||||
}
|
||||
|
||||
pub fn push_keystroke(
|
||||
&mut self,
|
||||
keystroke: Keystroke,
|
||||
view_id: usize,
|
||||
ctx: &Context,
|
||||
) -> MatchResult {
|
||||
let pending = self.pending.entry(view_id).or_default();
|
||||
|
||||
if let Some(pending_ctx) = pending.context.as_ref() {
|
||||
if pending_ctx != ctx {
|
||||
pending.keystrokes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pending.keystrokes.push(keystroke);
|
||||
|
||||
let mut retain_pending = false;
|
||||
for binding in self.keymap.0.iter().rev() {
|
||||
if binding.keystrokes.starts_with(&pending.keystrokes)
|
||||
&& binding
|
||||
.context
|
||||
.as_ref()
|
||||
.map(|c| c.eval(ctx))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
if binding.keystrokes.len() == pending.keystrokes.len() {
|
||||
self.pending.remove(&view_id);
|
||||
return MatchResult::Action {
|
||||
name: binding.action.clone(),
|
||||
arg: binding.action_arg.as_ref().map(|arg| (*arg).boxed_clone()),
|
||||
};
|
||||
} else {
|
||||
retain_pending = true;
|
||||
pending.context = Some(ctx.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if retain_pending {
|
||||
MatchResult::Pending
|
||||
} else {
|
||||
self.pending.remove(&view_id);
|
||||
MatchResult::None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Matcher {
|
||||
fn default() -> Self {
|
||||
Self::new(Keymap::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Keymap {
|
||||
pub fn new(bindings: Vec<Binding>) -> Self {
|
||||
Self(bindings)
|
||||
}
|
||||
|
||||
fn add_bindings<T: IntoIterator<Item = Binding>>(&mut self, bindings: T) {
|
||||
self.0.extend(bindings.into_iter());
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Keymap {
|
||||
fn default() -> Self {
|
||||
Self(vec![
|
||||
Binding::new("up", "menu:select_prev", Some("menu")),
|
||||
Binding::new("ctrl-p", "menu:select_prev", Some("menu")),
|
||||
Binding::new("down", "menu:select_next", Some("menu")),
|
||||
Binding::new("ctrl-n", "menu:select_next", Some("menu")),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl Binding {
|
||||
pub fn new<S: Into<String>>(keystrokes: &str, action: S, context: Option<&str>) -> Self {
|
||||
let context = if let Some(context) = context {
|
||||
Some(ContextPredicate::parse(context).unwrap())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Self {
|
||||
keystrokes: keystrokes
|
||||
.split_whitespace()
|
||||
.map(|key| Keystroke::parse(key).unwrap())
|
||||
.collect(),
|
||||
action: action.into(),
|
||||
action_arg: None,
|
||||
context,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_arg<T: 'static + Any + Clone>(mut self, arg: T) -> Self {
|
||||
self.action_arg = Some(Box::new(arg));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Keystroke {
|
||||
pub fn parse(source: &str) -> anyhow::Result<Self> {
|
||||
let mut ctrl = false;
|
||||
let mut alt = false;
|
||||
let mut shift = false;
|
||||
let mut cmd = false;
|
||||
let mut key = None;
|
||||
|
||||
let mut components = source.split("-").peekable();
|
||||
while let Some(component) = components.next() {
|
||||
match component {
|
||||
"ctrl" => ctrl = true,
|
||||
"alt" => alt = true,
|
||||
"shift" => shift = true,
|
||||
"cmd" => cmd = true,
|
||||
_ => {
|
||||
if let Some(component) = components.peek() {
|
||||
if component.is_empty() && source.ends_with('-') {
|
||||
key = Some(String::from("-"));
|
||||
break;
|
||||
} else {
|
||||
return Err(anyhow!("Invalid keystroke `{}`", source));
|
||||
}
|
||||
} else {
|
||||
key = Some(String::from(component));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Keystroke {
|
||||
ctrl,
|
||||
alt,
|
||||
shift,
|
||||
cmd,
|
||||
key: key.unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Context {
|
||||
pub fn extend(&mut self, other: Context) {
|
||||
for v in other.set {
|
||||
self.set.insert(v);
|
||||
}
|
||||
for (k, v) in other.map {
|
||||
self.map.insert(k, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ContextPredicate {
|
||||
fn parse(source: &str) -> anyhow::Result<Self> {
|
||||
let mut parser = Parser::new();
|
||||
let language = unsafe { tree_sitter_zed_context_predicate() };
|
||||
parser.set_language(language).unwrap();
|
||||
let source = source.as_bytes();
|
||||
let tree = parser.parse(source, None).unwrap();
|
||||
Self::from_node(tree.root_node(), source)
|
||||
}
|
||||
|
||||
fn from_node(node: Node, source: &[u8]) -> anyhow::Result<Self> {
|
||||
let parse_error = "error parsing context predicate";
|
||||
let kind = node.kind();
|
||||
|
||||
match kind {
|
||||
"source" => Self::from_node(node.child(0).ok_or(anyhow!(parse_error))?, source),
|
||||
"identifier" => Ok(Self::Identifier(node.utf8_text(source)?.into())),
|
||||
"not" => {
|
||||
let child = Self::from_node(
|
||||
node.child_by_field_name("expression")
|
||||
.ok_or(anyhow!(parse_error))?,
|
||||
source,
|
||||
)?;
|
||||
Ok(Self::Not(Box::new(child)))
|
||||
}
|
||||
"and" | "or" => {
|
||||
let left = Box::new(Self::from_node(
|
||||
node.child_by_field_name("left")
|
||||
.ok_or(anyhow!(parse_error))?,
|
||||
source,
|
||||
)?);
|
||||
let right = Box::new(Self::from_node(
|
||||
node.child_by_field_name("right")
|
||||
.ok_or(anyhow!(parse_error))?,
|
||||
source,
|
||||
)?);
|
||||
if kind == "and" {
|
||||
Ok(Self::And(left, right))
|
||||
} else {
|
||||
Ok(Self::Or(left, right))
|
||||
}
|
||||
}
|
||||
"equal" | "not_equal" => {
|
||||
let left = node
|
||||
.child_by_field_name("left")
|
||||
.ok_or(anyhow!(parse_error))?
|
||||
.utf8_text(source)?
|
||||
.into();
|
||||
let right = node
|
||||
.child_by_field_name("right")
|
||||
.ok_or(anyhow!(parse_error))?
|
||||
.utf8_text(source)?
|
||||
.into();
|
||||
if kind == "equal" {
|
||||
Ok(Self::Equal(left, right))
|
||||
} else {
|
||||
Ok(Self::NotEqual(left, right))
|
||||
}
|
||||
}
|
||||
"parenthesized" => Self::from_node(
|
||||
node.child_by_field_name("expression")
|
||||
.ok_or(anyhow!(parse_error))?,
|
||||
source,
|
||||
),
|
||||
_ => Err(anyhow!(parse_error)),
|
||||
}
|
||||
}
|
||||
|
||||
fn eval(&self, ctx: &Context) -> bool {
|
||||
match self {
|
||||
Self::Identifier(name) => ctx.set.contains(name.as_str()),
|
||||
Self::Equal(left, right) => ctx
|
||||
.map
|
||||
.get(left)
|
||||
.map(|value| value == right)
|
||||
.unwrap_or(false),
|
||||
Self::NotEqual(left, right) => ctx
|
||||
.map
|
||||
.get(left)
|
||||
.map(|value| value != right)
|
||||
.unwrap_or(true),
|
||||
Self::Not(pred) => !pred.eval(ctx),
|
||||
Self::And(left, right) => left.eval(ctx) && right.eval(ctx),
|
||||
Self::Or(left, right) => left.eval(ctx) || right.eval(ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_keystroke_parsing() -> anyhow::Result<()> {
|
||||
assert_eq!(
|
||||
Keystroke::parse("ctrl-p")?,
|
||||
Keystroke {
|
||||
key: "p".into(),
|
||||
ctrl: true,
|
||||
alt: false,
|
||||
shift: false,
|
||||
cmd: false,
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Keystroke::parse("alt-shift-down")?,
|
||||
Keystroke {
|
||||
key: "down".into(),
|
||||
ctrl: false,
|
||||
alt: true,
|
||||
shift: true,
|
||||
cmd: false,
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Keystroke::parse("shift-cmd--")?,
|
||||
Keystroke {
|
||||
key: "-".into(),
|
||||
ctrl: false,
|
||||
alt: false,
|
||||
shift: true,
|
||||
cmd: true,
|
||||
}
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_context_predicate_parsing() -> anyhow::Result<()> {
|
||||
use ContextPredicate::*;
|
||||
|
||||
assert_eq!(
|
||||
ContextPredicate::parse("a && (b == c || d != e)")?,
|
||||
And(
|
||||
Box::new(Identifier("a".into())),
|
||||
Box::new(Or(
|
||||
Box::new(Equal("b".into(), "c".into())),
|
||||
Box::new(NotEqual("d".into(), "e".into())),
|
||||
))
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
ContextPredicate::parse("!a")?,
|
||||
Not(Box::new(Identifier("a".into())),)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_context_predicate_eval() -> anyhow::Result<()> {
|
||||
let predicate = ContextPredicate::parse("a && b || c == d")?;
|
||||
|
||||
let mut context = Context::default();
|
||||
context.set.insert("a".into());
|
||||
assert!(!predicate.eval(&context));
|
||||
|
||||
context.set.insert("b".into());
|
||||
assert!(predicate.eval(&context));
|
||||
|
||||
context.set.remove("b");
|
||||
context.map.insert("c".into(), "x".into());
|
||||
assert!(!predicate.eval(&context));
|
||||
|
||||
context.map.insert("c".into(), "d".into());
|
||||
assert!(predicate.eval(&context));
|
||||
|
||||
let predicate = ContextPredicate::parse("!a")?;
|
||||
assert!(predicate.eval(&Context::default()));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_matcher() -> anyhow::Result<()> {
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
struct ActionArg {
|
||||
a: &'static str,
|
||||
}
|
||||
|
||||
let keymap = Keymap(vec![
|
||||
Binding::new("a", "a", Some("a")).with_arg(ActionArg { a: "b" }),
|
||||
Binding::new("b", "b", Some("a")),
|
||||
Binding::new("a b", "a_b", Some("a || b")),
|
||||
]);
|
||||
|
||||
let mut ctx_a = Context::default();
|
||||
ctx_a.set.insert("a".into());
|
||||
|
||||
let mut ctx_b = Context::default();
|
||||
ctx_b.set.insert("b".into());
|
||||
|
||||
let mut matcher = Matcher::new(keymap);
|
||||
|
||||
// Basic match
|
||||
assert_eq!(
|
||||
matcher.test_keystroke("a", 1, &ctx_a),
|
||||
Some(("a".to_string(), Some(ActionArg { a: "b" })))
|
||||
);
|
||||
|
||||
// Multi-keystroke match
|
||||
assert_eq!(matcher.test_keystroke::<()>("a", 1, &ctx_b), None);
|
||||
assert_eq!(
|
||||
matcher.test_keystroke::<()>("b", 1, &ctx_b),
|
||||
Some(("a_b".to_string(), None))
|
||||
);
|
||||
|
||||
// Failed matches don't interfere with matching subsequent keys
|
||||
assert_eq!(matcher.test_keystroke::<()>("x", 1, &ctx_a), None);
|
||||
assert_eq!(
|
||||
matcher.test_keystroke("a", 1, &ctx_a),
|
||||
Some(("a".to_string(), Some(ActionArg { a: "b" })))
|
||||
);
|
||||
|
||||
// Pending keystrokes are cleared when the context changes
|
||||
assert_eq!(matcher.test_keystroke::<()>("a", 1, &ctx_b), None);
|
||||
assert_eq!(
|
||||
matcher.test_keystroke::<()>("b", 1, &ctx_a),
|
||||
Some(("b".to_string(), None))
|
||||
);
|
||||
|
||||
let mut ctx_c = Context::default();
|
||||
ctx_c.set.insert("c".into());
|
||||
|
||||
// Pending keystrokes are maintained per-view
|
||||
assert_eq!(matcher.test_keystroke::<()>("a", 1, &ctx_b), None);
|
||||
assert_eq!(matcher.test_keystroke::<()>("a", 2, &ctx_c), None);
|
||||
assert_eq!(
|
||||
matcher.test_keystroke::<()>("b", 1, &ctx_b),
|
||||
Some(("a_b".to_string(), None))
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Matcher {
|
||||
fn test_keystroke<A: Any + Clone>(
|
||||
&mut self,
|
||||
keystroke: &str,
|
||||
view_id: usize,
|
||||
ctx: &Context,
|
||||
) -> Option<(String, Option<A>)> {
|
||||
if let MatchResult::Action { name, arg } =
|
||||
self.push_keystroke(Keystroke::parse(keystroke).unwrap(), view_id, ctx)
|
||||
{
|
||||
Some((name, arg.and_then(|arg| arg.downcast_ref::<A>().cloned())))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5
gpui/src/lib.rs
Normal file
5
gpui/src/lib.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
pub mod keymap;
|
||||
pub mod platform;
|
||||
|
||||
pub use pathfinder_color as color;
|
||||
pub use pathfinder_geometry as geometry;
|
24
gpui/src/platform/event.rs
Normal file
24
gpui/src/platform/event.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
use crate::{geometry::vector::Vector2F, keymap::Keystroke};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Event {
|
||||
KeyDown {
|
||||
keystroke: Keystroke,
|
||||
chars: String,
|
||||
},
|
||||
ScrollWheel {
|
||||
position: Vector2F,
|
||||
delta: Vector2F,
|
||||
precise: bool,
|
||||
},
|
||||
LeftMouseDown {
|
||||
position: Vector2F,
|
||||
cmd: bool,
|
||||
},
|
||||
LeftMouseUp {
|
||||
position: Vector2F,
|
||||
},
|
||||
LeftMouseDragged {
|
||||
position: Vector2F,
|
||||
},
|
||||
}
|
176
gpui/src/platform/mac/app.rs
Normal file
176
gpui/src/platform/mac/app.rs
Normal file
|
@ -0,0 +1,176 @@
|
|||
use super::Event;
|
||||
pub use cocoa::foundation::NSSize;
|
||||
use cocoa::{
|
||||
base::{id, nil},
|
||||
foundation::{NSArray, NSAutoreleasePool, NSString},
|
||||
};
|
||||
use objc::{
|
||||
class,
|
||||
declare::ClassDecl,
|
||||
msg_send,
|
||||
runtime::{Class, Object, Sel},
|
||||
sel, sel_impl,
|
||||
};
|
||||
use std::{
|
||||
ffi::CStr,
|
||||
os::raw::{c_char, c_void},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct App {
|
||||
finish_launching_callback: Option<Box<dyn FnOnce()>>,
|
||||
become_active_callback: Option<Box<dyn FnMut()>>,
|
||||
resign_active_callback: Option<Box<dyn FnMut()>>,
|
||||
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
||||
open_files_callback: Option<Box<dyn FnMut(Vec<PathBuf>)>>,
|
||||
}
|
||||
|
||||
const RUST_WRAPPER_IVAR_NAME: &'static str = "rustWrapper";
|
||||
|
||||
impl super::App for App {
|
||||
fn on_finish_launching<F: 'static + FnOnce()>(mut self, callback: F) -> Self {
|
||||
self.finish_launching_callback = Some(Box::new(callback));
|
||||
self
|
||||
}
|
||||
|
||||
fn on_become_active<F: 'static + FnMut()>(mut self, callback: F) -> Self {
|
||||
self.become_active_callback = Some(Box::new(callback));
|
||||
self
|
||||
}
|
||||
|
||||
fn on_resign_active<F: 'static + FnMut()>(mut self, callback: F) -> Self {
|
||||
self.resign_active_callback = Some(Box::new(callback));
|
||||
self
|
||||
}
|
||||
|
||||
fn on_event<F: 'static + FnMut(Event) -> bool>(mut self, callback: F) -> Self {
|
||||
self.event_callback = Some(Box::new(callback));
|
||||
self
|
||||
}
|
||||
|
||||
fn on_open_files<F: 'static + FnMut(Vec<PathBuf>)>(mut self, callback: F) -> Self {
|
||||
self.open_files_callback = Some(Box::new(callback));
|
||||
self
|
||||
}
|
||||
|
||||
fn run(self) {
|
||||
unsafe {
|
||||
let self_ptr = Box::into_raw(Box::new(self));
|
||||
|
||||
let pool = NSAutoreleasePool::new(nil);
|
||||
let app: id = msg_send![build_app_class(), sharedApplication];
|
||||
(*app).set_ivar(RUST_WRAPPER_IVAR_NAME, self_ptr as *mut c_void);
|
||||
let app_delegate: id = msg_send![build_app_delegate_class(), new];
|
||||
(*app_delegate).set_ivar(RUST_WRAPPER_IVAR_NAME, self_ptr as *mut c_void);
|
||||
let _: () = msg_send![app, setDelegate: app_delegate];
|
||||
let _: () = msg_send![app, run];
|
||||
let _: () = msg_send![pool, drain];
|
||||
|
||||
// App is done running when we get here, so we can reinstantiate the Box and drop it.
|
||||
Box::from_raw(self_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_app_class() -> *const Class {
|
||||
unsafe {
|
||||
let mut decl = ClassDecl::new("GPUIApplication", class!(NSApplication)).unwrap();
|
||||
decl.add_ivar::<*mut c_void>(RUST_WRAPPER_IVAR_NAME);
|
||||
decl.add_method(
|
||||
sel!(sendEvent:),
|
||||
send_event as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.register()
|
||||
}
|
||||
}
|
||||
|
||||
fn build_app_delegate_class() -> *const Class {
|
||||
unsafe {
|
||||
let superclass = class!(NSResponder);
|
||||
let mut decl = ClassDecl::new("GPUIApplicationDelegate", superclass).unwrap();
|
||||
decl.add_ivar::<*mut c_void>(RUST_WRAPPER_IVAR_NAME);
|
||||
decl.add_method(
|
||||
sel!(applicationDidFinishLaunching:),
|
||||
did_finish_launching as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidBecomeActive:),
|
||||
did_become_active as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(applicationDidResignActive:),
|
||||
did_resign_active as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(application:openFiles:),
|
||||
open_files as extern "C" fn(&Object, Sel, id, id),
|
||||
);
|
||||
decl.register()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn get_app(object: &Object) -> &mut App {
|
||||
let wrapper_ptr: *mut c_void = *object.get_ivar(RUST_WRAPPER_IVAR_NAME);
|
||||
&mut *(wrapper_ptr as *mut App)
|
||||
}
|
||||
|
||||
extern "C" fn send_event(this: &Object, _sel: Sel, native_event: id) {
|
||||
let event = unsafe { Event::from_native(native_event, None) };
|
||||
|
||||
if let Some(event) = event {
|
||||
let app = unsafe { get_app(this) };
|
||||
if let Some(callback) = app.event_callback.as_mut() {
|
||||
if callback(event) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let _: () = msg_send![super(this, class!(NSApplication)), sendEvent: native_event];
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn did_finish_launching(this: &Object, _: Sel, _: id) {
|
||||
let app = unsafe { get_app(this) };
|
||||
if let Some(callback) = app.finish_launching_callback.take() {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn did_become_active(this: &Object, _: Sel, _: id) {
|
||||
let app = unsafe { get_app(this) };
|
||||
if let Some(callback) = app.become_active_callback.as_mut() {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn did_resign_active(this: &Object, _: Sel, _: id) {
|
||||
let app = unsafe { get_app(this) };
|
||||
if let Some(callback) = app.resign_active_callback.as_mut() {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn open_files(this: &Object, _: Sel, _: id, paths: id) {
|
||||
let paths = unsafe {
|
||||
(0..paths.count())
|
||||
.into_iter()
|
||||
.filter_map(|i| {
|
||||
let path = paths.objectAtIndex(i);
|
||||
match CStr::from_ptr(path.UTF8String() as *mut c_char).to_str() {
|
||||
Ok(string) => Some(PathBuf::from(string)),
|
||||
Err(err) => {
|
||||
log::error!("error converting path to string: {}", err);
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
let app = unsafe { get_app(this) };
|
||||
if let Some(callback) = app.open_files_callback.as_mut() {
|
||||
callback(paths);
|
||||
}
|
||||
}
|
115
gpui/src/platform/mac/event.rs
Normal file
115
gpui/src/platform/mac/event.rs
Normal file
|
@ -0,0 +1,115 @@
|
|||
use super::Event;
|
||||
use crate::{geometry::vector::vec2f, keymap::Keystroke};
|
||||
use cocoa::appkit::{
|
||||
NSDeleteFunctionKey as DELETE_KEY, NSDownArrowFunctionKey as ARROW_DOWN_KEY,
|
||||
NSLeftArrowFunctionKey as ARROW_LEFT_KEY, NSPageDownFunctionKey as PAGE_DOWN_KEY,
|
||||
NSPageUpFunctionKey as PAGE_UP_KEY, NSRightArrowFunctionKey as ARROW_RIGHT_KEY,
|
||||
NSUpArrowFunctionKey as ARROW_UP_KEY,
|
||||
};
|
||||
use cocoa::{
|
||||
appkit::{NSEvent as _, NSEventModifierFlags, NSEventType},
|
||||
base::{id, YES},
|
||||
foundation::NSString as _,
|
||||
};
|
||||
use std::{ffi::CStr, os::raw::c_char};
|
||||
|
||||
const BACKSPACE_KEY: u16 = 0x7f;
|
||||
const ENTER_KEY: u16 = 0x0d;
|
||||
const ESCAPE_KEY: u16 = 0x1b;
|
||||
|
||||
impl Event {
|
||||
pub unsafe fn from_native(native_event: id, window_height: Option<f32>) -> Option<Self> {
|
||||
let event_type = native_event.eventType();
|
||||
|
||||
// Filter out event types that aren't in the NSEventType enum.
|
||||
// See https://github.com/servo/cocoa-rs/issues/155#issuecomment-323482792 for details.
|
||||
match event_type as u64 {
|
||||
0 | 21 | 32 | 33 | 35 | 36 | 37 => {
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match event_type {
|
||||
NSEventType::NSKeyDown => {
|
||||
let modifiers = native_event.modifierFlags();
|
||||
let unmodified_chars = native_event.charactersIgnoringModifiers();
|
||||
let unmodified_chars = CStr::from_ptr(unmodified_chars.UTF8String() as *mut c_char)
|
||||
.to_str()
|
||||
.unwrap();
|
||||
|
||||
let unmodified_chars = if let Some(first_char) = unmodified_chars.chars().next() {
|
||||
match first_char as u16 {
|
||||
ARROW_UP_KEY => "up",
|
||||
ARROW_DOWN_KEY => "down",
|
||||
ARROW_LEFT_KEY => "left",
|
||||
ARROW_RIGHT_KEY => "right",
|
||||
PAGE_UP_KEY => "pageup",
|
||||
PAGE_DOWN_KEY => "pagedown",
|
||||
BACKSPACE_KEY => "backspace",
|
||||
ENTER_KEY => "enter",
|
||||
DELETE_KEY => "delete",
|
||||
ESCAPE_KEY => "escape",
|
||||
_ => unmodified_chars,
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let chars = native_event.characters();
|
||||
let chars = CStr::from_ptr(chars.UTF8String() as *mut c_char)
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
Some(Self::KeyDown {
|
||||
keystroke: Keystroke {
|
||||
ctrl: modifiers.contains(NSEventModifierFlags::NSControlKeyMask),
|
||||
alt: modifiers.contains(NSEventModifierFlags::NSAlternateKeyMask),
|
||||
shift: modifiers.contains(NSEventModifierFlags::NSShiftKeyMask),
|
||||
cmd: modifiers.contains(NSEventModifierFlags::NSCommandKeyMask),
|
||||
key: unmodified_chars.into(),
|
||||
},
|
||||
chars,
|
||||
})
|
||||
}
|
||||
NSEventType::NSLeftMouseDown => {
|
||||
window_height.map(|window_height| Self::LeftMouseDown {
|
||||
position: vec2f(
|
||||
native_event.locationInWindow().x as f32,
|
||||
window_height - native_event.locationInWindow().y as f32,
|
||||
),
|
||||
cmd: native_event
|
||||
.modifierFlags()
|
||||
.contains(NSEventModifierFlags::NSCommandKeyMask),
|
||||
})
|
||||
}
|
||||
NSEventType::NSLeftMouseUp => window_height.map(|window_height| Self::LeftMouseUp {
|
||||
position: vec2f(
|
||||
native_event.locationInWindow().x as f32,
|
||||
window_height - native_event.locationInWindow().y as f32,
|
||||
),
|
||||
}),
|
||||
NSEventType::NSLeftMouseDragged => {
|
||||
window_height.map(|window_height| Self::LeftMouseDragged {
|
||||
position: vec2f(
|
||||
native_event.locationInWindow().x as f32,
|
||||
window_height - native_event.locationInWindow().y as f32,
|
||||
),
|
||||
})
|
||||
}
|
||||
NSEventType::NSScrollWheel => window_height.map(|window_height| Self::ScrollWheel {
|
||||
position: vec2f(
|
||||
native_event.locationInWindow().x as f32,
|
||||
window_height - native_event.locationInWindow().y as f32,
|
||||
),
|
||||
delta: vec2f(
|
||||
native_event.scrollingDeltaX() as f32,
|
||||
native_event.scrollingDeltaY() as f32,
|
||||
),
|
||||
precise: native_event.hasPreciseScrollingDeltas() == YES,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
8
gpui/src/platform/mac/mod.rs
Normal file
8
gpui/src/platform/mac/mod.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use super::*;
|
||||
|
||||
mod app;
|
||||
mod event;
|
||||
|
||||
pub fn app() -> impl App {
|
||||
app::App::default()
|
||||
}
|
20
gpui/src/platform/mod.rs
Normal file
20
gpui/src/platform/mod.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
mod event;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod mac;
|
||||
pub mod current {
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use super::mac::*;
|
||||
}
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use event::Event;
|
||||
|
||||
pub trait App {
|
||||
fn on_finish_launching<F: 'static + FnOnce()>(self, callback: F) -> Self where;
|
||||
fn on_become_active<F: 'static + FnMut()>(self, callback: F) -> Self;
|
||||
fn on_resign_active<F: 'static + FnMut()>(self, callback: F) -> Self;
|
||||
fn on_event<F: 'static + FnMut(Event) -> bool>(self, callback: F) -> Self;
|
||||
fn on_open_files<F: 'static + FnMut(Vec<PathBuf>)>(self, callback: F) -> Self;
|
||||
fn run(self);
|
||||
}
|
12
zed/Cargo.toml
Normal file
12
zed/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
authors = ["Nathan Sobo <nathansobo@gmail.com>"]
|
||||
edition = "2018"
|
||||
name = "zed"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
dirs = "3.0"
|
||||
gpui = {path = "../gpui"}
|
||||
libc = "0.2"
|
||||
log = "0.4"
|
||||
simplelog = "0.9"
|
38
zed/src/main.rs
Normal file
38
zed/src/main.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
use std::fs;
|
||||
|
||||
use fs::OpenOptions;
|
||||
use gpui::platform::{current as platform, App as _};
|
||||
use log::LevelFilter;
|
||||
use simplelog::SimpleLogger;
|
||||
|
||||
fn main() {
|
||||
init_logger();
|
||||
platform::app()
|
||||
.on_finish_launching(|| log::info!("finish launching"))
|
||||
.run();
|
||||
}
|
||||
|
||||
fn init_logger() {
|
||||
let level = LevelFilter::Info;
|
||||
|
||||
if stdout_is_a_pty() {
|
||||
SimpleLogger::init(level, Default::default()).expect("could not initialize logger");
|
||||
} else {
|
||||
let log_dir_path = dirs::home_dir()
|
||||
.expect("could not locate home directory for logging")
|
||||
.join("Library/Logs/");
|
||||
let log_file_path = log_dir_path.join("Zed.log");
|
||||
fs::create_dir_all(&log_dir_path).expect("could not create log directory");
|
||||
let log_file = OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(log_file_path)
|
||||
.expect("could not open logfile");
|
||||
simplelog::WriteLogger::init(level, simplelog::Config::default(), log_file)
|
||||
.expect("could not initialize logger");
|
||||
}
|
||||
}
|
||||
|
||||
fn stdout_is_a_pty() -> bool {
|
||||
unsafe { libc::isatty(libc::STDOUT_FILENO as i32) != 0 }
|
||||
}
|
Loading…
Reference in a new issue