"pango 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "gtk-source-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cairo-sys-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdk-pixbuf-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gio-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gtk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "gtk-sys"
version = "0.5.0"
"comrak 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"gio 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gtk 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sourceview 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "sourceview"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cairo-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdk 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdk-pixbuf 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdk-pixbuf-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gio 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gio-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gtk 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gtk-source-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gtk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pango 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "strsim"
version = "0.6.0"
"checksum glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9693049613ff52b93013cc3d2590366d8e530366d288438724b73f6c7dc4be8"
"checksum gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60d507c87a71b1143c66ed21a969be9b99a76df234b342d733e787e6c9c7d7c2"
"checksum gtk 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0847c507e52c1feaede13ef56fb4847742438602655449d5f1f782e8633f146f"
+"checksum gtk-source-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b893d266bbc13de37ecd4ab7125761ce4cb924b1cf4603e73f14d13ca7d3a9c"
"checksum gtk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "905fcfbaaad1b44ec0b4bba9e4d527d728284c62bc2ba41fccedace2b096766f"
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
"checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8"
"checksum serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "0672de7300b02bac3f3689f8faea813c4a1ea9fe0cb49e80f714231d267518a2"
"checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab"
"checksum serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ea28ea0cca944668919bec6af209864a8dfe769fd2b0b723f36b22e20c1bf69f"
+"checksum sourceview 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "673844d773083b34c3cb3dab036c75eebb7b223343724f167915980a4586912e"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
[dependencies]
gio = "0.3"
+sourceview = "0.3"
comrak = "0.2"
[dependencies.gtk]
-->
<interface>
<requires lib="gtk+" version="3.20"/>
+ <requires lib="gtksourceview" version="3.0"/>
<!-- interface-license-type mit -->
<!-- interface-name markdown-rs -->
<!-- interface-description Simple Markdown editor -->
<object class="GtkToolButton" id="render_button">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="tooltip_text" translatable="yes">Open</property>
+ <property name="tooltip_text" translatable="yes">Render Markdown</property>
<property name="is_important">True</property>
<property name="label" translatable="yes">Render</property>
<property name="use_underline">True</property>
+ <property name="icon_name">view-refresh</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleToolButton" id="live_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Live Markdown</property>
+ <property name="label" translatable="yes">Live</property>
+ <property name="use_underline">True</property>
<property name="icon_name">media-playback-start</property>
</object>
<packing>
</packing>
</child>
<child>
- <object class="GtkBox">
+ <object class="GtkPaned">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="homogeneous">True</property>
+ <property name="can_focus">True</property>
<child>
<object class="GtkScrolledWindow" id="scrolled_window_left">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
+ <property name="min_content_width">200</property>
<child>
- <object class="GtkTextView" id="text_view">
+ <object class="GtkSourceView" id="text_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="wrap_mode">word</property>
- <property name="left_margin">4</property>
- <property name="right_margin">4</property>
- <property name="top_margin">4</property>
- <property name="bottom_margin">4</property>
- <property name="indent">2</property>
+ <property name="left_margin">2</property>
+ <property name="right_margin">2</property>
+ <property name="top_margin">2</property>
+ <property name="bottom_margin">2</property>
<property name="input_hints">GTK_INPUT_HINT_SPELLCHECK | GTK_INPUT_HINT_WORD_COMPLETION | GTK_INPUT_HINT_NONE</property>
<property name="monospace">True</property>
+ <property name="show_line_marks">True</property>
+ <property name="tab_width">4</property>
+ <property name="auto_indent">True</property>
+ <property name="insert_spaces_instead_of_tabs">True</property>
+ <property name="highlight_current_line">True</property>
+ <property name="background_pattern">grid</property>
</object>
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
+ <property name="resize">True</property>
+ <property name="shrink">False</property>
</packing>
</child>
<child>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
+ <property name="min_content_width">200</property>
<child>
<object class="GtkTextView" id="markdown_view">
<property name="visible">True</property>
</child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
+ <property name="resize">True</property>
+ <property name="shrink">False</property>
</packing>
</child>
</object>
</child>
</object>
</child>
- <child>
+ <child type="titlebar">
<placeholder/>
</child>
</object>
extern crate gio;
extern crate gtk;
+extern crate sourceview;
extern crate comrak;
mod markdown;
use gtk::prelude::*;
use gtk::Builder;
+use markdown::{string_to_html, buffer_to_html};
+
// http://gtk-rs.org/tuto/closures
macro_rules! clone {
(@param _) => ( _ );
let open_button: gtk::ToolButton = builder.get_object("open_button").expect("Couldn't get builder");
let render_button: gtk::ToolButton = builder.get_object("render_button").expect("Couldn't get builder");
+ let live_button: gtk::ToggleToolButton = builder.get_object("live_button").expect("Couldn't get builder");
- let text_view: gtk::TextView = builder.get_object("text_view").expect("Couldn't get text_view");
+ let text_view: sourceview::View = builder.get_object("text_view").expect("Couldn't get text_view");
let markdown_view: gtk::TextView = builder.get_object("markdown_view").expect("Couldn't get text_view");
- open_button.connect_clicked(clone!(window, text_view => move |_| {
+ open_button.connect_clicked(clone!(window, text_view, markdown_view => move |_| {
let file_chooser = gtk::FileChooserDialog::new(Some("Open File"), Some(&window), gtk::FileChooserAction::Open);
file_chooser.add_buttons(&[
("Open", gtk::ResponseType::Ok.into()),
let mut contents = String::new();
let _ = reader.read_to_string(&mut contents);
- text_view.get_buffer().expect("Couldn't get window").set_text(&contents);
+ text_view.get_buffer().unwrap().set_text(&contents);
+ markdown_view.get_buffer().unwrap().set_text(&string_to_html(contents));
}
file_chooser.destroy();
}));
- render_button.connect_clicked(clone!(text_view => move |_| {
- let buffer = text_view.get_buffer().expect("Error getting text");
- let (start, end) = buffer.get_bounds();
- let text = buffer.get_text(&start, &end, false);
+ text_view.connect_key_release_event(clone!(text_view, markdown_view, live_button => move |_, _| {
+ if live_button.get_active() {
+ let buffer = text_view.get_buffer().unwrap();
+ markdown_view.get_buffer().unwrap().set_text(&buffer_to_html(buffer));
+ }
+ Inhibit(true)
+ }));
- let html = markdown::to_html(text);
- markdown_view.get_buffer().expect("Couldn't get window").set_text(&html);
+ render_button.connect_clicked(clone!(text_view, markdown_view => move |_| {
+ let buffer = text_view.get_buffer().unwrap();
+ markdown_view.get_buffer().unwrap().set_text(&buffer_to_html(buffer));
}));
window.connect_delete_event(clone!(window => move |_, _| {
window.show_all();
}
-
fn main() {
let application = gtk::Application::new("com.github.markdown-rs", gio::ApplicationFlags::empty())
.expect("Initialization failed...");
// https://github.com/kivikakk/comrak
+use gtk::prelude::*;
+use gtk::TextBuffer;
+
use comrak::{markdown_to_html, ComrakOptions};
-pub fn to_html(text: Option<String>) -> String {
+pub fn string_to_html(text: String) -> String {
let options = ComrakOptions {
hardbreaks: true,
ext_table: true,
..ComrakOptions::default()
};
- markdown_to_html(&text.unwrap(), &options)
+ markdown_to_html(&text, &options)
+}
+
+pub fn buffer_to_html(buffer: TextBuffer) -> String {
+ let (start, end) = buffer.get_bounds();
+ let text = buffer.get_text(&start, &end, false);
+
+ string_to_html(text.unwrap())
}