Sublime Forum

Copy text with highlighted colors

#41

@facelessuser: No problem. That replaces all spaces - I might try to pursued it to only apply at the beginning of the line, otherwise it seems like overkill.

I do :wink: take your comments on board about the desktop library and non-Windows users. But Iā€™ll explore the C++ (and similar) issue(s) first.

Iā€™ve updated my repository with recent changes (not including the spaces, yet, or the C++ changes).

0 Likes

#42

[quote=ā€œagibsonswā€]@facelessuser: No problem. That replaces all spaces - I might try to pursued it to only apply at the beginning of the line, otherwise it seems like overkill.

I do :wink: take your comments on board about the desktop library and non-Windows users. But Iā€™ll explore the C++ (and similar) issue(s) first.

Iā€™ve updated my repository with recent changes (not including the spaces, yet, or the C++ changes).[/quote]

Thanks. I hope I am not coming off two aggressive or anything. I think this plugin is really cool, so I am just trying to give straight forward and honest feedback.

I do realize not everything I may suggest will be taken up, but I think it is better to throw it out there anyways. Ultimately it is your plugin, so you make the calls. People are always going to throw there 2 cents in (like me :smile: ). The fact that I am so vocal just shows that I really like the plugin and intend to use it.

0 Likes

#43

@facelessuser: Hey, no problem at all! I welcome your comments and assistance :wink:

I intend to understand, and agree with (mostlyā€¦) any changes made to the code. So Iā€™ll learn about pulling, forking, bundling other libraries, etc., along the way.

I only started this yesterday out of interest, but if it proves useful as a plug-in then thatā€™s great. In the meantime, Iā€™ve learnt about, coded (and discarded!) three different xml parsers.

(Originally I considered creating an .rtf, or using COM automation to format the text in Word - glad I took the HTML road :laughing: )

Keep the commentary coming! Andy.

0 Likes

#44

I havenā€™t applied your changes yet, but my C++ sample is formatting source.c++ and other scopes with a ā€˜randomā€™ scope way down in the file. Maybe itā€™s the pluses ++ that are causing the issue. Are there any other languages youā€™ve tested?

Added: C# seems to be okay, even coping with four spaces(?). Do you use four spacesā€¦?

0 Likes

#45

@facelessuser

I think youā€™re right :wink: Iā€™ll replace all spaces with Ā  - itā€™ll be more robust in terms of ā€˜mono-spacingā€™ the code.

I think Iā€™ll also have to wrap the lines within liā€™s, even without the line numbersā€™ option. Then I can apply css margins to create paragraph spacing - hopefully avoiding collapsing margins, he, he!

0 Likes

#46

[quote=ā€œagibsonswā€]I havenā€™t applied your changes yet, but my C++ sample is formatting source.c++ and other scopes with a ā€˜randomā€™ scope way down in the file. Maybe itā€™s the pluses ++ that are causing the issue. Are there any other languages youā€™ve tested?

Added: C# seems to be okay, even coping with four spaces(?). Do you use four spacesā€¦?[/quote]

JSON also turned brackets into comments. I assume there are many more, but after applying my changes, they all went away. I would need time to try more languages.

0 Likes

#47

Iā€™ve now applied (some/most of) your changes, and also changed the default **best_match **to 0 :laughing:. Iā€™ll have to do a bit of testing as well. (Need to discover whether itā€™s the plusses, something about the theme file, or other oddities in the scopes.)

Iā€™ve now put everything into liā€™s, so that I can adjust the paragraph spacing (margins) using the usersā€™ line-padding settings. When not using line numbers I have a few disappearing, blank lines - collapsing margins - as I guessed :smile:. But I think I just need to put insert Ā  if there happens to be a *completely *empty span.

0 Likes

#48

It has nothing to do with the ā€œ++ā€. If I have simple C code and I set the language to C instead of C++, so source now equals ā€œsource.cā€ all my text is still comments. Yours might be different if your theme is different, but yes it is the first entry in the theme. It never finds anything better (they are all equally bad matches). But ā€œsource.cā€ is a much better match than comments, which is why I compare it. And this same flaw bleeds into other languages like JSON etc. Some languages, like Python, do not exhibit this issue due to the way the items are scoped.

