Skip to content

Commit

Permalink
Added feature to auto detect the OS end-of-line (EOL) character.
Browse files Browse the repository at this point in the history
  • Loading branch information
Rohit Bhati committed Sep 4, 2024
1 parent f451f89 commit 08837aa
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 16 deletions.
Binary file modified docs/en_US/images/query_status_bar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion docs/en_US/query_tool_toolbar.rst
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ The status bar shows the following information:
* **Total rows**: The total number of rows returned by the query.
* **Query complete**: The time is taken by the query to complete.
* **Rows selected**: The number of rows selected in the data output panel.
* **Changes staged**: This information showed the number of rows added, deleted, and updated.
* **Changes staged**: This information shows the number of rows added, deleted, and updated.
* **LF/CRLF**: It shows the end of line sequence to be used for the editor. When opening an empty editor, it will be decided based on OS.
And when opening an existing file, it will be based on file end of lines. One can change the EOL by clicking on any of the options.
* **Ln**: In the Query tab, it is the line number at which the cursor is positioned.
* **Col**: In the Query tab, it is the column number at which the cursor is positioned
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { errorMarkerEffect } from './extensions/errorMarker';
import { currentQueryHighlighterEffect } from './extensions/currentQueryHighlighter';
import { activeLineEffect, activeLineField } from './extensions/activeLineMarker';
import { clearBreakpoints, hasBreakpoint, toggleBreakpoint } from './extensions/breakpointGutter';
import { autoCompleteCompartment } from './extensions/extraStates';
import { autoCompleteCompartment, eol, eolCompartment } from './extensions/extraStates';


