diff --git a/index.html b/index.html
index 16fc35f..8ecd55f 100644
--- a/index.html
+++ b/index.html
@@ -261,6 +261,10 @@
+
diff --git a/src/DomElements.ts b/src/DomElements.ts
index de5b0ce..964711c 100644
--- a/src/DomElements.ts
+++ b/src/DomElements.ts
@@ -1,12 +1,12 @@
export type ElementMap = {
[key: string]:
- | HTMLElement
- | HTMLButtonElement
- | HTMLDivElement
- | HTMLInputElement
- | HTMLSelectElement
- | HTMLCanvasElement
- | HTMLFormElement;
+ | HTMLElement
+ | HTMLButtonElement
+ | HTMLDivElement
+ | HTMLInputElement
+ | HTMLSelectElement
+ | HTMLCanvasElement
+ | HTMLFormElement;
};
export const singleElements = {
@@ -36,6 +36,7 @@ export const singleElements = {
line_numbers_checkbox: "show-line-numbers",
time_position_checkbox: "show-time-position",
tips_checkbox: "show-tips",
+ completion_checkbox: "show-completions",
midi_clock_checkbox: "send-midi-clock",
midi_channels_scripts: "midi-channels-scripts",
midi_clock_ppqn: "midi-clock-ppqn-input",
diff --git a/src/EditorSetup.ts b/src/EditorSetup.ts
index 944454d..5e3be76 100644
--- a/src/EditorSetup.ts
+++ b/src/EditorSetup.ts
@@ -34,6 +34,12 @@ import { EditorView } from "codemirror";
import { toposTheme } from "./themes/toposTheme";
import { javascript } from "@codemirror/lang-javascript";
import { inlineHoveringTips } from "./documentation/inlineHelp";
+import { toposCompletions } from "./documentation/inlineHelp";
+import { javascriptLanguage } from "@codemirror/lang-javascript"
+
+export const jsCompletions = javascriptLanguage.data.of({
+ autocomplete: toposCompletions
+})
export const editorSetup: Extension = (() => [
highlightActiveLineGutter(),
@@ -47,8 +53,6 @@ export const editorSetup: Extension = (() => [
bracketMatching(),
closeBrackets(),
autocompletion(),
- // rectangularSelection(),
- // crosshairCursor(),
highlightActiveLine(),
highlightSelectionMatches(),
keymap.of([
@@ -62,6 +66,7 @@ export const editorSetup: Extension = (() => [
export const installEditor = (app: Editor) => {
app.vimModeCompartment = new Compartment();
app.hoveringCompartment = new Compartment();
+ app.completionsCompartment = new Compartment();
app.withLineNumbers = new Compartment();
app.chosenLanguage = new Compartment();
app.fontSize = new Compartment();
@@ -86,6 +91,7 @@ export const installEditor = (app: Editor) => {
app.withLineNumbers.of(lines),
app.fontSize.of(fontModif),
app.hoveringCompartment.of(app.settings.tips ? inlineHoveringTips : []),
+ app.completionsCompartment.of(app.settings.completions ? jsCompletions : []),
editorSetup,
toposTheme,
app.chosenLanguage.of(javascript()),
diff --git a/src/FileManagement.ts b/src/FileManagement.ts
index 75db8a6..6b8b969 100644
--- a/src/FileManagement.ts
+++ b/src/FileManagement.ts
@@ -48,6 +48,7 @@ export interface Settings {
* @param line_numbers - Whether or not to show line numbers
* @param time_position - Whether or not to show time position
* @param tips - Whether or not to show tips
+ * @param completions- Whether or not to show completions
* @param send_clock - Whether or not to send midi clock
* @param midi_channels_scripts - Whether midi input channels fires scripts
* @param midi_clock_input - The name of the midi clock input
@@ -64,6 +65,7 @@ export interface Settings {
time_position: boolean;
load_demo_songs: boolean;
tips: boolean;
+ completions: boolean;
send_clock: boolean;
midi_channels_scripts: boolean;
midi_clock_input: string | undefined;
@@ -125,6 +127,7 @@ export class AppSettings {
* @param line_numbers - Whether or not to show line numbers
* @param time_position - Whether or not to show time position
* @param tips - Whether or not to show tips
+ * @param completions - Whether or not to show completions
* @param send_clock - Whether or not to send midi clock
* @param midi_channels_scripts - Whether midi input channels fires scripts
* @param midi_clock_input - The name of the midi clock input
@@ -140,7 +143,8 @@ export class AppSettings {
public selected_universe: string = "Default";
public line_numbers: boolean = true;
public time_position: boolean = true;
- public tips: boolean = true;
+ public tips: boolean = false;
+ public completions: boolean = false;
public send_clock: boolean = false;
public midi_channels_scripts: boolean = true;
public midi_clock_input: string | undefined = undefined;
@@ -164,6 +168,7 @@ export class AppSettings {
this.line_numbers = settingsFromStorage.line_numbers;
this.time_position = settingsFromStorage.time_position;
this.tips = settingsFromStorage.tips;
+ this.completions = settingsFromStorage.completions;
this.send_clock = settingsFromStorage.send_clock;
this.midi_channels_scripts = settingsFromStorage.midi_channels_scripts;
this.midi_clock_input = settingsFromStorage.midi_clock_input;
@@ -193,6 +198,7 @@ export class AppSettings {
line_numbers: this.line_numbers,
time_position: this.time_position,
tips: this.tips,
+ completions: this.completions,
send_clock: this.send_clock,
midi_channels_scripts: this.midi_channels_scripts,
midi_clock_input: this.midi_clock_input,
@@ -220,6 +226,7 @@ export class AppSettings {
this.line_numbers = settings.line_numbers;
this.time_position = settings.time_position;
this.tips = settings.tips;
+ this.completions = settings.completions;
this.send_clock = settings.send_clock;
this.midi_channels_scripts = settings.midi_channels_scripts;
this.midi_clock_input = settings.midi_clock_input;
diff --git a/src/InterfaceLogic.ts b/src/InterfaceLogic.ts
index 1cfd385..18bb17d 100644
--- a/src/InterfaceLogic.ts
+++ b/src/InterfaceLogic.ts
@@ -21,6 +21,7 @@ import { loadSamples } from "./API";
import { tryEvaluate } from "./Evaluator";
import { inlineHoveringTips } from "./documentation/inlineHelp";
import { lineNumbers } from "@codemirror/view";
+import { jsCompletions } from "./EditorSetup";
export const installInterfaceLogic = (app: Editor) => {
(app.interface.line_numbers_checkbox as HTMLInputElement).checked =
@@ -28,6 +29,8 @@ export const installInterfaceLogic = (app: Editor) => {
(app.interface.time_position_checkbox as HTMLInputElement).checked =
app.settings.time_position;
(app.interface.tips_checkbox as HTMLInputElement).checked = app.settings.tips;
+ (app.interface.completion_checkbox as HTMLInputElement).checked = app.settings.completions;
+
(app.interface.midi_clock_checkbox as HTMLInputElement).checked =
app.settings.send_clock;
(app.interface.midi_channels_scripts as HTMLInputElement).checked =
@@ -378,6 +381,18 @@ export const installInterfaceLogic = (app: Editor) => {
});
});
+ app.interface.completion_checkbox.addEventListener("change", () => {
+ let checked = (app.interface.completion_checkbox as HTMLInputElement).checked
+ ? true
+ : false;
+ app.settings.completions = checked;
+ app.view.dispatch({
+ effects: app.completionsCompartment.reconfigure(
+ checked ? jsCompletions : []
+ ),
+ });
+ });
+
app.interface.midi_clock_checkbox.addEventListener("change", () => {
let checked = (app.interface.midi_clock_checkbox as HTMLInputElement)
.checked
diff --git a/src/documentation/inlineHelp.ts b/src/documentation/inlineHelp.ts
index ef6bc24..eddb2c3 100644
--- a/src/documentation/inlineHelp.ts
+++ b/src/documentation/inlineHelp.ts
@@ -1,5 +1,7 @@
import { hoverTooltip } from "@codemirror/view";
import { type EditorView } from "@codemirror/view";
+import { CompletionContext } from "@codemirror/autocomplete"
+
interface InlineCompletion {
name: string;
@@ -23,7 +25,7 @@ const completionDatabase: CompletionDatabase = {
name: "delayr",
category: "time",
description: "Delay a function
n times by
t ms",
- example: "delayr(50, 3, () => beat(1) :: log('delayed'))",
+ example: "delayr(50,3,()=> beat(1)::log('hey!'))",
},
toss: {
name: "toss",
@@ -35,7 +37,7 @@ const completionDatabase: CompletionDatabase = {
name: "lpadsr",
category: "synthesis",
description: "Lowpass filter ADSR envelope",
- example: "sound('sawtooth').lpadsr(2, 0, .1, 0, 0).out()",
+ example: "sound('sawtooth').lpadsr(2,0,.1,0,0).out()",
},
lpenv: {
name: "lpenv",
@@ -968,3 +970,29 @@ export const inlineHoveringTips = hoverTooltip(
};
}
);
+
+export const toposCompletions = (context: CompletionContext) => {
+ let word = context.matchBefore(/\w*/)
+ if (word) {
+ if (word.from == word.to && !context.explicit)
+ return null
+ return {
+ from: word.from,
+ options: Object.keys(completionDatabase).map((key) => ({
+ label: key,
+ type: completionDatabase[key].category,
+ info: () => {
+ let div = document.createElement('div');
+ div.innerHTML = `
+
${completionDatabase[key].name} [${completionDatabase[key].category}]
+
${completionDatabase[key].description}
+
${completionDatabase[key].example}
+ `
+ div.classList.add("px-4", "py-2", "rounded-lg", "w-92");
+ return div
+ }
+ }))
+ }
+ }
+}
+
diff --git a/src/main.ts b/src/main.ts
index d1c8203..1cdff38 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -42,6 +42,7 @@ export class Editor {
withLineNumbers!: Compartment;
vimModeCompartment!: Compartment;
hoveringCompartment!: Compartment;
+ completionsCompartment!: Compartment;
chosenLanguage!: Compartment;
dynamicPlugins!: Compartment;
currentDocumentationPane: string = "introduction";