0 Likes

#49

Also, this is really a show stopper for me:

tidied_text = tidied_text.replace(' ' * tab_size, ' ' * tab_size)

Since this only replaces a tabsize * spaces to tabsize * ā€™Ā ', it messes up alignment of structures:

You can run this through and see how alignment gets messed up. Tab set to 4. Now with larger structures, you will see this getting real ugly.

const s_SomeType c_SomeClass::SomeList] = { { SOME_ITEM, 3 }, { SOME_OTHER_ITEM, 4 }, END_OF_LIST() }

It really shouldnā€™t be trying to correct spaces, it should be trying to give the closes representation to what is in the editor. Converting a tab to spaces makes sense.

0 Likes

#50

@facelessuser: Is the problem still present after your changes?

A sensible, alternative approach might be to set the first dictionary entry to ā€˜source.langā€™: ā€˜foreground-colourā€™? This is how ST behaves anyway, even though itā€™s not a visible rule in the theme. The problem might disappear then :smile:

Different topic: Iā€™m ending up with lots of (completely) empty spans in the code:

<li><span style="color:#FFCC11"></span></li>
This is not necessarily an issue. However, having converted everything to fit within liā€™s - to enable some paragraph spacing - should an a li contain just an empty span, then the line collapses. Iā€™m not sure whether these empty spans were always there, or have arisen recently. Iā€™ll have to try and overcome this because, I believe, the liā€™s are necessary.

Aha! If the tidied text is just ā€˜\nā€™ the len-gth is this is two! This should lead me to a solution. Andy.

0 Likes

#51

[quote=ā€œfacelessuserā€]Also, this is really a show stopper for me:

tidied_text = tidied_text.replace(' ' * tab_size, '&nbsp;' * tab_size)

It really shouldnā€™t be trying to correct spaces, it should be trying to give the closes representation to what is in the editor. Converting a tab to spaces makes sense.[/quote]

I changed it to your suggestion:** tidied_text = tidied_text.replace(ā€™ ', ā€™Ā ')** - we need nbsp to maintain mono-space-like behaviour.

Is this still an issue? I copied your code but it worked fine for me(?).

PS This is the problem with using spaces to fake alignment :smiley:

0 Likes

#52

Would it help if you used

 tags?

(Iā€™m just butting into this topic since I understand ~1% of it.)

0 Likes

#53

[quote=ā€œagibsonswā€]

[quote=ā€œfacelessuserā€]Also, this is really a show stopper for me:

tidied_text = tidied_text.replace(' ' * tab_size, ' ' * tab_size)

It really shouldnā€™t be trying to correct spaces, it should be trying to give the closes representation to what is in the editor. Converting a tab to spaces makes sense.[/quote]

I changed it to your suggestion:** tidied_text = tidied_text.replace(ā€™ ', ā€™ ')** - we need nbsp to maintain mono-space-like behaviour.

Is this still an issue? I copied your code but it worked fine for me(?).

PS This is the problem with using spaces to fake alignment :smiley:[/quote]

Did you push it to the repository? The actual repository shows that you did not change it. I must not have the latest. Can you double check?

0 Likes

#54

[quote=ā€œC0D312ā€]Would it help if you used

 tags?

(Iā€™m just butting into this topic since I understand ~1% of it.)[/quote]

PRE may be an alternative, but it presents other issues in terms of formatting within them (I think). Iā€™m hoping, having replaced all spaces with Ā , that this issue is resolved. But this is more to do with the way HTML behaves, rather than a faulty approach within my code :wink:

I should look again at just leaving the spaces, but they tend to *disappear *quite often, he, he. And creating empty elements of a certain size is a minefield - which probably wonā€™t work anyway.

I was going to suggest that you canā€™t go wrong with tabsā€¦ but tabs are not always four spaces, Doh! Another issue for laterā€¦

@facelessuser: I havenā€™t updated my repo recently. My recent code is below, but I want to fix the disappearing lines issue before I update. That is, if thereā€™s a completely blank line (when not printing line numbers) I want to insert a Ā  to prevent it collapsing.

