// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
\page qtqml-tooling-qmlformat.html
\title qmlformat
\brief A tool that automatically formats QML files according to the QML coding
conventions.
\ingroup qtqml-tooling
\ingroup qtqml-tooling-devtools

\e qmlformat is a tool that automatically formats QML files according to
the \l{QML Coding Conventions}.

\table
\header
    \li Usage:
\row
    \li qmlformat [\l{options}] \l{arguments}
\endtable

\section1 Options and settings
\target options
You can configure qmlformat with command-line options. There are two groups of
options: those that are directly related to formatting, and those that control
the behavior of the tool.

The following options only affect the tool behavior:

\table
\header
    \li Command-line option
    \li Description
\row
    \li \c{-h}, \c{--help}
    \li Displays help on command-line options.
\row
    \li \c{--help-all}
    \li Displays help, including generic Qt options.
\row
    \li \c{-v}, \c{--version}
    \li Displays version information.
\row
    \li \c{-V}, \c{--verbose}
    \li Verbose mode. Outputs more detailed information.
\row
    \li \c{--write-defaults}
    \li Writes default settings to \c{.qmlformat.ini} and exits.
\row
    \li \c{--output-options}
    \li Output all available options, their default value, and a hint of values
        or types.
\row
    \li \c{--ignore-settings}
    \li Ignores all settings files and only takes command-line options into
        consideration.
\row
    \li \c{-i}, \c{--inplace}
    \li Edit file in-place instead of outputting to stdout.
\row
    \li \c{-f}, \c{--force}
    \li Continue even if an error occurs.
\row
    \li \c{-F}, \c{--files <file>}
    \li Format all files listed in file, in-place.
\endtable

The next group of options controls how files should be formatted, and can also
be controlled through a \l{Settings File}{settings file}.

For boolean options, pass the flag on the command line or set the variable to
\c{true} in the settings file to enable the behavior.

\table
\header
    \li Command-line option
    \li Setting name
    \li Default value
    \li Description
\row
    \li \c{-t}, \c{--tabs}
    \li UseTabs
    \li false
    \li Use tabs instead of spaces.
\row
    \li \c{-w}, \c{--indent-width <width>}
    \li IndentWidth
    \li 4
    \li How many spaces are used when indenting.
\row
    \li \c{-W}, \c{--column-width <width>}
    \li MaxColumnWidth
    \li -1
    \li Breaks the line into multiple lines if it exceeds the specified width.
        Use \c{-1} to disable line wrapping (default).
\row
    \li \c{-n}, \c{--normalize}
    \li NormalizeOrder
    \li false
    \li Reorders and sorts the attributes of objects according to
        the QML coding guidelines.
        Incompatible with \c{--group-attributes-together}.
\row
    \li \c{-l}, \c{--newline <newline>}
    \li NewlineType
    \li native
    \li Overrides the new line format to use (\c {native}, \c {macos},
        \c {unix}, \c {windows}).
\row
    \li \c{-S}, \c{--sort-imports}
    \li SortImports
    \li false
    \li Sort imports alphabetically
        (this might change semantics if a given name identifies types in
        multiple modules).
\row
    \li \c{--objects-spacing}
    \li ObjectsSpacing
    \li false
    \li Ensures spaces between objects (only works with \c{normalize} or
        \c{group-attributes-together}).
\row
    \li \c{--functions-spacing}
    \li FunctionsSpacing
    \li false
    \li Ensures spaces between functions (only works with \c{normalize} or
        \c{group-attributes-together}).
\row
    \li \c{--group-attributes-together}
    \li GroupAttributesTogether
    \li false
    \li Reorders but does not sort the attributes of objects according to
        the QML coding guidelines.
        Incompatible with \c{--normalize}.
\row
    \li \c{--single-line-empty-objects}
    \li SingleLineEmptyObjects
    \li false
    \li Writes empty objects on a single line (only works with \c{normalize}
        or \c{group-attributes-together}).
\row
    \li \c{--semicolon-rule}
    \li SemicolonRule
    \li always
    \li Customizes the addition of semicolons at the end of JS statements
        (\c{always}, \c{essential}). See \l{Semicolon Rule} for more details.
