Sublime Forum

Compact whitespace

#1

How can I select text in a document(like an HTML document) and format it as “compact” (remove returns and extra whitespace between tags)

In BBEdit, I choose Format > Compact

0 Likes

#2

use the regreplace plugin.

0 Likes

#3

Somehow that doesn’t sound as simple as Format > Compact…

Or is there a preset?

0 Likes

#4

Have you used regreplace? You set up a regex, name it Compact, then when you want to use it, you just open the command palette and type “compact”. Voila.

0 Likes

#5

Can you be more specific? I have never used bbedit.

Do you want remove all empty whitespace lines in a file removed? What exactly are you looking for. Without seeing an example of what you mean, I am not sure I can help. RegReplace does not currently search and replace within a selection, but it could in the future. I can help you construct a rule for RegReplace, if I know exactly what it is you want.

RegReplace either searches a whole file, or finds the first instance after your cursor (you tell it what you want it to do). I can help if you can give me a good example. If you absolutely need it to work under a selection, I can look into adding it in the future.

0 Likes

#6

I tried out bbedit, and I think I understand what it is doing.

This might do what you want in an HTML file.

Add this to your replacement definitions in RegReplace. You can see I am avoiding PHP source code and javascript; you can add additional if you like. You can also tweak this further if it doesn’t do exactly what you want.

reg_replace.sublime-settings

"trim_html_whitespace" : { "find": "\\s*(<|>)\\s*", "replace": "\\1", "scope_filter": "-source.js","-source.php","-string", "-comment"], "greedy": true }, "reduce_spaces_to_one": { "find": " \t]+", "replace": " ", "scope_filter": "-source.js","-source.php","-string", "-comment"], "greedy": true }, "remove_all_newlines": { "find": "\r\n]*", "replace": "", "scope_filter": "-source.js","-source.php"], "greedy": true },

This is the command that you would add to the command palette.

Default.sublime-commands

{ "caption": "Format: Compact", "command": "reg_replace", "args": {"replacements": "trim_html_whitespace", "reduce_spaces_to_one", "remove_all_newlines"]} },

0 Likes

#7

Thanks, but for some reason the command does nothing for me. I copied your code into the 2 files. The command shows on shift-command-p

But when I run it, nothing changes in my test doc (attached).
foo.html.zip (1.72 KB)

0 Likes

#8

Did you install RegReplace?

Check if your reg_replace.sublime-settings and Defualt.sublime-commands file is sound (Are there trailing commas, or something like that? If there are, remove them)

What syntax is selected when viewing your HTML. Mine is either HTML, or HTML 5.

I just ran it on my system, and it worked fine. I attached the output I am getting. Also let me know if the output I got is what you are expected to get.
foo-compact.html.zip (2.09 KB)

0 Likes

#9

I installed RegReplace.

I added the first code block to …/Packages/RegReplace/reg_replace.sublime-settings

I pasted it right after the existing

	// Highlight style? (outline|solid|underline)
	"find_highlight_style": "outline", [/code]

I had to delete the trailing comma after your block: 
[code]  "greedy": true
      },

I added the second code block to …/Packages/RegReplace/Default.sublime-commands and I also tried adding a Default.sublime-commands to my User folder, with your command.

The command shows up either way. The replacements never happen. I’ve attached these 2 files.
rereplacefiles.zip (2.4 KB)

0 Likes

#10

Ahh. You have to put them under the replacements object. You can see there are some already under there. I have posted the entire modified file here.

[code]////////////////////////////////
// Regex with scope qualifiers//
////////////////////////////////
// Required parameters:
// find: Regex description of what you would like to target.
//
// Optional parameters:
// replace: description of what you would like to replace target with.
// Variables are okay for non-literal searches and are done by escaping
// the selection number \1 etc. Default value is “\0”.
// literal: Boolean setting to define whether the find and replace is literal or not.
// Default is false.
// greedy: Boolean setting to define whether search is greedy or not. Default is true.
// case: Boolean defining case sensitivity. True equals sensitive. Defualt is true.
// scope_filter: an array of scope qualifiers for the match.
// - Any instance of scope qualifies match: scope.name
// - Entire match of scope qualifies match: !scope.name
// - Any instance of scope disqualifies match: -scope.name
// - Entire match of scope disqualifies match: -!scope.name

