Implement Rich text on Windows

This commit is contained in:
Federico Terzi 2020-10-08 23:17:01 +02:00
parent 50f1fe9f19
commit 185d06e8e9
13 changed files with 546 additions and 17 deletions

209
Cargo.lock generated
View File

@ -380,10 +380,12 @@ dependencies = [
"dialoguer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"html2text 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"markdown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"named_pipe 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -505,6 +507,15 @@ name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "futf"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"new_debug_unreachable 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "futures"
version = "0.1.29"
@ -546,6 +557,29 @@ dependencies = [
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "html2text"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"html5ever 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
"markup5ever_rcdom 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "html5ever"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"markup5ever 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "http"
version = "0.1.18"
@ -725,6 +759,48 @@ dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "markdown"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pipeline 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "markup5ever"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"phf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_codegen 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "markup5ever_rcdom"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"html5ever 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
"markup5ever 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"xml5ever 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "matches"
version = "0.1.8"
@ -839,6 +915,11 @@ dependencies = [
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "new_debug_unreachable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nodrop"
version = "0.1.13"
@ -955,6 +1036,45 @@ name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "phf"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "phf_codegen"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_generator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "phf_generator"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "phf_shared"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"siphasher 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pipeline"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pkg-config"
version = "0.3.16"
@ -970,6 +1090,11 @@ name = "ppv-lite86"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.30"
@ -1042,6 +1167,7 @@ dependencies = [
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1139,6 +1265,14 @@ dependencies = [
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_pcg"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
@ -1393,6 +1527,11 @@ dependencies = [
"term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "siphasher"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "slab"
version = "0.4.2"
@ -1416,6 +1555,29 @@ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "string_cache"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"new_debug_unreachable 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "string_cache_codegen"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"phf_generator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "strsim"
version = "0.8.0"
@ -1465,6 +1627,16 @@ dependencies = [
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tendril"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "term"
version = "0.6.1"
@ -1703,6 +1875,11 @@ dependencies = [
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "utf-8"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "uuid"
version = "0.7.4"
@ -1810,6 +1987,17 @@ dependencies = [
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "xml5ever"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"markup5ever 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "yaml-rust"
version = "0.4.3"
@ -1888,10 +2076,13 @@ dependencies = [
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b"
"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef"
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571"
"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462"
"checksum html2text 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a26379dcb715e237b96102a12b505c553e2bffa74bae2e54658748d298660ef1"
"checksum html5ever 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcf38a1a36118242d29b92e1b08ef84e67e4a5ed06e0a80be20e6a32bfed6b"
"checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4"
"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
@ -1912,6 +2103,10 @@ dependencies = [
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae0136257df209261daa18d6c16394757c63e032e27aafd8b07788b051082bef"
"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
"checksum markdown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef3aab6a1d529b112695f72beec5ee80e729cb45af58663ec902c8fac764ecdd"
"checksum markup5ever 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aae38d669396ca9b707bfc3db254bc382ddb94f57cc5c235f34623a669a01dab"
"checksum markup5ever_rcdom 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f015da43bcd8d4f144559a3423f4591d69b8ce0652c905374da7205df336ae2b"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
@ -1924,6 +2119,7 @@ dependencies = [
"checksum named_pipe 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad9c443cce91fc3e12f017290db75dde490d685cdaaf508d7159d7cf41f0eb2b"
"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
"checksum new_debug_unreachable 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd"
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
@ -1937,9 +2133,15 @@ dependencies = [
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
"checksum phf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
"checksum phf_codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
"checksum phf_generator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
"checksum phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
"checksum pipeline 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d15b6607fa632996eb8a17c9041cb6071cb75ac057abd45dece578723ea8c7c0"
"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea"
"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd"
"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95"
"checksum publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510"
@ -1958,6 +2160,7 @@ dependencies = [
"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
"checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
@ -1986,15 +2189,19 @@ dependencies = [
"checksum signal-hook 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff2db2112d6c761e12522c65f7768548bd6e8cd23d2a9dae162520626629bd6"
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
"checksum simplelog 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe8c881061cce7ee205784634eda7a61922925e7cc2833188467d3a560e027"
"checksum siphasher 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
"checksum string_cache 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2940c75beb4e3bf3a494cef919a747a2cb81e52571e212bfbd185074add7208a"
"checksum string_cache_codegen 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
"checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b"
"checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5"
"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
@ -2020,6 +2227,7 @@ dependencies = [
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61"
"checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
@ -2036,5 +2244,6 @@ dependencies = [
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum xml5ever 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b1b52e6e8614d4a58b8e70cf51ec0cc21b256ad8206708bcff8139b5bbd6a59"
"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d"
"checksum zip 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3c21bb410afa2bd823a047f5bda3adb62f51074ac7e06263b2c97ecdd47e9fc6"

View File

@ -34,6 +34,8 @@ dialoguer = "0.4.0"
rand = "0.7.2"
zip = "0.5.3"
notify = "4.0.13"
markdown = "0.3.0"
html2text = "0.2.1"
[target.'cfg(unix)'.dependencies]
libc = "0.2.62"

View File

@ -898,3 +898,37 @@ int32_t set_clipboard_image(wchar_t *path) {
return result;
}
// Inspired by https://docs.microsoft.com/en-za/troubleshoot/cpp/add-html-code-clipboard
int32_t set_clipboard_html(char * html, wchar_t * text_fallback) {
// Get clipboard id for HTML format
static int cfid = 0;
if(!cfid) {
cfid = RegisterClipboardFormat(L"HTML Format");
}
int32_t result = 0;
const size_t html_len = strlen(html) + 1;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, html_len * sizeof(char));
memcpy(GlobalLock(hMem), html, html_len * sizeof(char));
GlobalUnlock(hMem);
const size_t fallback_len = wcslen(text_fallback) + 1;
HGLOBAL hMemFallback = GlobalAlloc(GMEM_MOVEABLE, fallback_len * sizeof(wchar_t));
memcpy(GlobalLock(hMemFallback), text_fallback, fallback_len * sizeof(wchar_t));
GlobalUnlock(hMemFallback);
if (!OpenClipboard(NULL)) {
return -1;
}
EmptyClipboard();
if (!SetClipboardData(cfid, hMem)) {
result = -2;
}
if (!SetClipboardData(CF_UNICODETEXT, hMemFallback)) {
result = -3;
}
CloseClipboard();
GlobalFree(hMem);
return result;
}

View File

@ -179,6 +179,13 @@ extern "C" int32_t set_clipboard(wchar_t * text);
*/
extern "C" int32_t set_clipboard_image(wchar_t * path);
/*
* Set clipboard HTML. Notice how in this case, text is not a wide char but instead
* uses the UTF8 encoding.
* Also set the text fallback, in case some applications don't support HTML clipboard.
*/
extern "C" int32_t set_clipboard_html(char * html, wchar_t * text_fallback);
// PROCESSES
extern "C" int32_t start_process(wchar_t * cmd);

View File

@ -17,7 +17,7 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use std::os::raw::c_void;
use std::os::raw::{c_char, c_void};
#[repr(C)]
pub struct WindowsMenuItem {
@ -55,6 +55,7 @@ extern "C" {
pub fn get_clipboard(buffer: *mut u16, size: i32) -> i32;
pub fn set_clipboard(payload: *const u16) -> i32;
pub fn set_clipboard_image(path: *const u16) -> i32;
pub fn set_clipboard_html(html: *const c_char, text_fallback: *const u16) -> i32;
// KEYBOARD
pub fn register_keypress_callback(

View File

@ -32,6 +32,7 @@ pub trait ClipboardManager {
fn get_clipboard(&self) -> Option<String>;
fn set_clipboard(&self, payload: &str);
fn set_clipboard_image(&self, image_path: &Path);
fn set_clipboard_html(&self, html: &str);
}
// LINUX IMPLEMENTATION

View File

@ -17,8 +17,10 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::bridge::windows::{get_clipboard, set_clipboard, set_clipboard_image};
use std::path::Path;
use crate::bridge::windows::{
get_clipboard, set_clipboard, set_clipboard_html, set_clipboard_image,
};
use std::{ffi::CString, path::Path};
use widestring::U16CString;
pub struct WindowsClipboardManager {}
@ -60,4 +62,58 @@ impl super::ClipboardManager for WindowsClipboardManager {
set_clipboard_image(payload_c.as_ptr());
}
}
fn set_clipboard_html(&self, html: &str) {
// In order to set the HTML clipboard, we have to create a prefix with a specific format
// For more information, look here:
// https://docs.microsoft.com/en-us/windows/win32/dataxchg/html-clipboard-format
// https://docs.microsoft.com/en-za/troubleshoot/cpp/add-html-code-clipboard
let mut tokens = Vec::new();
tokens.push("Version:0.9");
tokens.push("StartHTML:<<STR*#>");
tokens.push("EndHTML:<<END*#>");
tokens.push("StartFragment:<<SFG#*>");
tokens.push("EndFragment:<<EFG#*>");
tokens.push("<html>");
tokens.push("<body>");
let content = format!("<!--StartFragment-->{}<!--EndFragment-->", html);
tokens.push(&content);
tokens.push("</body>");
tokens.push("</html>");
let mut render = tokens.join("\r\n");
// Now replace the placeholders with the actual positions
render = render.replace(
"<<STR*#>",
&format!("{:0>8}", render.find("<html>").unwrap_or_default()),
);
render = render.replace("<<END*#>", &format!("{:0>8}", render.len()));
render = render.replace(
"<<SFG#*>",
&format!(
"{:0>8}",
render.find("<!--StartFragment-->").unwrap_or_default()
+ "<!--StartFragment-->".len()
),
);
render = render.replace(
"<<EFG#*>",
&format!(
"{:0>8}",
render.find("<!--EndFragment-->").unwrap_or_default()
),
);
// Render the text fallback for those applications that don't support HTML clipboard
let decorator = html2text::render::text_renderer::TrivialDecorator::new();
let text_fallback =
html2text::from_read_with_decorator(html.as_bytes(), 1000000, decorator);
unsafe {
let payload_c =
CString::new(render).expect("unable to create CString for html content");
let payload_fallback_c = U16CString::from_str(text_fallback).unwrap();
set_clipboard_html(payload_c.as_ptr(), payload_fallback_c.as_ptr());
}
}
}

View File

@ -154,8 +154,14 @@ impl<
}
}
fn inject_text(&self, config: &Configs, target_string: &str, force_clipboard: bool) {
let backend = if force_clipboard {
fn inject_text(
&self,
config: &Configs,
target_string: &str,
force_clipboard: bool,
is_html: bool,
) {
let backend = if force_clipboard || is_html {
&BackendType::Clipboard
} else if config.backend == BackendType::Auto {
if cfg!(target_os = "linux") {
@ -188,7 +194,12 @@ impl<
}
}
BackendType::Clipboard => {
if !is_html {
self.clipboard_manager.set_clipboard(&target_string);
} else {
self.clipboard_manager.set_clipboard_html(&target_string);
}
self.keyboard_manager.trigger_paste(&config);
}
_ => {
@ -270,10 +281,10 @@ impl<
// clipboard content to restore it later.
previous_clipboard_content = self.return_content_if_preserve_clipboard_is_enabled();
self.inject_text(&config, &target_string, m.force_clipboard);
self.inject_text(&config, &target_string, m.force_clipboard, m.is_html);
// Disallow undo backspace if cursor positioning is used
if cursor_rewind.is_none() {
// Disallow undo backspace if cursor positioning is used or text is HTML
if cursor_rewind.is_none() && !m.is_html {
expansion_data = Some((
m.triggers[trigger_offset].clone(),
target_string.chars().count() as i32,
@ -350,7 +361,7 @@ impl<
self.keyboard_manager
.delete_string(&config, *injected_text_len - 1);
// Restore previous text
self.inject_text(&config, trigger_string, false);
self.inject_text(&config, trigger_string, false, false);
}
}

View File

@ -1,3 +1,22 @@
/*
* This file is part of espanso.
*
* Copyright (C) 2020 Federico Terzi
*
* espanso is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* espanso is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::config::Configs;
use log::debug;
use std::sync::atomic::Ordering::Release;

View File

@ -22,9 +22,9 @@ use crate::event::{KeyEvent, KeyModifier};
use regex::{Captures, Regex};
use serde::{Deserialize, Deserializer, Serialize};
use serde_yaml::{Mapping, Value};
use std::collections::HashMap;
use std::fs;
use std::path::PathBuf;
use std::{borrow::Cow, collections::HashMap};
pub(crate) mod scrolling;
@ -36,6 +36,7 @@ pub struct Match {
pub passive_only: bool,
pub propagate_case: bool,
pub force_clipboard: bool,
pub is_html: bool,
// Automatically calculated from the triggers, used by the matcher to check for correspondences.
#[serde(skip_serializing)]
@ -132,15 +133,36 @@ impl<'a> From<&'a AutoMatch> for Match {
})
.collect();
let content = if let Some(replace) = &other.replace {
// Text match
let new_replace = replace.clone();
let (text_content, is_html) = if let Some(replace) = &other.replace {
(Some(Cow::from(replace)), false)
} else if let Some(markdown_str) = &other.markdown {
// Render the markdown into HTML
let mut html = markdown::to_html(markdown_str);
html = html.trim().to_owned();
if !other.paragraph {
// Remove the surrounding paragraph
if html.starts_with("<p>") {
html = html.trim_start_matches("<p>").to_owned();
}
if html.ends_with("</p>") {
html = html.trim_end_matches("</p>").to_owned();
}
}
(Some(Cow::from(html)), true)
} else if let Some(html) = &other.html {
(Some(Cow::from(html)), true)
} else {
(None, false)
};
let content = if let Some(content) = text_content {
// Check if the match contains variables
let has_vars = VAR_REGEX.is_match(replace);
let has_vars = VAR_REGEX.is_match(&content);
let content = TextContent {
replace: new_replace,
replace: content.to_string(),
vars: other.vars.clone(),
_has_vars: has_vars,
};
@ -208,7 +230,7 @@ impl<'a> From<&'a AutoMatch> for Match {
MatchContentType::Image(content)
} else {
eprintln!("ERROR: no action specified for match {}, please specify either 'replace', 'image_path' or 'form'", other.trigger);
eprintln!("ERROR: no action specified for match {}, please specify either 'replace', 'markdown', 'html', image_path' or 'form'", other.trigger);
std::process::exit(2);
};
@ -220,6 +242,7 @@ impl<'a> From<&'a AutoMatch> for Match {
_trigger_sequences: trigger_sequences,
propagate_case: other.propagate_case,
force_clipboard: other.force_clipboard,
is_html,
}
}
}
@ -259,6 +282,15 @@ struct AutoMatch {
#[serde(default = "default_force_clipboard")]
pub force_clipboard: bool,
#[serde(default = "default_markdown")]
pub markdown: Option<String>,
#[serde(default = "default_paragraph")]
pub paragraph: bool,
#[serde(default = "default_html")]
pub html: Option<String>,
}
fn default_trigger() -> String {
@ -294,6 +326,15 @@ fn default_propagate_case() -> bool {
fn default_force_clipboard() -> bool {
false
}
fn default_markdown() -> Option<String> {
None
}
fn default_paragraph() -> bool {
true
}
fn default_html() -> Option<String> {
None
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct MatchVariable {
@ -663,4 +704,95 @@ mod tests {
_ => panic!("wrong content"),
}
}
#[test]
fn test_match_markdown_loaded_correctly() {
let match_str = r###"
trigger: ":test"
markdown: "This *text* is **very bold**"
"###;
let _match: Match = serde_yaml::from_str(match_str).unwrap();
match _match.content {
MatchContentType::Text(content) => {
assert_eq!(
content.replace,
"This <em>text</em> is <strong>very bold</strong>"
);
assert_eq!(_match.is_html, true);
}
_ => {
assert!(false);
}
}
}
#[test]
fn test_match_markdown_keep_vars() {
let match_str = r###"
trigger: ":test"
markdown: "This *text* is {{variable}} **very bold**"
"###;
let _match: Match = serde_yaml::from_str(match_str).unwrap();
match _match.content {
MatchContentType::Text(content) => {
assert_eq!(
content.replace,
"This <em>text</em> is {{variable}} <strong>very bold</strong>"
);
assert_eq!(_match.is_html, true);
assert_eq!(content._has_vars, true);
}
_ => {
assert!(false);
}
}
}
#[test]
fn test_match_html_loaded_correctly() {
let match_str = r###"
trigger: ":test"
html: "This <i>text<i> is <b>very bold</b>"
"###;
let _match: Match = serde_yaml::from_str(match_str).unwrap();
match _match.content {
MatchContentType::Text(content) => {
assert_eq!(content.replace, "This <i>text<i> is <b>very bold</b>");
assert_eq!(_match.is_html, true);
}
_ => {
assert!(false);
}
}
}
#[test]
fn test_match_html_keep_vars() {
let match_str = r###"
trigger: ":test"
html: "This <i>text<i> is {{var}} <b>very bold</b>"
"###;
let _match: Match = serde_yaml::from_str(match_str).unwrap();
match _match.content {
MatchContentType::Text(content) => {
assert_eq!(
content.replace,
"This <i>text<i> is {{var}} <b>very bold</b>"
);
assert_eq!(_match.is_html, true);
assert_eq!(content._has_vars, true);
}
_ => {
assert!(false);
}
}
}
}

View File

@ -1,3 +1,22 @@
/*
* This file is part of espanso.
*
* Copyright (C) 2020 Federico Terzi
*
* espanso is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* espanso is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use log::debug;
use std::error::Error;
use std::io::{copy, Cursor};

View File

@ -1,3 +1,22 @@
/*
* This file is part of espanso.
*
* Copyright (C) 2020 Federico Terzi
*
* espanso is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* espanso is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use log::info;
use std::os::unix::fs::symlink;
use std::path::PathBuf;

View File

@ -1,3 +1,22 @@
/*
* This file is part of espanso.
*
* Copyright (C) 2020 Federico Terzi
*
* espanso is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* espanso is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::config::Configs;
use log::{error, info};
use std::io::{Error, Write};