Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate text to allow copy/paste #5

Closed
patrislav1 opened this issue Nov 30, 2023 · 13 comments · Fixed by #7
Closed

Consolidate text to allow copy/paste #5

patrislav1 opened this issue Nov 30, 2023 · 13 comments · Fixed by #7

Comments

@patrislav1
Copy link
Collaborator

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
Copy link
Owner

wader commented Nov 30, 2023

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
Copy link
Owner

wader commented Nov 30, 2023

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

  • Somehow use <tspan>/textLength to produce smaller output. Maybe em/ch CSS units for background rects, but seems inkscape do not like ch. Would also make it nicer to copy text from SVG.

@patrislav1
Copy link
Collaborator Author

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. 😅

@wader
Copy link
Owner

wader commented Nov 30, 2023

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
Copy link
Collaborator Author

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
Copy link
Owner

wader commented Nov 30, 2023

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.

wader added a commit that referenced this issue Dec 2, 2023
Replace text elements (block) with tspan (inline) which seem to cause new lines when copying text.

Remove all whitespace between tspan:s to not cause them to end as whitespace in copied text.

Replace figure space codepoint with normal whitespace and use xml:space="preserve" instead.
Otherwise copied text would include a confusing non-U+0020 whitespace. This also fixes an issue
with Inkscape not rendering underline for a text element with only whitespace.

Have reported bug/issue here https://gitlab.com/inkscape/inbox/-/issues/9621

Note that selecting multiple lines will currently not produce new lines i copied text.

Possibly also fixes issue in Safari with text baseline styling.

Fixes #5
@patrislav1
Copy link
Collaborator Author

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
Copy link
Owner

wader commented Dec 4, 2023

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
Copy link
Collaborator Author

👍 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
Copy link
Owner

wader commented Dec 4, 2023

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
Copy link
Collaborator Author

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

wader added a commit that referenced this issue Dec 4, 2023
Replace text elements with a text element per line which consists of tspan elements and
remove all whitespace between tspan:s.

Replace figure space codepoint with normal whitespace and use xml:space="preserve" instead.
Otherwise copied text would include a confusing non-U+0020 whitespace. This also fixes an issue
with Inkscape not rendering underline for a text element with only whitespace.

With this combined copy/paste should work much better and even preserve new lines.

Note that tabs are not preserved at the moment, they get converted into spaces using 8 space tabulation.

Possibly also fixes issue in Safari with text baseline styling.

Inkescape issue has been reported here https://gitlab.com/inkscape/inbox/-/issues/9621

Fixes #5
@wader
Copy link
Owner

wader commented Dec 4, 2023

@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 added a commit that referenced this issue Dec 5, 2023
Replace text elements with a text element per line which consists of tspan elements and
remove all whitespace between tspan:s.

Replace figure space codepoint with normal whitespace and use xml:space="preserve" instead.
Otherwise copied text would include a confusing non-U+0020 whitespace. This also fixes an issue
with Inkscape not rendering underline for a text element with only whitespace.

With this combined copy/paste should work much better and even preserve new lines.

Note that tabs are not preserved at the moment, they get converted into spaces using 8 space tabulation.

Possibly also fixes issue in Safari with text baseline styling.

Inkescape issue has been reported here https://gitlab.com/inkscape/inbox/-/issues/9621

Fixes #5
@wader wader closed this as completed in #7 Dec 5, 2023
@wader
Copy link
Owner

wader commented Dec 5, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants