novelist: restart project with Rust and Gtk4

main
Katharina Fey 2 years ago
parent 3723de4b0c
commit 9d46c04917
Signed by: kookie
GPG Key ID: 90734A9E619C8A6C
  1. 1
      prototypes/novelist/.envrc
  2. 1
      prototypes/novelist/.gitignore
  3. 0
      prototypes/novelist/.gitlab-ci.yml
  4. 0
      prototypes/novelist/.projectile
  5. 699
      prototypes/novelist/Cargo.lock
  6. 5
      prototypes/novelist/Cargo.toml
  7. 0
      prototypes/novelist/LICENSE
  8. 0
      prototypes/novelist/NOTES
  9. 0
      prototypes/novelist/README.org
  10. 0
      prototypes/novelist/assets/early-demo.png
  11. 0
      prototypes/novelist/assets/icons/128x128.png
  12. 0
      prototypes/novelist/assets/icons/256x256.png
  13. 0
      prototypes/novelist/assets/icons/32x32.png
  14. 0
      prototypes/novelist/assets/icons/64x64.png
  15. 0
      prototypes/novelist/assets/icons/scalable.svg
  16. 0
      prototypes/novelist/assets/novelist.png
  17. 0
      prototypes/novelist/config.el
  18. 9
      prototypes/novelist/novelist-data/Cargo.toml
  19. 26
      prototypes/novelist/novelist-data/src/file.rs
  20. 78
      prototypes/novelist/novelist-data/src/lib.rs
  21. 101
      prototypes/novelist/novelist-data/src/tags.rs
  22. 10
      prototypes/novelist/novelist-gtk/Cargo.toml
  23. 78
      prototypes/novelist/novelist-gtk/src/main.rs
  24. 57
      prototypes/novelist/novelist-gtk/src/text_buffer.rs
  25. 10
      prototypes/novelist/novelist-gtk/src/text_tags.rs
  26. 0
      prototypes/novelist/novelist-mode.el
  27. 17
      prototypes/novelist/shell.nix

@ -0,0 +1 @@
eval "$(lorri direnv)"

