Skip to content

Commit

Permalink
Uppercase, Lowercase and Duplicate Lines functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
bogosorter committed Oct 30, 2024
1 parent 5b5b960 commit 105598c
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 49 deletions.
13 changes: 11 additions & 2 deletions src/renderer/components/CommandPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ export default function CommandPalette() {
<Command.List>
<Command.Empty style={{ color: theme.primary }}>No results found <span className='emoticon'>:(</span></Command.Empty>
{
items.map(({ label, action }) => (
items.map(({ label, action }, index) => (
<Command.Item
key={label}
key={index}
onSelect={() => {
setValue('');
action();
Expand Down Expand Up @@ -152,6 +152,15 @@ const actions = {
}, {
label: 'Markdown: Todo List',
action: () => store.getState().todoList()
}, {
label: 'Markdown: Uppercase',
action: () => store.getState().uppercase()
}, {
label: 'Markdown: Lowercase',
action: () => store.getState().lowercase()
}, {
label: 'Markdown: Duplicate Lines',
action: () => store.getState().duplicateLines()
}, {
label: 'Elementary: About',
action: () => store.getState().openInfo()
Expand Down
98 changes: 95 additions & 3 deletions src/renderer/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,14 @@ type Store = {
unorderedList: () => void;
todoList: () => void;

// Auxiliar markdown methods
// Other text editing operations
uppercase: () => void;
lowercase: () => void;
duplicateLines: () => void;

// Auxiliar text methods
surroundText: (start: string, end: string) => void;
transformText: (transformation: (input: string) => string) => void;
prependText: (start: string) => void;

// Documentation
Expand All @@ -92,6 +98,7 @@ type Store = {
onWindowClose: () => Promise<void>;
getLocalFile: (path: string) => Promise<string | null>;
getLocalFileBase64: (path: string) => Promise<{mimeType: string, data: string} | null>;
getSelectedText: () => Monaco.Selection | null;
// Ensures that some custom markdown elements are rendered correctly
updateDecorations: () => void;
updateStats: () => void;
Expand All @@ -112,7 +119,10 @@ const store = create<Store>((set, get) => ({
'ctrl+n': () => get().newFile(),
'ctrl+b': () => get().bold(),
'ctrl+i': () => get().italic(),
'ctrl+k': () => get().link()
'ctrl+k': () => get().link(),
'ctrl+u': () => get().uppercase(),
'ctrl+l': () => get().lowercase(),
'ctrl+d': () => get().duplicateLines()
},
commandPalette: {
open: false,
Expand Down Expand Up @@ -152,6 +162,16 @@ const store = create<Store>((set, get) => ({
// Disable trigger suggestion on Ctrl+I
keybinding: Monaco.KeyMod.CtrlCmd | Monaco.KeyCode.KeyI,
command: null
}, {
// Disable Ctrl+U keybindings
keybinding: Monaco.KeyMod.CtrlCmd | Monaco.KeyCode.KeyU,
command: null
}, {
keybinding: Monaco.KeyMod.CtrlCmd | Monaco.KeyCode.KeyL
}, {
// Disable Ctrl+D keybindings
keybinding: Monaco.KeyMod.CtrlCmd | Monaco.KeyCode.KeyD,
command: null
}
]);

Expand Down Expand Up @@ -358,8 +378,8 @@ const store = create<Store>((set, get) => ({
}

get().editor?.setValue(content);
get().editor?.setScrollTop(0);
set({ path: path, content: content, saved: true });
get().closeCommandPalette();
},
newFile: async () => {
if (!await get().canCloseFile()) return;
Expand Down Expand Up @@ -486,6 +506,40 @@ const store = create<Store>((set, get) => ({
get().closeCommandPalette();
},

uppercase: () => {
get().transformText((input) => input.toUpperCase());
get().closeCommandPalette();
},
lowercase: () => {
get().transformText((input) => input.toLowerCase());
get().closeCommandPalette();
},
duplicateLines: () => {
get().closeCommandPalette();

if (!(get().editor && get().monaco)) return;

let selection = get().editor!.getSelection();
if (!selection) return;

selection = new Monaco.Selection(
selection.startLineNumber,
0,
selection.endLineNumber,
get().editor!.getModel()!.getLineContent(selection.endLineNumber).length + 1
);

const lines = get().editor!.getModel()!.getValueInRange(selection);
console.log(lines);
get().editor!.executeEdits('', [{
range: selection,
// A double newline is needed since the newline character is not returned by
// `getValueInRange` and markdown paragraphs are separated by an extra newline.
text: lines + '\n\n' + lines,
forceMoveMarkers: true
}]);
},

surroundText: (start, end) => {
if (!get().editor) return;

Expand Down Expand Up @@ -537,6 +591,23 @@ const store = create<Store>((set, get) => ({

get().editor!.focus();
},
transformText: (transformation) => {
const selection = get().getSelectedText();
if (!selection) return;

const source = get().editor!.getModel()!.getValueInRange(selection);
const result = transformation(source);

get().editor!.executeEdits('', [{
range: selection,
text: result,
forceMoveMarkers: true
}]);

// TODO: Is this necessary?
get().editor!.setSelection(selection);
get().editor!.focus();
},
prependText: (start) => {
if (!get().editor) return;

Expand Down Expand Up @@ -611,6 +682,27 @@ const store = create<Store>((set, get) => ({
if (!get().path) return null;
return await window.electron.ipcRenderer.invoke('getLocalFileBase64', get().path, path);
},
getSelectedText: () => {
if (!get().editor) return null;

let selection = get().editor!.getSelection();
if (!selection) return null;

// If the selection is empty but near a word, select the word
if (selection.startColumn === selection.endColumn) {
const word = get().editor!.getModel()!.getWordAtPosition(selection.getStartPosition());
if (word) {
selection = new Monaco.Selection(
selection.startLineNumber,
word.startColumn,
selection.endLineNumber,
word.endColumn
);
}
}

return selection;
},
updateDecorations: () => {
if (!get().monaco || !get().editor) return;

Expand Down
44 changes: 0 additions & 44 deletions src/renderer/utils/highlight.ts

This file was deleted.

0 comments on commit 105598c

Please sign in to comment.