diff --git a/main.go b/main.go
index 0b674a05..573c9355 100644
--- a/main.go
+++ b/main.go
@@ -7,7 +7,6 @@ import (
"html/template"
"io/ioutil"
"log"
- "math/rand"
"net/http"
"os"
"os/signal"
@@ -36,11 +35,10 @@ type Specification struct {
var (
prettyCfg = tree.DefaultPrettyCfg()
+ flagExpanded = flag.Bool("expanded", false, "use a verbose, expansive format")
flagPrintWidth = flag.Int("print-width", 60, "line length where sqlfmt will try to wrap")
flagUseSpaces = flag.Bool("use-spaces", false, "indent with spaces instead of tabs")
flagTabWidth = flag.Int("tab-width", 4, "number of spaces per indentation level")
- flagNoSimplify = flag.Bool("no-simplify", false, "don't simplify the output")
- flagAlign = flag.Bool("align", false, "right-align keywords")
flagStmts = flag.StringArray("stmt", nil, "instead of reading from stdin, specify statements as arguments")
flagHelp = flag.BoolP("help", "h", false, "display help")
flagVersion = flag.BoolP("version", "v", false, "display version")
@@ -113,9 +111,11 @@ func runCmd() error {
cfg.UseTabs = !*flagUseSpaces
cfg.LineWidth = *flagPrintWidth
cfg.TabWidth = *flagTabWidth
- cfg.Simplify = !*flagNoSimplify
- cfg.Align = tree.PrettyNoAlign
- if *flagAlign {
+ if *flagExpanded {
+ cfg.Simplify = false
+ cfg.Align = tree.PrettyNoAlign
+ } else {
+ cfg.Simplify = false
cfg.Align = tree.PrettyAlignAndDeindent
}
@@ -323,15 +323,10 @@ func fmtSQLRequest(r *http.Request) (string, error) {
if err != nil {
return "", err
}
- simplify, err := parseBool(r.FormValue("simplify"))
+ expanded, err := parseBool(r.FormValue("expanded"))
if err != nil {
return "", err
}
- align, err := strconv.Atoi(r.FormValue("align"))
- if err != nil {
- return "", err
- }
- casemode := caseModes[r.FormValue("case")]
spaces, err := parseBool(r.FormValue("spaces"))
if err != nil {
return "", err
@@ -341,31 +336,16 @@ func fmtSQLRequest(r *http.Request) (string, error) {
pcfg.LineWidth = n
pcfg.UseTabs = !spaces
pcfg.TabWidth = tabWidth
- pcfg.Simplify = simplify
- pcfg.Align = tree.PrettyAlignMode(align)
- pcfg.Case = casemode
-
- return fmtsql(pcfg, []string{sql})
-}
-
-var caseModes = map[string]func(string) string{
- "upper": strings.ToUpper,
- "lower": strings.ToLower,
- "title": titleCase,
- "spongebob": spongeBobCase,
-}
-
-func titleCase(s string) string {
- return strings.Title(strings.ToLower(s))
-}
+ pcfg.Case = strings.ToUpper
-func spongeBobCase(s string) string {
- var b strings.Builder
- b.Grow(len(s))
- for _, c := range s {
- b.WriteRune(unicode.To(rand.Intn(2), c))
+ if expanded {
+ pcfg.Simplify = false
+ pcfg.Align = tree.PrettyNoAlign
+ } else {
+ pcfg.Simplify = true
+ pcfg.Align = tree.PrettyAlignAndDeindent
}
- return b.String()
+ return fmtsql(pcfg, []string{sql})
}
const (
@@ -435,32 +415,12 @@ Its purpose is to beautifully format SQL statements.
Usage
-There is a box in which to paste or type SQL statements. Multiple statements are supported by separating them with a semicolon (;). The slider below the box controls the desired maximum line width in characters. Various options on the side control tab/indentation width, the use of spaces or tabs, simplification, and alignment modes. Simplification causes the formatter to remove unneeded parentheses and words when the meaning will be the same without them.
-
-There are four alignment modes. The default, no, uses left alignment. partial right aligns keywords at the width of the longest keyword at the beginning of all lines immediately below. full is the same as partial but the keywords AND and OR are deindented, in a style similar to the sqlite tests. other is like partial but instead of deindenting AND and OR, their arguments are instead indented.
-
-no:
-
-SELECT
- a
-FROM
- t
-WHERE
- c
- AND b
- OR d
-
+There is a box in which to paste or type SQL statements. Multiple statements are supported by separating them with a semicolon (;). The slider below the box controls the desired maximum line width in characters. Various options on the side control tab/indentation width, and the use of spaces or tabs.
-partial:
-
-SELECT a
- FROM t
- WHERE c
- AND b
- OR d
-
+There are two formatting modes. The default "compact" format, simplifies expressions and collapses clauses using alignment to clarify between clauses.
+The "expanded" format avoids simplifying expressions and reveals the full structure of SQL queries.
-full:
+compact:
SELECT a
FROM t
@@ -469,14 +429,16 @@ SELECT a
OR d
-other:
+expanded:
-SELECT a
- FROM t
- WHERE c
- AND
- b
- OR d
+SELECT
+ a
+FROM
+ t
+WHERE
+ c
+ AND b
+ OR d
Background
@@ -504,18 +466,8 @@ sqlfmt was inspired by prettier . It is based
options:
tab width
- simplify
use spaces
- alignment mode:
- no
- full
- partial
- other
- case:
- UPPER
- lower
- Title
- sPOngEboB
+ expanded
reset to defaults
clear
auto paste
@@ -540,9 +492,7 @@ const actualWidth = document.getElementById('actual_width');
const actualBytes = document.getElementById('actual_bytes');
const n = document.getElementById('n');
const iw = document.getElementById('indent');
-const simplify = document.getElementById('simplify');
-const align = document.theform.align;
-const casemode = document.theform.casemode;
+const expanded = document.getElementById('expanded');
const spaces = document.getElementById('spaces');
const fmt = document.getElementById('fmt');
const sqlEl = document.getElementById('sql');
@@ -623,20 +573,16 @@ function range() {
const viw = iw.value;
const sql = sqlEl.value;
const spVal = spaces.checked ? 1 : 0;
- const simVal = simplify.checked ? 1 : 0;
- const alVal = align.value;
- const caseVal = casemode.value;
+ const expVal = expanded.checked ? 1 : 0;
localStorage.setItem('sql', sql);
localStorage.setItem('n', v);
localStorage.setItem('iw', viw);
- localStorage.setItem('simplify', simVal);
- localStorage.setItem('align', alVal);
- localStorage.setItem('case', caseVal);
+ localStorage.setItem('expanded', expVal);
localStorage.setItem('spaces', spVal);
fmt.style["tab-size"] = viw;
fmt.style["-moz-tab-size"] = viw;
- share.href = '/?n=' + v + '&indent=' + viw + '&spaces=' + spVal + '&simplify=' + simVal + '&align=' + alVal + '&case=' + caseVal + '&sql=' + encodeURIComponent(b64EncodeUnicode(sql));
- fetch('/fmt?json=1&n=' + v + '&indent=' + viw + '&spaces=' + spVal + '&simplify=' + simVal + '&align=' + alVal + '&case=' + caseVal + '&sql=' + encodeURIComponent(sql)).then(
+ share.href = '/?n=' + v + '&indent=' + viw + '&spaces=' + spVal + '&expanded=' + expVal + '&sql=' + encodeURIComponent(b64EncodeUnicode(sql));
+ fetch('/fmt?json=1&n=' + v + '&indent=' + viw + '&spaces=' + spVal + '&expanded=' + expVal + '&sql=' + encodeURIComponent(sql)).then(
resp => {
working = false;
resp.json().then(data => {
@@ -699,9 +645,7 @@ function reloadVals() {
let sql = localStorage.getItem('sql');
let nVal = localStorage.getItem('n');
let iwVal = localStorage.getItem('iw');
- let simVal = localStorage.getItem('simplify');
- let alVal = localStorage.getItem('align');
- let caseVal = localStorage.getItem('case');
+ let expVal = localStorage.getItem('expanded');
let spVal = localStorage.getItem('spaces');
// Load predefined defaults, for each value that didn't have a default in storage.
@@ -713,9 +657,7 @@ function reloadVals() {
}
if (nVal === null) { nVal = 60; }
if (iwVal === null) { iwVal = 4; }
- if (simVal === null) { simVal = 1; }
- if (alVal === null) { alVal = 0; }
- if (caseVal === null) { caseVal = 'upper'; }
+ if (expVal === null) { expVal = 1; }
if (spVal === null) { spVal = 0; }
// Override any value from the URL.
@@ -724,9 +666,7 @@ function reloadVals() {
if (search.has('sql')) { sql = b64DecodeUnicode(search.get('sql')); }
if (search.has('n')) { nVal = search.get('n'); }
if (search.has('indent')) { iwVal = search.get('indent'); }
- if (search.has('align')) { alVal = search.get('align'); }
- if (search.has('case')) { caseVal = search.get('case'); }
- if (search.has('simplify')) { simVal = search.get('simplify'); }
+ if (search.has('expanded')) { simVal = search.get('expanded'); }
if (search.has('spaces')) { spVal = search.get('spaces'); }
}
@@ -734,9 +674,7 @@ function reloadVals() {
sqlEl.value = sql;
n.value = nVal;
iw.value = iwVal;
- simplify.checked = !!simVal;
- align.value = alVal;
- casemode.value = caseVal;
+ expanded.checked = !!expVal;
spaces.checked = !!spVal;
}
@@ -762,9 +700,7 @@ autoPaste();
sqlEl.onkeydown = null;
n.oninput = n.onchange = range;
iw.oninput = iw.onchange = range;
- simplify.oninput = simplify.onchange = range;
- align.oninput = simplify.oninput = range;
- casemode.oninput = simplify.onchange = range;
+ expanded.oninput = expanded.onchange = range;
spaces.oninput = spaces.oninput = range;
reset.onclick = resetVals;
};
@@ -774,9 +710,7 @@ autoPaste();
range();
};
iw.oninput = iw.onchange = n.oninput;
- simplify.oninput = simplify.onchange = n.oninput;
- align.oninput = simplify.oninput = n.oninput;
- casemode.oninput = simplify.oninput = n.oninput;
+ expanded.oninput = expanded.onchange = n.oninput;
spaces.oninput = spaces.oninput = n.oninput;
reset.onclick = () => {
clearSearch();