diff --git a/package.json b/package.json
index d328e24dd..f73d174c0 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
"react-syntax-highlighter": "^15.5.0",
"shape": "npm:@multiprocess/shape",
"source-map-support": "^0.5.21",
+ "sql-formatter": "^6.1.1",
"tmp-promise": "^3.0.3",
"tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1",
diff --git a/ui/Panel.tsx b/ui/Panel.tsx
index 1c290ca9c..dcd6e7171 100644
--- a/ui/Panel.tsx
+++ b/ui/Panel.tsx
@@ -4,6 +4,7 @@ import {
IconArrowsDiagonalMinimize2,
IconArrowsMaximize,
IconArrowsMinimize,
+ IconBraces,
IconChevronDown,
IconChevronUp,
IconEye,
@@ -17,10 +18,11 @@ import formatDistanceToNow from 'date-fns/formatDistanceToNow';
import circularSafeStringify from 'json-stringify-safe';
import * as React from 'react';
import { toString } from 'shape';
+import { format as sqlFormat } from 'sql-formatter';
import { MODE_FEATURES } from '../shared/constants';
import { EVAL_ERRORS } from '../shared/errors';
import log from '../shared/log';
-import { PanelInfo, PanelResult } from '../shared/state';
+import { PanelInfo, PanelResult, ProgramPanelInfo } from '../shared/state';
import { humanSize } from '../shared/text';
import { panelRPC } from './asyncRPC';
import { Alert } from './components/Alert';
@@ -255,6 +257,22 @@ export function Panel({
setError(results.exception);
}, [results.exception]);
+ function formatThis() {
+ const old = panel.content;
+ try {
+ panel.content = sqlFormat(old);
+ if (panel.content === old) {
+ // Don't update if it hasn't changed
+ return;
+ }
+ } catch (e) {
+ log.error(e);
+ panel.content = old;
+ }
+
+ updatePanel(panel);
+ }
+
async function evalThis() {
if (killable) {
await killProcess();
@@ -449,6 +467,16 @@ export function Panel({
{loading ? : }
+ {panel.type ===
+ 'database' /* TODO: this format should become part of the paneldetails object */ ||
+ (panel.type === 'program' &&
+ (panel as ProgramPanelInfo).program.type === 'sql') ? (
+
+
+
+ ) : null}