//////////////////////////////////////////////////////////////
// Scope search with regex qualifier (also find and replace)//
//////////////////////////////////////////////////////////////
// Required parameters:
// scope: scope you would like to target
//
// Optional parameters:
// find: regex description that is to be applied to the scope
// to qualify. Also can be used to find and replace
// within the found scope. Default is None.
// replace: description of what you would like to replace within the scope.
// Default value is “\0”.
// literal: Boolean setting to define whether the find and replace is literal or not.
// Default is false.
// greedy_replace: Boolean setting to define whether regex search is greedy or not. Default is true.
// greedy_scope: Boolean setting to define whether scope search is greedy or not. Default is true.
// case: Boolean setting to define whether regex search is case sensitive. Default is true.
// multi_pass_regex:Boolean setting to define whether there will be multiple sweeps on the scope region
// region to find and replace all instances of the regex, when regex cannot be formatted
// to find all instances in a greedy fashion. Default is false.
{
“replacements”: {
// added for format-compact html
“trim_html_whitespace”: {
“find”: “\s*(<|>)\s*”,
“replace”: “\1”,
“scope_filter”: “-source.js”,"-source.php","-string", “-comment”],
“greedy”: true
},
“reduce_spaces_to_one”: {
“find”: " \t]+",
“replace”: " “,
“scope_filter”: “-source.js”,”-source.php","-string", “-comment”],
“greedy”: true
},
“remove_all_newlines”: {
“find”: “\r\n]",
“replace”: “”,
“scope_filter”: “-source.js”,"-source.php"],
“greedy”: true
},
// Example replacements
“html5_remove_deprecated_type_attr”: {
“find”: "(<(style|script)^>]
)\stype=(”|’)text/(css|javascript)("|’)(^>]>)",
“replace”: “\1\6”,
“greedy”: true,
“case”: false
},
// remove_json_dangling_commas
“remove_json_dangling_commas”: {
“find”: ",(\r\n\s]
)(\]|\})",
“replace”: “\1\2”,
“greedy”: true,
“scope_filter”: “-string”, “-comment”]
},
“remove_html_comments”: {
“find”: “”,
“replace”: “”,
“scope_filter”: “!comment”],
“greedy”: true,
“case”: true
},
“remove_trailing_spaces”: {
“find”: " \t]+$",
“replace”: “”,
“greedy”: true,
“case”: true
},
// Delete a comment or comment blocks
“remove_comments”: {
“scope”: “comment”,
“find” : “(^\n\r]+)”,
“replace”: “”,
“greedy_replace”: true
}
},

// If on_save is true, RegReplace will search through the file patterns listed below right before a file is saved,
// if the file name matches a file pattern, the sequence will be applied before the file is saved.
// RegReplace will apply all sequences that apply to a given file in the order they appear below.
"on_save": false,
"on_save_sequences": 
	// An example on_save event that removes dangling commas from json files
	// - file_regex: an array of regex strings that must match the file for the sequence to be applied
	// - case: regex case sensitivity (true|false) false is default (this setting is optional)
	// - file_pattern: an array of file patterns that must match for the sequence to be applied
	// - sequence: an array of replacement definitions to be applied on saving the file
	{
		"file_regex": ".*\\.sublime-(settings|commands|menu|keymap|mousemap|theme|build|project|completions|commands)"],
		"file_pattern": "*.json"],
		"sequence": "remove_json_dangling_commas"]
	},
	// An example on_save_sequence that targets all files and trims trailing spaces
	// - file_pattern: an array of file patterns that must match for the sequence to be applied
	// - sequence: an array of replacement definitions to be applied on saving the file
	{"file_pattern": "*"], "sequence": "remove_trailing_spaces"]}
],

