Skip to content

Commit

Permalink
Add eol = "auto" option as the default behavior.
Browse files Browse the repository at this point in the history
Fixes #829
  • Loading branch information
bitwiseman committed Jan 19, 2016
1 parent 98411a4 commit 796f080
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 44 deletions.
28 changes: 19 additions & 9 deletions js/lib/beautify.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,11 @@
// Matches a whole line break (where CRLF is considered a single
// line break). Used to count lines.

var lineBreak = exports.lineBreak = /\r\n|[\n\r\u2028\u2029]/g;
// in javascript, these two differ
// in python they are the same, different methods are called on them
var lineBreak = exports.lineBreak = /\r\n|[\n\r\u2028\u2029]/;
var allLineBreaks = exports.allLineBreaks = new RegExp(lineBreak.source, 'g');


// Test whether a given character code starts an identifier.

Expand Down Expand Up @@ -265,10 +269,9 @@
opt.brace_style = "expand";
}


opt.indent_size = options.indent_size ? parseInt(options.indent_size, 10) : 4;
opt.indent_char = options.indent_char ? options.indent_char : ' ';
opt.eol = options.eol ? options.eol : '\n';
opt.eol = options.eol ? options.eol : 'auto';
opt.preserve_newlines = (options.preserve_newlines === undefined) ? true : options.preserve_newlines;
opt.break_chained_methods = (options.break_chained_methods === undefined) ? false : options.break_chained_methods;
opt.max_preserve_newlines = (options.max_preserve_newlines === undefined) ? 0 : parseInt(options.max_preserve_newlines, 10);
Expand Down Expand Up @@ -297,6 +300,13 @@
opt.indent_size = 1;
}

if (opt.eol === 'auto') {
opt.eol = '\n';
if (js_source_text && acorn.lineBreak.test(js_source_text || '')) {
opt.eol = js_source_text.match(acorn.lineBreak)[0];
}
}

opt.eol = opt.eol.replace(/\\r/, '\r').replace(/\\n/, '\n')

//----------------------------------
Expand Down Expand Up @@ -402,10 +412,10 @@

// we could use just string.split, but
// IE doesn't like returning empty strings
function split_newlines(s) {
function split_linebreaks(s) {
//return s.split(/\x0d\x0a|\x0a/);

s = s.replace(/\x0d/g, '');
s = s.replace(acorn.allLineBreaks, '\n');
var out = [],
idx = s.indexOf("\n");
while (idx !== -1) {
Expand Down Expand Up @@ -1237,7 +1247,7 @@
return;
}

var lines = split_newlines(current_token.text);
var lines = split_linebreaks(current_token.text);
var j; // iterator for this case
var javadoc = false;
var starless = false;
Expand Down Expand Up @@ -1796,7 +1806,7 @@
comment += comment_match[0];
parser_pos += comment_match[0].length;
}
comment = comment.replace(acorn.lineBreak, '\n');
comment = comment.replace(acorn.allLineBreaks, '\n');
return [comment, 'TK_BLOCK_COMMENT', directives];
}
// peek for comment // ...
Expand Down Expand Up @@ -1880,7 +1890,7 @@
var xmlLength = match ? match.index + match[0].length : xmlStr.length;
xmlStr = xmlStr.slice(0, xmlLength);
parser_pos += xmlLength - 1;
xmlStr = xmlStr.replace(acorn.lineBreak, '\n');
xmlStr = xmlStr.replace(acorn.allLineBreaks, '\n');
return [xmlStr, "TK_STRING"];
}
} else {
Expand Down Expand Up @@ -1978,7 +1988,7 @@
if(template_match) {
c = template_match[0];
parser_pos += c.length - 1;
c = c.replace(acorn.lineBreak, '\n');
c = c.replace(acorn.allLineBreaks, '\n');
return [c, 'TK_STRING'];
}
}
Expand Down
3 changes: 2 additions & 1 deletion js/lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ function usage(err) {
' -s, --indent-size Indentation size [4]',
' -c, --indent-char Indentation character [" "]',
' -t, --indent-with-tabs Indent with tabs, overrides -s and -c',
' -e, --eol Character(s) to use as line terminators. (default newline - "\\n")',
' -e, --eol Character(s) to use as line terminators.',
' [first newline in file, otherwise "\\n]',
' -n, --end-with-newline End output with newline'
];

Expand Down
21 changes: 21 additions & 0 deletions js/test/shell-smoke-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,28 @@ test_cli_js_beautify()
exit 1
}