\endtable

\section1 Arguments
\target arguments
\table
\header
    \li Arguments:
\row
    \li filenames
\endtable

\section1 Usage
\e qmlformat is flexible and can be configured according to your needs. \e qmlformat should be
deployed in a sandbox, container, or other safe environment when running on untrusted code, for
example when formatting QML files during testing in a public CI.

\section2 Output
qmlformat writes the formatted version of the file to stdout.
To have your file updated in-place, specify the \c{-i} flag.

\section2 Grouping Properties, Functions, and Signals Together
With \c{-n} or \c{--normalize} flag, qmlformat groups and sorts all properties,
functions, and signals by name, instead of retaining the existing order.

For example:

\qml
import QtQuick

QtObject {
    signal s2()
    property int h
    function z() {}
    property int w
    function y() {}
    id: asdf
    signal s1()

    property Item myItem2: Item {
        TextEdit {}
        Rectangle {}
    }
    property Item myItem: Item {
        Rectangle {}
        TextEdit {}
    }
}
\endqml

is formatted to:

\qml
import QtQuick

QtObject {
    id: asdf

    property int h
    property Item myItem: Item {
        Rectangle {
        }
        TextEdit {
        }
    }
    property Item myItem2: Item {
        TextEdit {
        }
        Rectangle {
        }
    }
    property int w

    signal s1
    signal s2

    function y() {
    }
    function z() {
    }
}
\endqml

To group the attributes without sorting by name, use
\c{--group-attributes-together} instead.

This formats the previous snippet into:

\qml
import QtQuick

QtObject {
    id: asdf

    property int h
    property int w
    property Item myItem2: Item {
        TextEdit {
        }
        Rectangle {
        }
    }
    property Item myItem: Item {
        Rectangle {
        }
        TextEdit {
        }
    }

    signal s2
    signal s1

    function z() {
    }
    function y() {
    }
}
\endqml

This option takes precedence over \c{--normalize}.

\section2 Settings File
You can configure \e qmlformat by including a settings file (\c{.qmlformat.ini})
in your project source or in the parent directories of your project source
folder. You can obtain a default settings file by passing the
\c{--write-defaults} flag. This generates the \c{.qmlformat.ini} file in the
current working directory.

\warning \c{--write-defaults} overwrites all existing settings and comments.

\section2 Formatting a List of Files
While you can pass a list of files to be formatted as arguments, qmlformat
provides the \c {-F} option to format a set of files stored in a file. In this
case, formatting happens inplace.

\code
    // FileList.txt
    main.qml
    mycomponent.qml
\endcode

To use this list:

\code
    qmlformat -F FileList.txt
\endcode

\note If the file contains an invalid entry, for example, a file path that
doesn't exist or a valid file path but the content is an invalid QML document,
qmlformat reports an error for that entry and continues to format
the remaining valid entries in place.

\warning If you provide the \c{-F} option, qmlformat ignores the positional
    arguments.

\section2 Semicolon Rule
The \c{--semicolon-rule} option allows you to customize the addition of
semicolons at the end of JS statements.

The following values are accepted:
\list
    \li \c{always} - Always add semicolons (default).
    \li \c{essential} - Remove semicolons unless omitting them would cause
        issues.
\endlist

\section1 Disabling Formatting with Comments
You can temporarily disable qmlformat using special comments.

\list
    \li \c {// qmlformat off} turns off formatting from that line onward.
    \li \c {// qmlformat on} turns on formatting after you turned it off.
\endlist

This lets you preserve hand-tuned code or complex structures without qmlformat
changing their layout. Formatting remains off until the next
\c {// qmlformat on} comment, or until the end of the file if no re-enable
is found.

Keep the following in mind when using formatting directives:
\list
  \li Directives must be on their own line.
  \li Nested directives are not supported. Only the first \c {// qmlformat off}
      and the next \c {// qmlformat on} are considered. Any additional
      directives inside a disabled region are ignored.
  \li Directives are ignored in normalized formatting mode, when
      \c{sortImports} is enabled, or when any option that reorders the original
      document is used. In these cases, formatting is always applied.
\endlist

*/