[code]import sublime, sublime_plugin
from xml.dom import minidom
from os import path

class PrintHtmlCommand(sublime_plugin.TextCommand):
def run(self, edit, numbers): # numbers == True: output line numbers
self.colours = {}
path_packages = sublime.packages_path()
settings = sublime.load_settings(ā€˜Preferences.sublime-settingsā€™)
colour_scheme = settings.get(ā€˜color_schemeā€™)
colour_scheme = path.normpath(colour_scheme)
colour_scheme = colour_scheme.replace(ā€˜Packagesā€™, ā€˜ā€™)
font_size = settings.get(ā€˜font_sizeā€™) or 10
font_face = settings.get(ā€˜font_faceā€™) or ā€˜Consolasā€™
tab_size = settings.get(ā€˜tab_sizeā€™) or 4
padd_top = settings.get(ā€˜line_padding_topā€™) or 0
padd_bottom = settings.get(ā€˜line_padding_bottomā€™) or 0
doc = minidom.parse(path_packages + colour_scheme)
the_dict = doc.getElementsByTagName(ā€˜dictā€™)[0]
the_array = the_dict.getElementsByTagName(ā€˜arrayā€™)[0]
colour_settings = the_array.getElementsByTagName(ā€˜dictā€™)[0]
bground = ā€˜ā€™; fground = ā€˜ā€™; gfground = ā€˜ā€™
for key_tag in colour_settings.getElementsByTagName(ā€˜keyā€™):
try:
if key_tag.firstChild.data.strip() == ā€˜backgroundā€™:
bground = key_tag.nextSibling.nextSibling.firstChild.data.strip()
elif key_tag.firstChild.data.strip() == ā€˜foregroundā€™:
fground = key_tag.nextSibling.nextSibling.firstChild.data.strip()
elif key_tag.firstChild.data.strip() == ā€˜gutterForegroundā€™:
gfground = key_tag.nextSibling.nextSibling.firstChild.data.strip()
except:
pass
if gfground == ā€˜ā€™: gfground = fground
dict_items = the_array.getElementsByTagName(ā€˜dictā€™)[1:]
for item in dict_items:
scope = ā€˜ā€™; colour = ā€˜ā€™
for key_tag in item.getElementsByTagName(ā€˜keyā€™):
try:
if key_tag.firstChild.data.strip() == ā€˜scopeā€™:
scope = key_tag.nextSibling.nextSibling.firstChild.data.strip()
elif key_tag.firstChild.data.strip() == ā€˜foregroundā€™:
colour = key_tag.nextSibling.nextSibling.firstChild.data.strip()
except:
pass
if scope != ā€˜ā€™ and colour != ā€˜ā€™:
self.colours[scope] = colour

	curr_view = self.view
	curr_file = curr_view.file_name()
	if curr_file is None:
		fname = 'temp'
	else:
		head, tail = path.split(curr_file)
		fname, ext = path.splitext(tail)
		fname = fname + ext.replace('.', '_')
		fname = head + path.sep + fname
	
	curr_sel = curr_view.sel()[0]
	if curr_sel.empty() or abs(curr_sel.end() - curr_sel.begin()) < 4:
		the_html = open(fname + '_parsed.html', 'w')
		size = curr_view.size()
		pt = 0; end = 1
		partial = False
	else:
		the_html = open(fname + '_part.html', 'w')
		size = curr_sel.end()
		pt = curr_sel.begin()
		end = pt + 1
		curr_row = curr_view.rowcol(pt)[0] + 1
		partial = True
	the_html.write('<!DOCTYPE html>\n')
	the_html.write('<html>\n<head>\n<title>' + fname + '</title>\n')
	the_html.write('<style type=\"text/css\">\n')
	the_html.write('\tspan { display: inline; border: 0; margin: 0; padding: 0; }\n')
	if not numbers:
		the_html.write('\tol { list-style-type: none; }\n')
	the_html.write('\tli { color: ' + gfground  + '; margin-top: ' + 
		`padd_top` + 'pt; margin-bottom: ' + `padd_bottom` + 'pt; }\n')
	the_html.write('\tbody { ')
	if fground != '': the_html.write('color: ' + fground + ';')
	if bground != '': the_html.write(' background-color: ' + bground + ';')
	the_html.write(' font: ' + `font_size` + 'pt \"' + font_face + '\", Consolas, Monospace;')
	the_html.write('\n}\n')
	the_html.write('</style>\n</head>\n<body>\n')
	if numbers and partial:
		the_html.write('<ol>\n<li value="%d">' % curr_row)		# use code's line numbering
	else:
		the_html.write('<ol>\n<li>')
	default_scope = curr_view.scope_name(end).split(' ')[0]
	while end <= size:
		scope_name = curr_view.scope_name(pt)
		while curr_view.scope_name(end) == scope_name and end <= size:
			end += 1
		region = sublime.Region(pt, end)
		the_key = scope_name.strip()
		if self.colours.has_key(the_key):
			the_colour = self.colours[the_key]
		else:
			if the_key == default_scope:
				self.colours[the_key] = fground
				the_colour = fground
			else:
				best_match = 0
				for key in self.colours:
					if curr_view.score_selector(pt, key) > best_match:
						best_match = curr_view.score_selector(pt, key)
						the_colour = self.colours[key]
				if curr_view.score_selector(pt, default_scope) > best_match:
					the_colour = fground
				self.colours[the_key] = the_colour
		tidied_text = curr_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;' * tab_size)
		tidied_text = tidied_text.replace(' ', '&nbsp;')
		new_li = '</span></li>\n<li><span style=\"color:' + the_colour + '\">'
		if len(tidied_text) == 2: print ',' + tidied_text + ','
		tidied_text = tidied_text.replace('\n', new_li)
		the_html.write('<span style=\"color:' + the_colour + '\">')
		the_html.write(tidied_text + '</span>')
		pt = end
		end = pt + 1
	the_html.write('</li>\n</ol>')
	the_html.write('\n</body>\n</html>')
	the_html.close()[/code]
