X-Git-Url: http://nitlanguage.org diff --git a/src/nitpretty.nit b/src/nitpretty.nit index c583b53..17cc649 100644 --- a/src/nitpretty.nit +++ b/src/nitpretty.nit @@ -14,211 +14,55 @@ # `nitpretty` is a tool able to pretty print Nit files. # -# Usage: -# -# nitpretty source.nit -# -# Main options: -# -# * `-o res.nit` output result into `res.nit` -# * `--diff` show diff between `source` and `res` -# * `--meld` open diff with `meld` -# * `--check` check the format of multiple source files -# * `--check --meld` perform `--check` and open `meld` for each difference -# -# ## Specification -# -# The specification of the pretty printing is described here. -# -# * Default indentation level is one `'\t'` character and -# is increased by one for each indentation level. -# * Default line max-size is 80. -# -# ### Comments -# -# There is many categories of comments: -# -# `Licence comments` are attached to the top of the file -# no blank line before, one after. -# -# ~~~nitish -# # This is a licence comment -# -# # Documentation for module `foo` -# module foo -# ~~~ -# -# `ADoc` are documentation comments attached to a `AModule`, `AClassdef`, `APropdef`. -# -# They are printed before the definition with a blank line before and no after -# at the same indentation level than the definition. -# -# ~~~nitish -# # Documentation for module `foo` -# module foo -# -# # Documentation for class `Bar` -# class Bar -# # Documentation for method `baz` -# fun baz do end -# end -# ~~~ -# -# `Block comments` are comments composed of one or more line rattached to nothing. -# They are displayed with one blank line before and after at current indent level. -# -# ~~~nitish -# -# # block -# # comment -# -# ~~~ -# -# `Attached comments` are comments attached to a production. -# They are printed as this. -# -# ~~~nitish -# fun foo do # attached comment -# end -# ~~~ -# -# `nitpretty` automatically remove multiple blanks between comments: -# -# ~~~nitish -# # Licence -# # ... -# -# # Block comment -# ~~~ -# -# ### Inlining -# -# Productions are automatically inlined when possible. -# -# Conditions: -# -# * the production must be syntactically inlinable -# * the inlined production length is less than `PrettyPrinterVisitor::max-size` -# * the production do not contains any comments -# -# ### Modules -# -# * There is a blank between the module declaration and its imports -# * There is no blank between imports and only one after -# * There is a blank between each extern block definition -# * There is a blank between each class definition -# * There is no blank line at the end of the module -# -# ~~~nitish -# # Documentation for module `foo` -# module foo -# -# import a -# # import b -# import c -# -# # Documentation for class `Bar` -# class Bar end -# -# class Baz end # not a `ADoc` comment -# ~~~ -# -# -# ### Classes -# -# * There is no blank between the class definition and its super-classes declarations -# * There is no blank between two inlined property definition -# * There is a blank between each block definition -# * There no blank line at the end of the class definition -# -# ~~~nitish -# # Documentation for class `Bar` -# class Bar end -# -# class Baz -# super Bar -# -# fun a is abstract -# private fun b do end -# -# fun c do -# # ... -# end -# end -# ~~~ -# -# Generic types have no space after or before brackets and are separated by a comma and a space: -# -# ~~~nitish -# class A[E: Type1, F: Type1] end -# ~~~ -# -# ### Blocks -# -# * Inlined productions have no blank lines between them -# * Block productions have a blank before and after -# -# ~~~nitish -# var a = 10 -# var b = 0 -# -# if a > b then -# # is positive -# print "positive" -# end -# -# print "end" -# ~~~ -# -# ### Calls and Binary Ops -# -# Arguments are always printed separated with a comma and a space: -# -# ~~~nitish -# foo(a, b, c) -# ~~~ -# -# Binary ops are always printed wrapped with spaces: -# -# ~~~nitish -# var c = 1 + 2 -# ~~~ -# -# Calls and binary ops can be splitted to fit the `max-size` constraint. -# Breaking priority is given to arguments declaration after the comma. -# -# ~~~nitish -# return foo("aaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbb", -# "cccccccccccccccccccccccccc") -# ~~~ -# -# Binary ops can also be broken to fit the `max-size` limit: -# -# ~~~nitish -# return "aaaaaaaaaaaaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbbbbbbbbbbbbb" + -# "cccccccccccccccccccccccccc" -# ~~~ -module nitpretty - +# See `man nitpretty` for more infos. import pretty redef class ToolContext + # The working directory used to store temp files. var opt_dir = new OptionString("Working directory (default is '.nitpretty')", "--dir") + # Output pretty printed code with this filename. var opt_output = new OptionString("Output name (default is pretty.nit)", "-o", "--output") + # Show diff between source and pretty printed code. var opt_diff = new OptionBool("Show diff between source and output", "--diff") + # Show diff between source and pretty printed code using meld. var opt_meld = new OptionBool("Show diff between source and output using meld", "--meld") + # --line-width + var opt_line_width = new OptionInt("Maximum length of lines (use 0 to disable automatic line breaks)", 80, "--line-width") + + # --no-inline + var opt_no_inline = new OptionBool("Disable automatic one-liners", "--no-inline") + + # Break too long string literals. + var opt_break_str = new OptionBool("Break too long string literals", "--break-strings") + + # Force `do` on the same line as the method signature. + var opt_inline_do = new OptionBool("Force do keyword on the same line as the method signature", + "--inline-do") + + # Force formatting on empty lines. + # + # By default empty lines are kept as they were typed in the file. + # When enabling this option, `nitpretty` will decide where to break lines + # and will put empty lines to separate properties and code blocks. + var opt_skip_empty = new OptionBool("Force formatting of empty lines", "--skip-empty") + + # Check formatting instead of pretty printing. + # + # This option creates a temporary pretty printed file then checks if the + # output of the diff command on the source file and the pretty printed one is + # empty. var opt_check = new OptionBool("Check format of Nit source files", "--check") end # Return result from diff between `file1` and `file2`. private fun diff(file1, file2: String): String do - var p = new IProcess("diff", "-u", file1, file2) + var p = new ProcessReader("diff", "-u", file1, file2) var res = p.read_all p.wait p.close @@ -228,9 +72,12 @@ end # process options var toolcontext = new ToolContext -toolcontext.option_context. - add_option(toolcontext.opt_dir, toolcontext.opt_output, toolcontext.opt_diff, - toolcontext.opt_meld, toolcontext.opt_check) +var opts = toolcontext.option_context +opts.add_option(toolcontext.opt_dir, toolcontext.opt_output) +opts.add_option(toolcontext.opt_diff, toolcontext.opt_meld, toolcontext.opt_check) +opts.add_option(toolcontext.opt_line_width, toolcontext.opt_break_str, toolcontext.opt_inline_do) +opts.add_option(toolcontext.opt_no_inline) +opts.add_option(toolcontext.opt_skip_empty) toolcontext.tooldescription = "Usage: nitpretty [OPTION]... \n" + "Pretty print Nit code from Nit source files." @@ -240,7 +87,7 @@ var arguments = toolcontext.option_context.rest # build model var model = new Model var mbuilder = new ModelBuilder(model, toolcontext) -var mmodules = mbuilder.parse(arguments) +var mmodules = mbuilder.parse_full(arguments) mbuilder.run_phases if mmodules.is_empty then @@ -257,13 +104,26 @@ var dir = toolcontext.opt_dir.value or else ".nitpretty" if not dir.file_exists then dir.mkdir var v = new PrettyPrinterVisitor +v.max_size = toolcontext.opt_line_width.value +if toolcontext.opt_break_str.value then + v.break_strings = true +end +if toolcontext.opt_inline_do.value then + v.inline_do = true +end +if toolcontext.opt_skip_empty.value then + v.skip_empty = true +end +if toolcontext.opt_no_inline.value then + v.no_inline = true +end + for mmodule in mmodules do - if not mbuilder.mmodule2nmodule.has_key(mmodule) then + var nmodule = mbuilder.mmodule2node(mmodule) + if nmodule == null then print " Error: no source file for module {mmodule}" return end - - var nmodule = mbuilder.mmodule2nmodule[mmodule] var file = "{dir}/{mmodule.name}.nit" var tpl = v.pretty_nmodule(nmodule) tpl.write_to_file file