# ensure new line settings work
$CLI_SCRIPT -o /tmp/js-beautify-mkdir/js-beautify-n.js --eol '\n' $SCRIPT_DIR/../bin/js-beautify.js
$CLI_SCRIPT -o /tmp/js-beautify-mkdir/js-beautify-rn.js --eol '\r\n' /tmp/js-beautify-mkdir/js-beautify-n.js

diff -q /tmp/js-beautify-mkdir/js-beautify-n.js /tmp/js-beautify-mkdir/js-beautify-rn.js && {
diff /tmp/js-beautify-mkdir/js-beautify-n.js /tmp/js-beautify-mkdir/js-beautify-rn.js | cat -t -e
echo "js-beautify output for /tmp/js-beautify-mkdir/js-beautify-n.js and /tmp/js-beautify-mkdir/js-beautify-rn.js was expected to be different."
exit 1
}

$CLI_SCRIPT /tmp/js-beautify-mkdir/js-beautify-n.js | diff -q /tmp/js-beautify-mkdir/js-beautify-n.js - || {
echo "js-beautify output for /tmp/js-beautify-mkdir/js-beautify-n.js was expected to be unchanged."
exit 1
}

$CLI_SCRIPT --eol 'auto' /tmp/js-beautify-mkdir/js-beautify-rn.js | diff -q /tmp/js-beautify-mkdir/js-beautify-rn.js - || {
echo "js-beautify output for /tmp/js-beautify-mkdir/js-beautify-rn.js was expected to be unchanged."
exit 1
}

# ensure unchanged files are not overwritten
$CLI_SCRIPT -o /tmp/js-beautify-mkdir/js-beautify.js $SCRIPT_DIR/../bin/js-beautify.js
cp -p /tmp/js-beautify-mkdir/js-beautify.js /tmp/js-beautify-mkdir/js-beautify-old.js
touch /tmp/js-beautify-mkdir/js-beautify.js
sleep 2
Expand Down
72 changes: 41 additions & 31 deletions python/jsbeautifier/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import print_function
import sys
import os
import io
import getopt
import re
import string
Expand Down Expand Up @@ -64,7 +65,7 @@ def __init__(self):
self.indent_size = 4
self.indent_char = ' '
self.indent_with_tabs = False
self.eol = '\n'
self.eol = 'auto'
self.preserve_newlines = True
self.max_preserve_newlines = 10
self.space_in_paren = False
Expand Down Expand Up @@ -186,7 +187,10 @@ def __init__(self):
# Matches a whole line break (where CRLF is considered a single
# line break). Used to count lines.

# in javascript, these two differ
# in python they are the same, different methods are called on them
self.lineBreak = re.compile(self.six.u("\r\n|[\n\r\u2028\u2029]"))
self.allLineBreaks = self.lineBreak


# Test whether a given character code starts an identifier.
Expand Down Expand Up @@ -241,7 +245,7 @@ def beautify_file(file_name, opts = default_options() ):
if file_name == '-': # stdin
stream = sys.stdin
else:
stream = open(file_name)
stream = io.open(file_name, 'rt', newline='')

return beautify(''.join(stream.readlines()), opts)

