-
Notifications
You must be signed in to change notification settings - Fork 76
Add support for Terminology escape sequences #16
Conversation
c4f2379
to
e54b84c
Compare
Thanks, but can you add a few comments to explain what the code does and why terminology needs so much more code than iterm2? How does the terminology format look like? |
src/terminal.rs
Outdated
pub enum ImageFormat { | ||
ITerm2, | ||
Terminology, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice change :)
Can you add doc comments to the enum and each field, perhaps with a link to the documentation for each of these formats. For iterm2 it's here: https://www.iterm2.com/documentation-images.html
src/terminal.rs
Outdated
@@ -48,6 +48,8 @@ pub fn columns() -> u16 { | |||
enum Terminal { | |||
/// iTerm2 | |||
ITerm2, | |||
/// Terminology |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you perhaps add a link to the Terminology website? I'll add one for the iterm website as well :)
src/commonmark.rs
Outdated
@@ -440,6 +440,68 @@ impl<'a, W: Write + 'a> Context<'a, W> { | |||
); | |||
write!(self.output.writer, "{}", osc(&command)) | |||
} | |||
|
|||
/// Write an inline image for Terminology. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this method needs much more documentation; I don't even understand what it does at all 🙈
Can you perhaps explain how it works, and also how the image format of terminology looks like?
src/commonmark.rs
Outdated
use std::process::Command; | ||
use termion::terminal_size; | ||
|
||
let lines = terminal_size().unwrap_or((0, 24)).1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move this to the terminal
module, similar to the existing helpers for the column with.
Also, please don't compute it inline, but add it to the Context
. There's already a field for the columns
, why not replace it with a size
field with a corresponding struct Size
?
src/commonmark.rs
Outdated
|
||
let lines = terminal_size().unwrap_or((0, 24)).1; | ||
|
||
Command::new("identify") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we use a crate here? Perhaps image
? I'd prefer if we could work without a runtime dependency on imagemagick here.
If it's not possible, tho, please document that identify
must be in $PATH
for Terminology image support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use a crate here. But do you want to inflate the binary size with parsing code for multiple image formats in an application that is essentially used in terminals and it'd be a natural solution to depend on external commands?
Just choose an option and I'll go with it. I didn't add a crate because I thought you'd dislike this option.
src/commonmark.rs
Outdated
|
||
let o = String::from_utf8(o.stdout).or(Err(ErrorKind::InvalidData))?; | ||
let mut tokens = o.split(' '); | ||
let (w, h) = (get_v(tokens.next())? as f64, get_v(tokens.next())? as f64); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please .map
over tokens
to parse each item and use collect
to extract the result; this avoids the extra helper function.
src/commonmark.rs
Outdated
.ok_or(Into::<Error>::into(ErrorKind::InvalidData)) | ||
} | ||
|
||
let o = String::from_utf8(o.stdout).or(Err(ErrorKind::InvalidData))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please do not abbreviate names. Use output
instead of o
.
src/commonmark.rs
Outdated
.map(str::to_owned) | ||
.ok_or(ErrorKind::InvalidData)?) | ||
} else { | ||
From::from(path.to_str().ok_or(ErrorKind::InvalidData)?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This else
is the same as the first if
, isn't it? Please refactor this condition to avoid the duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said, you don't need to check whether path is relative; joining a path with an absolute path just returns the latter, so you can just use self.input.base_dir.join(path)
in all cases, and it'll always give you a correct path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This else is the same as the first if, isn't it?
You're right. Gonna do.
so you can just use self.input.base_dir.join(path) in all cases, and it'll always give you a correct path
If path is already absolute, I don't want to change the path by joining.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You won't change the path, I think; I prefer having a simpler code path with less conditions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You won't change the path, I think
You're right: https://play.rust-lang.org/?gist=5651ff43abd5f8bc7af2eaeb1c0cde36&version=stable
But I still need to have different code path for remote URLs.
src/commonmark.rs
Outdated
path.to_str() | ||
.map(|p| p.starts_with("http")) | ||
.unwrap_or(false) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this? In the if
below the behaviour doesn't change for HTTP URLs.
If we do need this, please extract into a resources
helper module and use Url
to implement it, ie, Url::parse(…).map(|url| url.scheme == "https" || url.scheme == "http").unwrap_or(false)
.
Perhaps you can even generalize it into a is_remote_reference
function, as in Url::parse(…).map(|url| url.scheme != "file").unwrap_or(false)
.
About the comments that I didn't answer explicitly: I won't comment them. I'll just commit the code. |
@vinipsmaker Thanks for replying. Just FYI, I did a bit of refactoring which adds the entire terminal size to the As for the binary size: syntect—which I use for highlighting—already makes the binary huge because it adds dumps of syntax rules for all the languages it supports. Another crate won't make a difference, so I think we should prefer easy of use here: |
Okay. Gonna do the other changes locally and wait for your code. |
1f0f10a
to
ee1fd7f
Compare
@lunaryorn, the PR is ready to the new round of review. |
@vinipsmaker Thanks 👍 I took a cursory look and I like it a lot more now 👍 I'll take a more detailed look tomorrow, but I think I'll merge it without more review! |
@vinipsmaker Merged, with some modifications tho to account for some other refactoring of mine. I also disabled remote images in Terminology for now, because I'm not sure how they work. For instance what happens when you try to show something that is no image, like when you get a 404 or so? What does Terminology do in this case? I plan to add remote images to iTerm2 too, and I'll just fetch images with I'm sorry if there's an obvious answer to this question; I just don't how Terminology works, and I don't have access to a system where I can try 😊 |
PS: I'm sorry that it took me so long to merge it. 😔 |
They do work. No special treatment. Just give an absolute link (remote or local) and Terminology will fetch the resource.
Terminology will asynchronously fetch the resource. You'll see a running circle to know that a resource is being fetched. If resource fails to load, no problem. You'll just have an empty space there.
It's more inconvenient to have a blocking load of a file. Ideally, Terminology approach would work better. However, because the need to compute a "proportion", it'd be nice to fetch the file ourselves and then feed it to terminology. Before we do that, first I need to know if we can send files instead file references. References to I can see there are fr/fs/fx commands on the Terminology documentation, but I don't know how they work. I can only work on such projects on weekends, so you'll have to wait until I can test anything. |
@vinipsmaker Nice, that's cool. I think we should rely on Terminology fetching images then; it's better if it's asynchronous. I am just a bit concerned that if the image fails to fetch the user is left with an empty space w/o indication what's gone wrong. Currently mdcat shows the image URL for remote images; if we let Terminology download the image, and it fails, it's too late to fallback to showing the image link. Any idea? Just a minor concern, tho. I'll re-enable remote images for Terminology anyway. |
I talked to Terminology/Enlightenment developers over the week. From the discussion, I guess the two best solutions are:
You'll see the spinning circle, but if it fails to load, the spinning circle just disappear, so no indication of failure is left. You'll have a good hint that the resource failed to load, but no notification will stand there.
Maybe a But I can't already work around this w/o any extra code. If I set
Great! |
You mean with paging? I don't think I'd like to do that; iTerm2 at least is better at paging and scrolling then less. I myself use I'll add a |
Okay. Sounds perfect. Best tool to read MarkDown inside the terminal :) |
Thanks 😊 |
Updates #12