Sublime Forum

Copy text with highlighted colors

#101

@facelessuser
A grey-scale option occurred to me a while ago :wink:

Wouldnā€™t JS be overkill? I removed the left-margin (when not printing line numbers) with a couple of css-tweaks.

Iā€™ve posted the code below in case it has anything useful to you - but Iā€™m still using a list.

Iā€™m building a temporary string of the spans before writing them;
Iā€™m able to skip a line entirely if itā€™s empty;
Iā€™m stripping ā€˜\r\nā€™ in case there are any, particularly ā€˜\rā€™, left over;
Iā€™m only replacing spaces with nbsp if they occur at the beginning of the span. This is helpful when copying the HTML, but I donā€™t know how it would affect your* fake alignment* of, for example, dictionary assignments;
Iā€™m not writing the temporary line if itā€™s empty.

[code]
def convert_view_to_html(self, the_html):
for line in self.view.split_by_newlines(sublime.Region(self.pt, self.size)):
self.pt = line.begin(); self.end = self.pt + 1
if line.empty():
the_html.write(ā€™
\n

  • ā€™)
    continue
    self.line_end = line.end()
    temp_line = ā€˜ā€™
    while self.end <= self.line_end:
    scope_name = self.view.scope_name(self.pt)
    while (self.end <= self.line_end and (self.view.scope_name(self.end) == scope_name
    or (self.view.substr(self.end) in ā€˜\tā€™, ā€™ ', ā€˜ā€™]))):
    self.end += 1
    region = sublime.Region(self.pt, self.end)
                the_colour = self.guess_colour(scope_name.strip())
                tidied_text = self.view.substr(region)
                tidied_text = tidied_text.replace('&', '&amp;')
                tidied_text = tidied_text.replace('<', '&lt;')
                tidied_text = tidied_text.replace('>', '&gt;')
                tidied_text = tidied_text.replace('\t', '&nbsp;' * self.tab_size)
                tidied_text = tidied_text.strip('\r\n')
                if len(tidied_text):
                    without_init_sp = tidied_text.lstrip(' ')
                    init_spaces = len(tidied_text) - len(without_init_sp)
                    if init_spaces:
                        without_init_sp = ('&nbsp;' * init_spaces) + without_init_sp
                        tidied_text = without_init_sp
                    temp_line += '<span style=\"color:' + the_colour + '\">'
                    temp_line += tidied_text + '</span>'
                self.pt = self.end
                self.end = self.pt + 1
            if temp_line != '':
                the_html.write(temp_line)
            the_html.write('</li>\n<li>')[/code]
    

    [Copied from HTML :smile: ]

    There might be a neater way of replacing the spaces only at the beginning of the line :question: (non-regex).

    I tried ā€˜closingā€™ your pull request but Iā€™m still unable to update to my local version :question:

    Added: Oops. My version doesnā€™t copy the line numbers, Doh! Iā€™ve only just noticed this :laughing:. I think you may have hinted at this earlier :wink:
    Added again: No worries, I can always copy/save the HTML if I want the line numbers.

  • 0 Likes

    #102

    I thought it might seem like overkill at first, but it seems to work quite well.

    I just write this to the end of the document feeding in the right parameters. User can define wrap size (px).

    [code]WRAP =
    ā€œā€"

    ā€œā€"[/code]

    With this method, if you copy the text, the wrapped lines will still be part of the same lines, not separate. I am still goofing around, this could change. It is easier this way, because then I can just grab the size of the number column and resize the content of text column on the fly. I have to guess size if I try to do it at HTML creation time. There are a lot of factors: font, font-size, largest row number, etc.

    0 Likes

    #103

    Meant style.width not offsetwidth on the file info one. It is fixed.

    0 Likes

    #104

    @facelessuser

    I closed your pull request but was still having trouble updating from my local copy. It asked me to pull first. Anyway, I managed to commit my update but the file includes some weird annotations:

    [code]<<<<<<< HEAD

    e1ec88f044e2ef6bc61552215c2e77e3f61b9ec2

    class PrintHtmlCommand(sublime_plugin.TextCommand):[/code]
    Have you seen this before? Andy.

    **Added **No worries, I committed again and itā€™s fine. Donā€™t know why I had to pull first thoughā€¦

    0 Likes

    #105

    Considering myself a JS guy :wink: itā€™s just

    [code]
    // or, if you must
    //

    [/code] I haven't read your code in detail but I'm sure you're aware that attempting to read **width** if it hasn't been set can lead to unexpected return values (in different browsers). But a quick glance tells me that you've set it to a value anyway :smile:
    0 Likes

    #106

    [quote=ā€œagibsonswā€]Considering myself a JS guy :wink: itā€™s just

    [code]
    // or, if you must
    //

    [/code] I haven't read your code in detail but I'm sure you're aware that attempting to read **width** if it hasn't been set can lead to unexpected return values (in different browsers). But a quick glance tells me that you've set it to a value anyway :smile:[/quote] Yeah, I was a little sloppy (mainly just tinkering right now). I haven't done javascript since I wrote a plugin for the TonidoPlug (I have been taking a long javascript break since then). I find JS fun, but I find all the different web browser inconsistencies not fun. Some of it isn't as fresh in my brain. I will be running it through the browser gamut when I get closer to a finalized plugin. I probably need to reference my old JS code to remember everything; I really got deep into JS and browsers when I was doing it.
    0 Likes

    #107

    Iā€™m keen on JS (wrote my own library :smiley: ) which makes me dislike all the fake Python assignments ( something = why! ). So let me know if you need a second opinion at any stage.

    Andy.

    0 Likes

    #108

    [quote=ā€œagibsonswā€]Iā€™m keen on JS (wrote my own library :smiley: ) which makes me dislike all the fake Python assignments ( something = why! ). So let me know if you need a second opinion at any stage.

    Andy.[/quote]

    Thanks, I will let you know if I have any specific questions. That TonidoPlug plugin I mentioned, it has my javascript library built into it too :smile: (I got really in to JS for that span of time). But as with anything use it or lose it. The good thing about this plugin, it should be very light on JS. I think I really on have two small applications for it right now: open browser print dialog, and wrap html at XXX px. I want to keep it very very light.

    0 Likes

    #109

    @facelessuser: Wonā€™t be as light as mine - Iā€™ve finished for the moment :wink:

    [quote] def write_header(self, the_html):
    header = CSS % (
    path.basename(the_html.name), # Title
    str(self.font_size), # Code font size
    self.font_face, # Code font face
    self.bground, # Page background color
    self.gbground, # Gutter background color
    self.fground # Default text color
    )
    the_html.write(header)[/quote]

    Named parameters are cool:

    print '<a href="%(url)s">%(url)s</a>' % {'url': my_url}

    but itā€™s probably not worth amending. It just means you/we wouldnā€™t have to worry about the order, or comments.

    0 Likes

    #110

    I will have to check it out :smile:. Since my requirements are slightly different, I probably cannot pull in your format, but if it works better and fulfills my requirementsā€¦I do like lighter.

    [quote=ā€œagibsonswā€]

    [quote] def write_header(self, the_html):
    header = CSS % (
    path.basename(the_html.name), # Title
    str(self.font_size), # Code font size
    self.font_face, # Code font face
    self.bground, # Page background color
    self.gbground, # Gutter background color
    self.fground # Default text color
    )
    the_html.write(header)[/quote]

    Named parameters are cool:

    print '<a href="%(url)s">%(url)s</a>' % {'url': my_url}

    but itā€™s probably not worth amending. It just means you/we wouldnā€™t have to worry about the order, or comments.[/quote]

    That would be pretty useful. Man , why didnā€™t I realize I could do that. I will pick that up for sure.

    0 Likes

    #111

    @facelessuser

    You can also repeat an argument

    (some_fn(), ) * x

    (Iā€™m sure you know thisā€¦) but I donā€™t think itā€™s relevant.

    **

    0 Likes

    #112

    Well hereā€™s my updated repository on GitHub.

    @facelessuser: They only minor changes worth mentioning are that:

    Iā€™ve set ā€˜curr_row = 1ā€™ for numbers/not partial, just to leave the future possibility that I might want to number them differently.

    And, borrowing from syntax you introduced me to:

    # Get general theme colors from color scheme file self.bground = colour_settings"background"] if "background" \ in colour_settings else '#FFFFFF' self.fground = colour_settings"foreground"] if "foreground" \ in colour_settings else '#000000' self.gfground = colour_settings"gutterForeground"] if "gutterForeground" \ in colour_settings else self.fground
    This also means I donā€™t have to check ā€˜if self.fground == ā€˜ā€™ā€™ when creating the style-rules (or initialize them to ā€˜ā€™ ).

    0 Likes

    #113

    Just trivia:

    I spent ages racking my brain to obtain a neat way of replacing the spaces, but only at the beginning of a string. After a few attempts I ended up with:

    if len(tidied_text): init_spaces = len(tidied_text) - len(tidied_text.lstrip(' ')) if init_spaces: tidied_text = (init_spaces * '&nbsp;') + tidied_text.lstrip(' ')
    But it made me smile as this was practically the very first (and best) method that I had tried :laughing: :sunglasses:

    0 Likes

    #114

    [quote=ā€œagibsonswā€]Well hereā€™s my updated repository on GitHub.

    @facelessuser: They only minor changes worth mentioning are that:

    Iā€™ve set ā€˜curr_row = 1ā€™ for numbers/not partial, just to leave the future possibility that I might want to number them differently.

    And, borrowing from syntax you introduced me to:

    # Get general theme colors from color scheme file self.bground = colour_settings"background"] if "background" \ in colour_settings else '#FFFFFF' self.fground = colour_settings"foreground"] if "foreground" \ in colour_settings else '#000000' self.gfground = colour_settings"gutterForeground"] if "gutterForeground" \ in colour_settings else self.fground
    This also means I donā€™t have to check ā€˜if self.fground == ā€˜ā€™ā€™ when creating the style-rules (or initialize them to ā€˜ā€™ ).[/quote]

    Cool, I will check it out.

    Here is a preview of multi-select support :wink: ā€¦


    0 Likes

    #115

    @facelessuser: Oh, I see :sunglasses: Very clever, and useful!

    I misunderstood; I was thinking, previously, of highlighting the text that they have selected (with their selection colour) - but are you doing this as well?

    As youā€™ve mentioned JS :smile: a silly, but interesting idea is to allow text to be highlighted and annotations added using the input panel. These could then become tooltips, or popup boxes in the HTML - even just with CSS. This would make the page dynamicā€¦ and cool. But I donā€™t want you to have another sleepless night.

    BTW I might look at Word at the weekend. Not because itā€™ll be useful, but purely for my Python education. Alternatively, an Outlook/ send to option - which begins an email with the HTML in the body - should not be too tricky. In fact, it may only require a handful of code-lines.

    Andy.

    0 Likes

    #116

    Actually, doesnā€™t have to be Outlook.

    Iā€™ll pursue this a little bit. Thereā€™s a mailer module which is a simple wrapper around the ā€˜emailā€™ module. Itā€™s under an MIT licence :question: but if itā€™s possible I could copy the source-code and remove the bits I donā€™t need (as itā€™s for a quite specific purpose).

    If I canā€™t just *rip *the code then Iā€™ll have to study the email module and build a wrapper myself (I suppose).

    Otherwise, should be a breeze. Andy.

    Actually, I need to tear off the header, etc., from the_html - leaving just a list or table.

    0 Likes

    #117

    [quote=ā€œagibsonswā€]@facelessuser: Oh, I see :sunglasses: Very clever, and useful!

    I misunderstood; I was thinking, previously, of highlighting the text that they have selected (with their selection colour) - but are you doing this as well?
    [/quote]

    I meant both:


    [quote=ā€œagibsonswā€]
    As youā€™ve mentioned JS :smile: a silly, but interesting idea is to allow text to be highlighted and annotations added using the input panel. These could then become tooltips, or popup boxes in the HTML - even just with CSS. This would make the page dynamicā€¦ and cool. But I donā€™t want you to have another sleepless night.

    BTW I might look at Word at the weekend. Not because itā€™ll be useful, but purely for my Python education. Alternatively, an Outlook/ send to option - which begins an email with the HTML in the body - should not be too tricky. In fact, it may only require a handful of code-lines.

    Andy.[/quote]

    That would be interesting. Especially if you were looking for an annotated document of your code. I am wondering how useful it would be? It is kind of a cool idea though. Donā€™t worry about me not sleeping. I am almost done with all features on my immediate todo list. Anything like this would come after I take a nice long break :smile:. I just want to round out the basic features and put it through some good testing and give it a 1.0.0 release version.

    0 Likes

    #118

    [quote=ā€œagibsonswā€]Actually, doesnā€™t have to be Outlook.

    Iā€™ll pursue this a little bit. Thereā€™s a mailer module which is a simple wrapper around the ā€˜emailā€™ module. Itā€™s under an MIT licence :question: but if itā€™s possible I could copy the source-code and remove the bits I donā€™t need (as itā€™s for a quite specific purpose).

    If I canā€™t just *rip *the code then Iā€™ll have to study the email module and build a wrapper myself (I suppose).

    Otherwise, should be a breeze. Andy.

    Actually, I need to tear off the header, etc., from the_html - leaving just a list or table.[/quote]

    MIT is pretty forgiving. You can use it and even modify it as I understand, but you must not claim it as your own and you must provide the license as well or at least have it in the code file. GNU GPL is a bit more annoying (though there are a couple of versions) but in general it kind of infects your project, and the project including it must also be released under the same license. Technically, I think the desktop module that we are including is GNU GPL (that is the one downside of it). But keep in mind, I am no expert in all of this license stuff. For anything we are doing, I donā€™t think it matters, but combining MIT and GPL, I am not sure how that works together or if it can.

    0 Likes

    #119

    It appears the Desktop module is the Lesser GPL which I think is compatible with MIT. So I think you would be fine.

    0 Likes

    #120

    @facelessuser: Thought you were doing both, as I noticed you storing the ā€˜selectionā€™ colour. Been a bit pre-occupied to study your code in more detail though :smile:

    The mailer source code includes the following comment:

    [quote]A lot of this code was taken from the online examples in the
    email module documentation:
    docs.python.org/library/email-examples.html

    Released under MIT license.[/quote]

    which seems very noble. At the end of the day, we are ALL *borrowing *code from somewhere :smile:

    Actuallyā€¦ just had an inspiring idea about the tooltips/ popup boxes. They could be (editable - TextArea) to-do items/ comments. What a cool idea :sunglasses: :bulb:. But Iā€™m getting a little carried away nowā€¦

    Andy.

    0 Likes