function getAutocompLoading({ bottom, left }, dom) {
Expand All @@ -30,11 +30,13 @@ export default class CustomEditorView extends EditorView {
this._cleanDoc = this.state.doc;
}

getValue(tillCursor=false) {
getValue(tillCursor=false, useLineSep=false) {
if(tillCursor) {
return this.state.sliceDoc(0, this.state.selection.main.head);
} else if (useLineSep) {
return this.state.doc.sliceString(0, this.state.doc.length, this.getEOL());
}
return this.state.doc.toString();
return this.state.sliceDoc();
}

/* Function to extract query based on position passed */
Expand Down Expand Up @@ -328,4 +330,14 @@ export default class CustomEditorView extends EditorView {
setQueryHighlightMark(from,to) {
this.dispatch({ effects: currentQueryHighlighterEffect.of({ from, to }) });
}

getEOL(){
return this.state.facet(eol);
}

setEOL(val){
this.dispatch({
effects: eolCompartment.reconfigure(eol.of(val))
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ import CustomEditorView from '../CustomEditorView';
import breakpointGutter, { breakpointEffect } from '../extensions/breakpointGutter';
import activeLineExtn from '../extensions/activeLineMarker';
import currentQueryHighlighterExtn from '../extensions/currentQueryHighlighter';
import { autoCompleteCompartment, indentNewLine } from '../extensions/extraStates';
import { autoCompleteCompartment, eolCompartment, indentNewLine, eol } from '../extensions/extraStates';
import { OS_EOL } from '../../../../../tools/sqleditor/static/js/components/QueryToolConstants';

const arrowRightHtml = ReactDOMServer.renderToString(<KeyboardArrowRightRoundedIcon style={{width: '16px'}} />);
const arrowDownHtml = ReactDOMServer.renderToString(<ExpandMoreRoundedIcon style={{width: '16px'}} />);
Expand Down Expand Up @@ -144,6 +145,10 @@ const defaultExtensions = [
return 0;
}),
autoCompleteCompartment.of([]),
EditorView.clipboardOutputFilter.of((text, state)=>{
const lineSep = state.facet(eol);
return state.doc.sliceString(0, text.length, lineSep);
})
];

export default function Editor({
Expand All @@ -167,6 +172,7 @@ export default function Editor({

useEffect(() => {
const finalOptions = { ...defaultOptions, ...options };
const osEOL = OS_EOL === 'crlf' ? '\r\n' : '\n';
const finalExtns = [
(language == 'json') ? json() : sql({dialect: PgSQL}),
...defaultExtensions,
Expand All @@ -191,6 +197,7 @@ export default function Editor({
const state = EditorState.create({
extensions: [
...finalExtns,
eolCompartment.of([eol.of(osEOL)]),
shortcuts.current.of([]),
configurables.current.of([]),
editableConfig.current.of([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ export const indentNewLine = Facet.define({
combine: values => values.length ? values[0] : true,
});

export const eol = Facet.define({
combine: values => values.length ? values[0] : '\n',
});

export const autoCompleteCompartment = new Compartment();
export const eolCompartment = new Compartment();

Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export const QUERY_TOOL_EVENTS = {
RESET_GRAPH_VISUALISER: 'RESET_GRAPH_VISUALISER',

GOTO_LAST_SCROLL: 'GOTO_LAST_SCROLL',
CHANGE_EOL: 'CHANGE_EOL'
};

export const CONNECTION_STATUS = {
Expand Down Expand Up @@ -105,4 +106,6 @@ export const PANELS = {
GRAPH_VISUALISER: 'id-graph-visualiser',
};

export const MAX_QUERY_LENGTH = 1000000;
export const MAX_QUERY_LENGTH = 1000000;

export const OS_EOL = navigator.platform === 'win32' ? 'crlf' : 'lf';
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ export default function Query({onTextSelect}) {
const pgAdmin = usePgAdmin();
const preferencesStore = usePreferences();
const queryToolPref = queryToolCtx.preferences.sqleditor;

const highlightError = (cmObj, {errormsg: result, data}, executeCursor)=>{
let errorLineNo = 0,
startMarker = 0,
Expand Down Expand Up @@ -175,7 +174,6 @@ export default function Query({onTextSelect}) {
}
});


eventBus.registerListener(QUERY_TOOL_EVENTS.LOAD_FILE, (fileName, storage)=>{
queryToolCtx.api.post(url_for('sqleditor.load_file'), {
'file_name': decodeURI(fileName),
Expand All @@ -200,7 +198,7 @@ export default function Query({onTextSelect}) {
eventBus.registerListener(QUERY_TOOL_EVENTS.SAVE_FILE, (fileName)=>{
queryToolCtx.api.post(url_for('sqleditor.save_file'), {
'file_name': decodeURI(fileName),
'file_content': editor.current.getValue(),
'file_content': editor.current.getValue(false, true),
}).then(()=>{
editor.current.markClean();
eventBus.fireEvent(QUERY_TOOL_EVENTS.SAVE_FILE_DONE, fileName, true);
Expand Down Expand Up @@ -288,6 +286,12 @@ export default function Query({onTextSelect}) {
editor.current.setValue(formattedSql);
}
});

eventBus.registerListener(QUERY_TOOL_EVENTS.CHANGE_EOL, (lineSep)=>{
editor.current?.setEOL(lineSep);
eventBus.fireEvent(QUERY_TOOL_EVENTS.QUERY_CHANGED, true);
});

eventBus.registerListener(QUERY_TOOL_EVENTS.EDITOR_TOGGLE_CASE, ()=>{
let selectedText = editor.current?.getSelection();
if (!selectedText) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import React, { useEffect, useState, useContext } from 'react';
import React, { useEffect, useState, useContext, useCallback } from 'react';
import { styled } from '@mui/material/styles';
import { Box } from '@mui/material';
import { Box, Tooltip } from '@mui/material';
import _ from 'lodash';
import { QUERY_TOOL_EVENTS } from '../QueryToolConstants';
import { OS_EOL, QUERY_TOOL_EVENTS } from '../QueryToolConstants';
import { useStopwatch } from '../../../../../../static/js/custom_hooks';
import { QueryToolEventsContext } from '../QueryToolComponent';
import gettext from 'sources/gettext';
import { PgMenu, PgMenuItem } from '../../../../../../static/js/components/Menu';


const StyledBox = styled(Box)(({theme}) => ({
Expand All @@ -26,17 +27,17 @@ const StyledBox = styled(Box)(({theme}) => ({
userSelect: 'text',
'& .StatusBar-padding': {
padding: '2px 12px',
'& .StatusBar-mlAuto': {
'&.StatusBar-mlAuto': {
marginLeft: 'auto',
},
'& .StatusBar-divider': {
'&.StatusBar-divider': {
...theme.mixins.panelBorder.right,
},
},
}));

export function StatusBar() {

export function StatusBar() {
const eventBus = useContext(QueryToolEventsContext);
const [position, setPosition] = useState([1, 1]);
const [lastTaskText, setLastTaskText] = useState(null);
Expand All @@ -50,6 +51,35 @@ export function StatusBar() {
});
const {seconds, minutes, hours, msec, start:startTimer, pause:pauseTimer, reset:resetTimer} = useStopwatch({});

const [selectedEol, setSelectedEol] = useState(OS_EOL);
const [openMenuName, setOpenMenuName] = useState(null);
const prevMenuOpenIdRef = React.useRef(null);
const eolMenuRef = React.useRef(null);

const toggleMenu = React.useCallback((e) => {
const name = e.currentTarget?.getAttribute('name');
setOpenMenuName(() => {
return prevMenuOpenIdRef.current === name ? null : name;
});
prevMenuOpenIdRef.current = null;
}, []);

const onMenuClose = React.useCallback(() => {
prevMenuOpenIdRef.current = openMenuName;
setTimeout(() => {
prevMenuOpenIdRef.current = null;
}, 300);
setOpenMenuName(null);
}, [openMenuName]);

const handleEndOfLineChange = useCallback((e)=>{
const val = e.value;
const lineSep = val === 'crlf' ? '\r\n' : '\n';
setSelectedEol(val);
eventBus.fireEvent(QUERY_TOOL_EVENTS.CHANGE_EOL, lineSep);
onMenuClose();
}, []);

useEffect(()=>{
eventBus.registerListener(QUERY_TOOL_EVENTS.CURSOR_ACTIVITY, (newPos)=>{
setPosition(newPos||[1, 1]);
Expand Down Expand Up @@ -109,7 +139,36 @@ export function StatusBar() {
<span>{gettext('Changes staged: %s', stagedText)}</span>
</Box>
}
<Box className='StatusBar-padding StatusBar-mlAuto'>{gettext('Ln %s, Col %s', position[0], position[1])}</Box>

<Box className='StatusBar-padding StatusBar-mlAuto' style={{display:'flex'}}>
<Box className="StatusBar-padding StatusBar-divider">
<Tooltip title="Select EOL Sequence" disableInteractive enterDelay={2500}>
<span
onClick={toggleMenu}
ref={eolMenuRef}
name="menu-eoloptions"
style={{
cursor: 'pointer',
display: 'inline-flex',
alignItems: 'center',
fontSize: 'inherit',
}}
>
{selectedEol.toUpperCase()}
</span>
</Tooltip>
<PgMenu
anchorRef={eolMenuRef}
open={openMenuName=='menu-eoloptions'}
onClose={onMenuClose}
label={gettext('EOL Options Menu')}
>
<PgMenuItem hasCheck value="lf" checked={selectedEol === 'lf'} onClick={handleEndOfLineChange}>{gettext('LF')}</PgMenuItem>
<PgMenuItem hasCheck value="crlf" checked={selectedEol === 'crlf'} onClick={handleEndOfLineChange}>{gettext('CRLF')}</PgMenuItem>
</PgMenu>
</Box>
<Box className='StatusBar-padding'>{gettext('Ln %s, Col %s', position[0], position[1])}</Box>
</Box>
</StyledBox>
);
}

0 comments on commit 08837aa

Please sign in to comment.