@ -0,0 +1,699 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cairo-rs"
version = "0.15.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62be3562254e90c1c6050a72aa638f6315593e98c5cdaba9017cedbabf0a5dee"
dependencies = [
"bitflags",
"cairo-sys-rs",
"glib",
"libc",
"thiserror",
]
[[package]]
name = "cairo-sys-rs"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8"
dependencies = [
"glib-sys",
"libc",
"system-deps",
]
[[package]]
name = "cfg-expr"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e068cb2806bbc15b439846dc16c5f89f8599f2c3e4d73d4449d38f9b2f0b6c5"
dependencies = [
"smallvec",
]
[[package]]
name = "field-offset"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92"
dependencies = [
"memoffset",
"rustc_version",
]
[[package]]
name = "futures-channel"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
[[package]]
name = "futures-executor"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
[[package]]
name = "futures-task"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
[[package]]
name = "futures-util"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
dependencies = [
"futures-core",
"futures-task",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "gdk-pixbuf"
version = "0.15.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a"
dependencies = [
"bitflags",
"gdk-pixbuf-sys",
"gio",
"glib",
"libc",
]
[[package]]
name = "gdk-pixbuf-sys"
version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "140b2f5378256527150350a8346dbdb08fadc13453a7a2d73aecd5fab3c402a7"
dependencies = [
"gio-sys",
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
]
[[package]]
name = "gdk4"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4a2fc0bd03d59383fc10b71a8cb731a1fac2998732a36a0c03e9b1de1513218"
dependencies = [
"bitflags",
"cairo-rs",
"gdk-pixbuf",
"gdk4-sys",
"gio",
"glib",
"libc",
"pango",
]
[[package]]
name = "gdk4-sys"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48a39e34abe35ee2cf54a1e29dd983accecd113ad30bdead5050418fa92f2a1b"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gio-sys",
"glib-sys",
"gobject-sys",
"libc",
"pango-sys",
"pkg-config",
"system-deps",
]
[[package]]
name = "gio"
version = "0.15.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f132be35e05d9662b9fa0fee3f349c6621f7782e0105917f4cc73c1bf47eceb"
dependencies = [
"bitflags",
"futures-channel",
"futures-core",
"futures-io",
"gio-sys",
"glib",
"libc",
"once_cell",
"thiserror",
]
[[package]]
name = "gio-sys"
version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32157a475271e2c4a023382e9cab31c4584ee30a97da41d3c4e9fdd605abcf8d"
dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
"winapi",
]
[[package]]
name = "glib"
version = "0.15.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd124026a2fa8c33a3d17a3fe59c103f2d9fa5bd92c19e029e037736729abeab"
dependencies = [
"bitflags",
"futures-channel",
"futures-core",
"futures-executor",
"futures-task",
"glib-macros",
"glib-sys",
"gobject-sys",
"libc",
"once_cell",
"smallvec",
"thiserror",
]
[[package]]
name = "glib-macros"
version = "0.15.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64"
dependencies = [
"anyhow",
"heck",
"proc-macro-crate",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "glib-sys"
version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4"
dependencies = [
"libc",
"system-deps",
]
[[package]]
name = "gobject-sys"
version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a"
dependencies = [
"glib-sys",
"libc",
"system-deps",
]
[[package]]
name = "graphene-rs"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c54f9fbbeefdb62c99f892dfca35f83991e2cb5b46a8dc2a715e58612f85570"
dependencies = [
"glib",
"graphene-sys",
"libc",
]
[[package]]
name = "graphene-sys"
version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa691fc7337ba1df599afb55c3bcb85c04f1b3f17362570e9bb0ff0d1bc3028a"
dependencies = [
"glib-sys",
"libc",
"pkg-config",
"system-deps",
]
[[package]]
name = "gsk4"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14d5a47a78c682bb67496b562495ed84972c0512ba0654888c4dc92b80a85bd3"
dependencies = [
"bitflags",
"cairo-rs",
"gdk4",
"glib",
"graphene-rs",
"gsk4-sys",
"libc",
"pango",
]
[[package]]
name = "gsk4-sys"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e31d21d7ce02ba261bb24c50c4ab238a10b41a2c97c32afffae29471b7cca69b"
dependencies = [
"cairo-sys-rs",
"gdk4-sys",
"glib-sys",
"gobject-sys",
"graphene-sys",
"libc",
"pango-sys",
"system-deps",
]
[[package]]
name = "gtk4"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb5d40303dabe4608fc260de2bd7563da6f85bc90af956323f0cd8ae0abcfe03"
dependencies = [
"bitflags",
"cairo-rs",
"field-offset",
"futures-channel",
"gdk-pixbuf",
"gdk4",
"gio",
"glib",
"graphene-rs",
"gsk4",
"gtk4-macros",
"gtk4-sys",
"libc",
"once_cell",
"pango",
]
[[package]]
name = "gtk4-macros"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f3c4aa605fb3d78205c7aef0eeaa6db61d8cc4dd05a465dc6ffdfdaee84f825"
dependencies = [
"anyhow",
"proc-macro-crate",
"proc-macro-error",
"proc-macro2",
"quick-xml",
"quote",
"syn",
]
[[package]]
name = "gtk4-sys"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c47c075e8f795c38f6e9a47b51a73eab77b325f83c0154979ed4d4245c36490d"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gdk4-sys",
"gio-sys",
"glib-sys",
"gobject-sys",
"graphene-sys",
"gsk4-sys",
"libc",
"pango-sys",
"system-deps",
]
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "libc"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "novelist-data"
version = "0.1.0"
dependencies = [
"serde",
"xml-rs",
]
[[package]]
name = "novelist-gtk"
version = "0.1.0"
dependencies = [
"glib",
"gtk4",
"novelist-data",
]
[[package]]
name = "once_cell"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
[[package]]
name = "pango"
version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f"
dependencies = [
"bitflags",
"glib",
"libc",
"once_cell",
"pango-sys",
]
[[package]]
name = "pango-sys"
version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2a00081cde4661982ed91d80ef437c20eacaf6aa1a5962c0279ae194662c3aa"
dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
]
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "proc-macro-crate"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
dependencies = [
"thiserror",
"toml",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quick-xml"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b"
dependencies = [
"memchr",
]
[[package]]
name = "quote"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc_version"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
dependencies = [
"semver",
]
[[package]]
name = "semver"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
dependencies = [
"pest",
]
[[package]]
name = "serde"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "slab"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
[[package]]
name = "smallvec"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
[[package]]
name = "syn"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04066589568b72ec65f42d65a1a52436e954b168773148893c020269563decf2"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "system-deps"
version = "6.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709"
dependencies = [
"cfg-expr",
"heck",
"pkg-config",
"toml",
"version-compare",
]
[[package]]
name = "thiserror"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "toml"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
dependencies = [
"serde",
]
[[package]]
name = "ucd-trie"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unicode-xid"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
[[package]]
name = "version-compare"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[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-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "xml-rs"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"

@ -0,0 +1,5 @@
[workspace]
members = [
"novelist-gtk",
"novelist-data",
]

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

@ -0,0 +1,9 @@
[package]
name = "novelist-data"
description = "Contain data models for the Novelist application stack"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
xml-rs = "*"

@ -0,0 +1,26 @@
use crate::{Buffer, Format, TagEntry};
use std::sync::{Arc, Mutex};
pub fn example() -> Arc<Buffer> {
let content = "Impedit voluptatibus sequi aperiam atque vel vero qui qui. Sit voluptates dicta fugiat repellat qui quia at velit. Reprehenderit qui sit explicabo delectus dolorum necessitatibus adipisci. Minima dignissimos sint et autem aut maiores autem quis. Eum modi et ab.
Quo eaque et est enim. Laudantium quis quod enim dignissimos. Dolorem perferendis unde eveniet perspiciatis ipsam magnam. Suscipit laboriosam maiores vero illum exercitationem vel.
Quia atque ipsa ut molestiae non aspernatur. Rem rem delectus occaecati voluptas praesentium et. Distinctio nobis similique et et. Maxime quaerat itaque doloribus. Nesciunt et numquam at voluptate in iste.";
let first = TagEntry {
start: 27,
end: 57,
style: Format::Bold,
};
let second = TagEntry {
start: 609,
end: 650,
style: Format::Bold,
};
Arc::new(Buffer {
content: Mutex::new(content.into()),
tags: Mutex::new(vec![first, second].into()),
})
}

@ -0,0 +1,78 @@
pub mod file;
mod tags;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use tags::RangeState;
pub use tags::{BoundState, Format, TagEntry};
/// Main content buffer of a Novelist file
///
/// The content is a simple text buffer of UTF-8 strings. Formatting
/// tags are applied independently via the tags abstraction.
pub struct Buffer {
// TODO: how does mixed RTL and LTR text get handled here?
pub content: Mutex<String>,
pub tags: Mutex<VecDeque<TagEntry>>,
}
/// A glue trait to connect the storage buffer to a UI toolkit
pub trait PopulateBuffer {
/// Populate a UI text buffer from a storage buffer
fn populate(&self, buffer: &Buffer);
}
impl Buffer {
/// Create a new empty Buffer
pub fn new() -> Arc<Self> {
Arc::new(Self {
content: Mutex::new(String::new()),
tags: Mutex::new(vec![].into()),
})
}
/// Pass a UI buffer to populate from this storage buffer
pub fn populate_ui(self: &Arc<Self>, hook: &impl PopulateBuffer) {
hook.populate(self)
}
/// Toggle a style for a particular range of characters
///
/// This function MUST handle specific corner cases around
/// overlapping ranges.
///
/// Returns a set of styles that MUST be applied to the TextBuffer
pub fn toggle_style(
self: &Arc<Self>,
(start, end): (i32, i32),
style: Format,
) -> Vec<(i32, i32, Format)> {
// 1. Go through linked list and compare list-pos to new-pos
// 2. If NoOverlap, continue
// 3. If BeforeOverlap, expand start-number
// 4. If FullOverlap, ignore (return)
// 5. If AfterOverlap, expand end-number
// 6. If no match was found: insert && sort
// The action we would like to apply
let target = TagEntry { start, end, style };
// Lock existing tags and iterate through them
let mut tags = self.tags.lock().unwrap();
for entry in tags.iter_mut() {
// First perform a simple boundry check
match entry.in_range(&target) {
RangeState::Under => continue,
RangeState::Over => break,
RangeState::InRange => {},
}
// If full-overlap we invert the desired action
// Then handle before and after overlapjjjjjjtncthgki.iidukntxgbeubyx.ixptxddcdpexe
}
todo!()
}
}

@ -0,0 +1,101 @@
#[derive(Debug)]
pub enum Format {
Bold,
Italics,
BoldItalics,
}
#[derive(Debug)]
pub struct TagEntry {
pub start: i32,
pub end: i32,
pub style: Format,
}
/// State differentiator for tag entry bounds
#[derive(Debug, PartialEq)]
pub enum BoundState {
/// Other is before Self
BeforeOverlap,
/// Other is after Self
AfterOverlap,
/// Other is inside Self
FullOverlap,
/// There is no overlap
NoOverlap,
}
/// Indicate whether a section is in range of a target
#[derive(Debug, PartialEq)]
pub(crate) enum RangeState {
Under,
InRange,
Over,
}
impl TagEntry {
/// Create a new TagEntry
pub(crate) fn new(start: i32, end: i32, style: Format) -> Self {
Self { start, end, style }
}
fn test(start: i32, end: i32) -> Self {
Self::new(start, end, Format::Bold)
}
pub(crate) fn in_range(&self, other: &TagEntry) -> RangeState {
match (self.start, other.start, self.end, other.end) {
(_s1, s2, e1, _e2) if e1 < s2 => RangeState::Under,
(s1, s2, e1, e2) if e1 > s2 && s1 < e2 => RangeState::InRange,
(s1, _s2, _e1, e2) if s1 > e2 => RangeState::Over,
(_, _, _, _) => unreachable!(),
}
}
/// Compare self bounds to other bounds
pub(crate) fn check_bounds(&self, other: &TagEntry) -> BoundState {
// s1/e1 = self, s2/e2 = other
match (self.start, other.start, self.end, other.end) {
(s1, s2, _e1, e2) if s2 < s1 && e2 >= s1 => BoundState::BeforeOverlap,
(s1, s2, e1, e2) if s2 > s1 && s2 <= e1 && e2 > e1 => BoundState::AfterOverlap,
(s1, s2, e1, e2) if s2 >= s1 && e2 <= e1 => BoundState::FullOverlap,
_ => BoundState::NoOverlap,
}
}
}
#[test]
fn tag_entry_test1() {
let one = TagEntry::test(0, 9);
let two = TagEntry::test(13, 18);
let one_two_bound = one.check_bounds(&two);
assert_eq!(one_two_bound, BoundState::NoOverlap);
}
#[test]
fn tag_entry_test2() {
let one = TagEntry::test(0, 9);
let two = TagEntry::test(8, 12);
let one_two_bound = one.check_bounds(&two);
assert_eq!(one_two_bound, BoundState::AfterOverlap);
}
#[test]
fn tag_entry_test3() {
let one = TagEntry::test(8, 12);
let two = TagEntry::test(4, 8);
let one_two_bound = one.check_bounds(&two);
assert_eq!(one_two_bound, BoundState::BeforeOverlap);
}
#[test]
fn tag_entry_test4() {
let one = TagEntry::test(9, 12);
let two = TagEntry::test(4, 8);
let one_two_bound = one.check_bounds(&two);
assert_eq!(one_two_bound, BoundState::NoOverlap);
}

@ -0,0 +1,10 @@
[package]
name = "novelist-gtk"
description = "Novest Gtk application interface"
version = "0.1.0"
edition = "2021"
[dependencies]
novelist-data = { path = "../novelist-data" }
gtk4 = "*"
glib = "*"

@ -0,0 +1,78 @@
mod text_buffer;
mod text_tags;
use gtk4::gio::{SimpleAction, SimpleActionGroup};
use gtk4::prelude::*;
use gtk4::{Application, ApplicationWindow, TextView, WrapMode};
use novelist_data::Format;
use std::sync::Arc;
fn main() {
let app = Application::builder()
.application_id("de.spacekookie.novelist")
.build();
app.connect_activate(|app| {
// We create the main window.
let window = ApplicationWindow::builder()
.application(app)
.default_width(800)
.default_height(600)
.title("Novelist")
.build();
// Make Novelist use a light theme (TODO: make this work)
// window.settings().set_gtk_application_prefer_dark_theme(false);
let text_tag_table = text_tags::generate_table();
let novelist_buffer = novelist_data::file::example();
let text_buffer = text_buffer::from_store(&text_tag_table, &novelist_buffer);
let indent = 48;
let margin = 32;
let text_view = TextView::with_buffer(&text_buffer);
text_view.set_accepts_tab(false);
text_view.set_indent(indent);
text_view.set_bottom_margin(indent);
text_view.set_top_margin(indent);
text_view.set_left_margin(margin);
text_view.set_right_margin(margin);
text_view.set_wrap_mode(WrapMode::Word);
let bold_action = SimpleAction::new("make-bold", None);
let text_buffer2 = text_buffer.clone();
let text_buffer3 = text_buffer.clone();
let novelist_buffer2 = Arc::clone(&novelist_buffer);
bold_action.connect_activate(move |_, _| {
if let Some((start, end)) = text_buffer2.selection_bounds() {
novelist_buffer2.toggle_style((start.offset(), end.offset()), Format::Bold);
println!("Making text {}-{} bold...", start.offset(), end.offset());
text_buffer2.apply_tag_by_name("bold", &start, &end);
}
});
let save_action = SimpleAction::new("save", None);
save_action.connect_activate(move |_, _| {
let markup =
text_buffer3.text(&text_buffer.start_iter(), &text_buffer.end_iter(), true);
println!("=== SAVING ===\n{}", markup);
});
let action_group = SimpleActionGroup::new();
action_group.add_action(&bold_action);
action_group.add_action(&save_action);
window.insert_action_group("textbuf", Some(&action_group));
window.set_child(Some(&text_view));
window.show();
});
app.connect_startup(|app| {
app.set_accels_for_action("textbuf.make-bold", &["<Ctrl>b"]);
app.set_accels_for_action("textbuf.save", &["<Ctrl>s"]);
});
app.run();
}

@ -0,0 +1,57 @@
//! A text buffer abstraction
//!
//! Because of the separation between novelist-data and novelist-gtk
//! the storage buffer can't rely on the Gtk buffer to fill data and
//! set tag data. This module wraps this relationship
use gtk4::{prelude::TextBufferExt, TextBuffer, TextTagTable};
use novelist_data::{Buffer, Format, PopulateBuffer, TagEntry};
use std::sync::Arc;
pub struct GtkBuffer(TextBuffer);
impl GtkBuffer {
pub fn new(tb: TextBuffer) -> Self {
Self(tb)
}
pub fn consume(self) -> TextBuffer {
self.0
}
}
impl PopulateBuffer for GtkBuffer {
fn populate(&self, storage: &Buffer) {
let content = storage.content.lock().unwrap();
self.0.set_text(&content);
storage
.tags
.lock()
.unwrap()
.iter()
.for_each(|TagEntry { start, end, style }| {
self.0.apply_tag_by_name(
match style {
Format::Bold => "bold",
Format::Italics => "italics",
_ => unimplemented!(),
},
&self.0.iter_at_offset(*start),
&self.0.iter_at_offset(*end),
)
})
}
}
/// Create an empty text buffer
pub fn empty(text_tag_table: &TextTagTable) -> TextBuffer {
TextBuffer::new(Some(&text_tag_table))
}
/// Load a text buffer from a store
pub fn from_store(text_tag_table: &TextTagTable, buffer: &Arc<Buffer>) -> TextBuffer {
let gtk_buffer = GtkBuffer(empty(text_tag_table));
buffer.populate_ui(&gtk_buffer);
gtk_buffer.0
}

@ -0,0 +1,10 @@
use gtk4::{prelude::TextTagExt, TextTag, TextTagTable};
/// Generate a table of text tags used in novelist
pub fn generate_table() -> TextTagTable {
let text_tag_table = TextTagTable::new();
let bold = TextTag::new(Some("bold"));
bold.set_weight(600);
text_tag_table.add(&bold);
text_tag_table
}

@ -0,0 +1,17 @@
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "novelist";
buildInputs = with pkgs; [
rustc cargo rust-analyzer rustfmt clangStdenv
pkg-config
atk
cairo
gdk-pixbuf
gdk-pixbuf-xlib
glib
gtk4
pango
];
}
Loading…
Cancel
Save