// Show replace results in panel
"results_in_panel": false,

// Maximum sweep threshold for multi-pass
"multi_pass_max_sweeps": 100,

// Color? (scope)
"find_highlight_color": "invalid",

// Highlight style? (outline|solid|underline)
"find_highlight_style": "outline"

}
[/code]

0 Likes

#11

Thank you. I thought I was losing my mind.

Works now, albeit a bit slowly.

0 Likes

#12

Yeah, the actual searching is pretty quick, if you configure the command to ask for confirmation before replacing (add the “find_only” argument):

{ "caption": "Format: Compact", "command": "reg_replace", "args": {"replacements": "trim_html_whitespace", "reduce_spaces_to_one", "remove_all_newlines"], "find_only": true} },

It highlights the regions to replace pretty quick, but replacing all of the regions through the ST2 API usually takes a bit. I may see if there is any way to speed that up in the future, but I might not be able to. The more regions or the bigger the buffer that must be replaced, the longer it takes.

Glad it works for you though

EDIT
Replace this regex replacement; this is much faster (instead of targeting every white space, we only target the white space that isn’t already reduced to one; we also target tabs. This means less regions to replace; therefore, faster):

"reduce_spaces_to_one": { "find": " ]{2,}|\t]+", "replace": " ", "scope_filter": "-source.js","-source.php","-string", "-comment"], "greedy": true },

0 Likes

#13

yes, that was much faster, thanks!

0 Likes

#14

Was a little hasty this morning. Final revision of this. Tabs need to be evaluated before spaces, figured I should avoid CSS as well. I also renamed some of the replacements to be more descriptive.

"trim_html_whitespace": { "find": "\\s*(<|>)\\s*", "replace": "\\1", "scope_filter": "-source.js","-source.php", "-source.css","-string", "-comment"], "greedy": true }, "html_compact_tab_whitespace": { "find": "\t]+", "replace": " ", "scope_filter": "-source.js","-source.php", "-source.css", "-string", "-comment"], "greedy": true }, "html_compact_space_whitespace": { "find": " ]{2,}", "replace": " ", "scope_filter": "-source.js","-source.php", "-source.css", "-string", "-comment"], "greedy": true }, "html_remove_all_newlines": { "find": "\r\n]*", "replace": "", "scope_filter": "-source.js","-source.php", "-source.css"], "greedy": true },

New command is as follows:

// HTML Compact Format { "caption": "Format: Compact", "command": "reg_replace", "args": {"replacements": "trim_html_whitespace", "html_compact_tab_whitespace", "html_compact_space_whitespace", "html_remove_all_newlines"]} },

Okay, I am done fooling with this :smile: .

0 Likes

#15

[quote=“facelessuser”]Was a little hasty this morning. Final revision of this. Tabs need to be evaluated before spaces, figured I should avoid CSS as well. I also renamed some of the replacements to be more descriptive.

"trim_html_whitespace": { "find": "\\s*(<|>)\\s*", "replace": "\\1", "scope_filter": "-source.js","-source.php", "-source.css","-string", "-comment"], "greedy": true }, "html_compact_tab_whitespace": { "find": "\t]+", "replace": " ", "scope_filter": "-source.js","-source.php", "-source.css", "-string", "-comment"], "greedy": true }, "html_compact_space_whitespace": { "find": " ]{2,}", "replace": " ", "scope_filter": "-source.js","-source.php", "-source.css", "-string", "-comment"], "greedy": true }, "html_remove_all_newlines": { "find": "\r\n]*", "replace": "", "scope_filter": "-source.js","-source.php", "-source.css"], "greedy": true },

New command is as follows:

// HTML Compact Format { "caption": "Format: Compact", "command": "reg_replace", "args": {"replacements": "trim_html_whitespace", "html_compact_tab_whitespace", "html_compact_space_whitespace", "html_remove_all_newlines"]} },

Okay, I am done fooling with this :smile: .[/quote]

Fantastic! Thanks

0 Likes