Expand All @@ -259,23 +263,24 @@ def usage(stream=sys.stdout):
Input options:
-i, --stdin read input from stdin
-i, --stdin Read input from stdin
Output options:
-s, --indent-size=NUMBER indentation size. (default 4).
-c, --indent-char=CHAR character to indent with. (default space).
-e, --eol=STRING character(s) to use as line terminators. (default newline - "\\n")
-s, --indent-size=NUMBER Indentation size. (default 4).
-c, --indent-char=CHAR Character to indent with. (default space).
-e, --eol=STRING Character(s) to use as line terminators.
(default first newline in file, otherwise "\\n")
-t, --indent-with-tabs Indent with tabs, overrides -s and -c
-d, --disable-preserve-newlines do not preserve existing line breaks.
-P, --space-in-paren add padding spaces within paren, ie. f( a, b )
-d, --disable-preserve-newlines Do not preserve existing line breaks.
-P, --space-in-paren Add padding spaces within paren, ie. f( a, b )
-E, --space-in-empty-paren Add a single space inside empty paren, ie. f( )
-j, --jslint-happy more jslint-compatible output
-a, --space_after_anon_function add a space before an anonymous function's parens, ie. function ()
-b, --brace-style=collapse brace style (collapse, expand, end-expand)
-k, --keep-array-indentation keep array indentation.
-r, --replace write output in-place, replacing input
-o, --outfile=FILE specify a file to output to (default stdout)
-j, --jslint-happy More jslint-compatible output
-a, --space_after_anon_function Add a space before an anonymous function's parens, ie. function ()
-b, --brace-style=collapse Brace style (collapse, expand, end-expand)
-k, --keep-array-indentation Keep array indentation.
-r, --replace Write output in-place, replacing input
-o, --outfile=FILE Specify a file to output to (default stdout)
-f, --keep-function-indentation Do not re-indent function bodies defined in var lines.
-x, --unescape-strings Decode printable chars encoded in \\xNN notation.
-X, --e4x Pass E4X xml literals through untouched
Expand All @@ -289,9 +294,9 @@ def usage(stream=sys.stdout):
installed. May be useful with some obfuscated
script but poses a potential security issue.
-l, --indent-level=NUMBER initial indentation level. (default 0).
-l, --indent-level=NUMBER Initial indentation level. (default 0).
-h, --help, --usage prints this help statement.
-h, --help, --usage Prints this help statement.
-v, --version Show the version
""", file=stream)
Expand All @@ -311,8 +316,8 @@ class Beautifier:
def __init__(self, opts = default_options() ):

self.opts = copy.copy(opts)
self.blank_state()
self.acorn = Acorn()
self.blank_state()

def blank_state(self, js_source_text = None):

Expand All @@ -332,6 +337,11 @@ def blank_state(self, js_source_text = None):
self.opts.indent_char = "\t"
self.opts.indent_size = 1

if self.opts.eol == 'auto':
self.opts.eol = '\n'
if self.acorn.lineBreak.search(js_source_text or ''):
self.opts.eol = self.acorn.lineBreak.search(js_source_text).group()

self.opts.eol = self.opts.eol.replace('\\r', '\r').replace('\\n', '\n')

self.indent_string = self.opts.indent_char * self.opts.indent_size
Expand Down Expand Up @@ -1141,7 +1151,7 @@ def handle_block_comment(self, current_token):
self.output.space_before_token = True
return

lines = self.acorn.lineBreak.split(current_token.text)
lines = self.acorn.allLineBreaks.split(current_token.text)
javadoc = False
starless = False
last_indent = current_token.whitespace_before
Expand Down Expand Up @@ -1601,7 +1611,7 @@ def __tokenize_next(self):
comment_match = self.directives_end_ignore_pattern.match(self.input, self.parser_pos)
comment += comment_match.group(0)
self.parser_pos += len(comment_match.group(0))
comment = re.sub(self.acorn.lineBreak, '\n', comment)
comment = re.sub(self.acorn.allLineBreaks, '\n', comment)
return comment, 'TK_BLOCK_COMMENT', directives

if self.input[self.parser_pos] == '/': # peek // comment
Expand Down Expand Up @@ -1674,7 +1684,7 @@ def __tokenize_next(self):
xmlLength = len(xmlStr)

self.parser_pos += xmlLength - 1
xmlStr = re.sub(self.acorn.lineBreak, '\n', xmlStr[:xmlLength])
xmlStr = re.sub(self.acorn.allLineBreaks, '\n', xmlStr[:xmlLength])
return xmlStr, 'TK_STRING'

else:
Expand Down Expand Up @@ -1726,7 +1736,7 @@ def __tokenize_next(self):
while self.parser_pos < len(self.input) and self.acorn.isIdentifierStart(ord(self.input[self.parser_pos])):
resulting_string += self.input[self.parser_pos]
self.parser_pos += 1
resulting_string = re.sub(self.acorn.lineBreak, '\n', resulting_string)
resulting_string = re.sub(self.acorn.allLineBreaks, '\n', resulting_string)

return resulting_string, 'TK_STRING'

Expand Down Expand Up @@ -1768,7 +1778,7 @@ def __tokenize_next(self):
if template_match:
c = template_match.group(0)
self.parser_pos += len(c) - 1
c = re.sub(self.acorn.lineBreak, '\n', c)
c = re.sub(self.acorn.allLineBreaks, '\n', c)
return c, 'TK_STRING'


Expand Down Expand Up @@ -1807,7 +1817,7 @@ def __tokenize_next(self):

def isFileDifferent(filepath, expected):
try:
return (''.join(open(filepath).readlines()) != expected)
return (''.join(io.open(filepath, 'rt', newline='').readlines()) != expected)
except:
return True

Expand Down Expand Up @@ -1895,19 +1905,19 @@ def main():
pretty = beautify_file(file, js_options)

if outfile == 'stdout':
# python automatically converts newlines in text to windows format
# uncomment this to make it not convert.
# if sys.platform == "win32":
# import msvcrt
# msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
# python automatically converts newlines in text to "\r\n" when on windows
# switch to binary to prevent this
if sys.platform == "win32":
import msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

sys.stdout.write(pretty)
else:
if isFileDifferent(outfile, pretty):
mkdir_p(os.path.dirname(outfile))
# python automatically converts newlines in text to windows format
# Change 'w' to 'wb' to make it not convert.
with open(outfile, 'w') as f:
# python automatically converts newlines in text to "\r\n" when on windows
# switch to binary to prevent this
with io.open(outfile, 'wt', newline='') as f:
f.write(pretty)

except Exception as ex:
Expand Down
24 changes: 21 additions & 3 deletions python/jsbeautifier/tests/shell-smoke-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ test_cli_js_beautify()
CLI_SCRIPT=$SCRIPT_DIR/../../js-beautify

$CLI_SCRIPT $SCRIPT_DIR/../../../js/bin/js-beautify.js > /dev/null || {
echo "js-beautify output for $SCRIPT_DIR/../bin/js-beautify.js was expected succeed."
echo "js-beautify output for $SCRIPT_DIR/../../../js/bin/js-beautify.js was expected succeed."
exit 1
}

Expand All @@ -75,7 +75,6 @@ test_cli_js_beautify()
# On windows python automatically converts newlines to windows format
# This occurs on both pipes and files.
# As a short-term workaround, disabling these two tests on windows.
if [[ "$OSTYPE" != "msys" ]]; then
$CLI_SCRIPT $SCRIPT_DIR/../../../js/bin/js-beautify.js | diff $SCRIPT_DIR/../../../js/bin/js-beautify.js - || {
$CLI_SCRIPT $SCRIPT_DIR/../../../js/bin/js-beautify.js | diff $SCRIPT_DIR/../../../js/bin/js-beautify.js - | cat -t -e
echo "js-beautify output for $SCRIPT_DIR/../../../js/bin/js-beautify.js was expected to be unchanged."
Expand All @@ -88,7 +87,26 @@ test_cli_js_beautify()
echo "js-beautify output for $SCRIPT_DIR/../../../js/bin/js-beautify.js should have been created in /tmp/js-beautify-mkdir/js-beautify.js."
exit 1
}
fi

# ensure new line settings work
$CLI_SCRIPT -o /tmp/js-beautify-mkdir/js-beautify-n.js -e '\n' $SCRIPT_DIR/../../../js/bin/js-beautify.js
$CLI_SCRIPT -o /tmp/js-beautify-mkdir/js-beautify-rn.js -e '\r\n' /tmp/js-beautify-mkdir/js-beautify-n.js

diff -q /tmp/js-beautify-mkdir/js-beautify-n.js /tmp/js-beautify-mkdir/js-beautify-rn.js && {
diff /tmp/js-beautify-mkdir/js-beautify-n.js /tmp/js-beautify-mkdir/js-beautify-rn.js | cat -t -e
echo "js-beautify output for /tmp/js-beautify-mkdir/js-beautify-n.js and /tmp/js-beautify-mkdir/js-beautify-rn.js was expected to be different."
exit 1
}

$CLI_SCRIPT /tmp/js-beautify-mkdir/js-beautify-n.js | diff -q /tmp/js-beautify-mkdir/js-beautify-n.js - || {
echo "js-beautify output for /tmp/js-beautify-mkdir/js-beautify-n.js was expected to be unchanged."
exit 1
}

$CLI_SCRIPT --eol 'auto' /tmp/js-beautify-mkdir/js-beautify-rn.js | diff -q /tmp/js-beautify-mkdir/js-beautify-rn.js - || {
echo "js-beautify output for /tmp/js-beautify-mkdir/js-beautify-rn.js was expected to be unchanged."
exit 1
}

# ensure unchanged files are not overwritten
$CLI_SCRIPT -o /tmp/js-beautify-mkdir/js-beautify.js $SCRIPT_DIR/../../../js/bin/js-beautify.js
Expand Down

0 comments on commit 796f080

Please sign in to comment.