wader / ansisvg

Convert ANSI to SVG
MIT License
89 stars 9 forks source link

Consolidate text to allow copy/paste #5

Closed patrislav1 closed 11 months ago

patrislav1 commented 11 months ago

One huge benefit of text-based screenshots over PNGs is the ability to select / copy contents and paste them elsewhere.

ansisvg generates a dedicated <text> element for each character, and if text is selected / copied from the rendered SVG then the copied selection includes a whitespace after each character.

example: if "WORD" is selected/copied, then the clipboard contents are "W O R D"

ansisvg could detect consecutive characters that have the same style attribute and consolidate them into a single <text> element to facilitate copy/pasting.

wader commented 11 months ago

Yes that would be great and i've tried to do it a couple of times but have failed to produce output that looks good in all major browsers and svg viewers. If i remember correctly it was tricky come up with a compatible way to position characters exactly when not positioning them one by one. Will try to remember more exactly what the problem was.

wader commented 11 months ago

This is in the README todo but don't remember much :)

patrislav1 commented 11 months ago

The issue here is probably that the calculated positions must exactly match the positions of the rendered characters. When the position is explicitly given for each single character (like it is now with dedicated <text> elements), then any deviation from the spacing in the rendered font is just between two adjacent characters, so mostly negligible. But if we render whole words per <text> element then any deviation will accumulate, so the space between words will appear either much too small or much too large. I believe it can be fixed with tweaking the settings for fontsize and charboxsize arguments, but I'm not sure if it's 1) working for all viewers and 2) if it's possible to come up with "working" default combinations of fontsize / charboxsize. Probably also a kind of depending on the currently used font. :sweat_smile:

wader commented 11 months ago

Yeap something like that, i remember tearing my hair and trying every font css property there is :) but i'm still convinced it's impossible :) think i also looked at how other similar projects do it but there was issues what does methods also if i remember correctly.

I've also thought about if there is some tricks one can do with hidden layer or if it's possible with css to give selection hints etc. Problem also is that SVG CSS seems to a subset of HTML CSS :)

I might give it a try again... let me know if you try or have any ideas

patrislav1 commented 11 months ago

How about a "experimental" option that just consolidates <text> elements if they share the style attribute, and does nothing else. The correct combination of fontname, fontsize and charboxsize is then up to the user.

wader commented 11 months ago

Mm could try that. I usually try things by generating some svg output with ansisvg and then manually mess around with it.

Now i got some vague memory that whitespace or possibly some special unicode like drawing-ish characters was hard to get to fill up space correctly somehow.

patrislav1 commented 11 months ago

Thanks for the quick implementation! A short test revealed that the output indeed looks the same as before (at least with my custom fontfamily/fontsize settings), and the copy/pasting now works as intended. Only thing missing is now that the linefeeds disappear from the original content. (I suppose we can't just put a LF into a tspan at the end of each line?)

I also see some instances where colors are not transferred (esp. when using kitty's copy_ansi_to_clipboard instead of just piping) but that's probably not related to this particular feature and needs some deeper investigation.

wader commented 11 months ago

Thanks for the quick implementation! A short test revealed that the output indeed looks the same as before (at least with my custom fontfamily/fontsize settings), and the copy/pasting now works as intended. Only thing missing is now that the linefeeds disappear from the original content. (I suppose we can't just put a LF into a tspan at the end of each line?)

👍 yeap with #7 it should look the same, no consolidating tricks it needed, just change to tspan and some other things. Haven't look deep into preserving new lines yet, could possibly be just to keep/recreate literal \n somehow.

Maybe can merge #7 and do line literals separetly?

I also see some instances where colors are not transferred (esp. when using kitty's copy_ansi_to_clipboard instead of just piping) but that's probably not related to this particular feature and needs some deeper investigation.

That i didn't even consider. I'm mostly testing with iterm2 which seems to not copy styling at all. If it do support copying colors i would guess it should just work as changing styling in svg will require use of separate text or tspan elements.

patrislav1 commented 11 months ago

👍 yeap with #7 it should look the same, no consolidating tricks it needed, just change to tspan and some other things.

Yes, but if consolidating was somehow an option it would greatly reduce file size as well as CPU load esp. for tools like Inkscape. However I understand that it'd be opening a whole different can of worms. Just going to tspan gives the better bang for the buck.

Haven't look deep into preserving new lines yet, could possibly be just to keep/recreate literal \n somehow.

Or translate to <br> in worst case (not sure if SVG supports that, however)

Maybe can merge #7 and do line literals separetly?

Agree

That i didn't even consider. I'm mostly testing with iterm2 which seems to not copy styling at all. If it do support copying colors i would guess it should just work as changing styling in svg will require use of separate text or tspan elements.

Note this is about picking up the colors from the console content and rendering them in SVG, so completely unrelated to the "copying" issue.

I have a few custom keybindings, Shift-Ctrl-x to copy with esc sequences (kitty copy_ansi_to_clipboard), F1 to run clipboard through ansi2html (Python) and open it with Firefox, F2 to run it through ansi2html and save it to $HOME/Pictures, F3 to run it through ansisvg and save it to Pictures.

The thing is, ansi2html always gets the colors right, regardless where it gets its input from - but ansisvg misses some of them if it gets its input from the clipboard, not directly from the pipe. But I have to investigate that a bit deeper before I file a new issue.

wader commented 11 months ago

Yes, but if consolidating was somehow an option it would greatly reduce file size as well as CPU load esp. for tools like Inkscape. However I understand that it'd be opening a whole different can of worms. Just going to tspan gives the better bang for the buck.

Mm maybe look into that later once we get something working.

Or translate to <br> in worst case (not sure if SVG supports that, however)

No <br> in svg unfortunately. Did some tests and i get a feeling literal new \n gets collapsed into a whitespace, so one probably has to generate <text> elements per line or possibly use html entity like etc.

Note this is about picking up the colors from the console content and rendering them in SVG, so completely unrelated to the "copying" issue.

Doh of course :)

I have a few custom keybindings, Shift-Ctrl-x to copy with esc sequences (kitty copy_ansi_to_clipboard), F1 to run clipboard through ansi2html (Python) and open it with Firefox, F2 to run it through ansi2html and save it to $HOME/Pictures, F3 to run it through ansisvg and save it to Pictures.

The thing is, ansi2html always gets the colors right, regardless where it gets its input from - but ansisvg misses some of them if it gets its input from the clipboard, not directly from the pipe. But I have to investigate that a bit deeper before I file a new issue.

Huh that is strange. Any pattern what styling it missing? If you could dump the input sent via clipboard vs pipe to a file somehow that would be great for debugging. Maybe can temporary change the clipboard program to shell scrip that redirects to a file?

patrislav1 commented 11 months ago

I opened a different issue to keep this one on topic.

wader commented 11 months ago

@patrislav1 could you give #7 a try again? pushed a version that has a text elements per line, seem to fix new line issue

wader commented 11 months ago

Rebased and merge on top of the cowsay fixes also. Let me know how it works out!