0 Likes

#55

Just updated my repo with the previous postā€™s code.

0 Likes

#56

Just a suggestion, since I believe

 preserves spaces so you wonā€™t have to deal with Ā 
But if thatā€™s all fixed, just ignore my ignorance :smile:

@facelessuser: have you played with my latest commit yet? :wink:

0 Likes

#57

[quote=ā€œC0D312ā€]
@facelessuser: have you played with my latest commit yet? :wink:[/quote]

Yeah, the concept is neat, just need to polish it up. I will start work on the syntax stuff maybe tonight.

0 Likes

#58

Yeah, new lines disappearing is annoying. Here is a fix.
import re and then:

m = re.match("^(.*)\r?\n((\r?\n)+)$", tidied_text) if not numbers else None new_li = '</span></li>\n<li><span style=\"color:' + the_colour + '\">' if m != None: new_lines = ''.join("<li><br/></li>" for c in str(m.group(2)) if c == "\n"]) tidied_text = m.group(1) + "</span></li>\n" + new_lines + '<li><span>' + new_li else: tidied_text = tidied_text.replace('\n', new_li)

Oh and the new commit did fix the alignment issue and the scope guessing.

0 Likes

#59

Awesome, thanks.

0 Likes

#60

[quote=ā€œfacelessuserā€]Yeah, new lines disappearing is annoying. Here is a fix.
import re and then:

m = re.match("^(.*)\r?\n((\r?\n)+)$", tidied_text) if not numbers else None new_li = '</span></li>\n<li><span style=\"color:' + the_colour + '\">' if m != None: new_lines = ''.join("<li><br/></li>" for c in str(m.group(2)) if c == "\n"]) tidied_text = m.group(1) + "</span></li>\n" + new_lines + '<li><span>' + new_li else: tidied_text = tidied_text.replace('\n', new_li)

Oh and the new commit did fix the alignment issue and the scope guessing.[/quote]

Thank you, Iā€™ll have a look after work. I also plan to set the first dictionary entry to ā€˜source.langā€™: ā€˜foregroundā€™, - that is, using ā€˜default_scopeā€™ - replicating the behaviour of ST.

0 Likes