Skip to content

Commit

Permalink
CodeMirror dialog box adds a file structure sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
CF3B5 committed Jul 14, 2024
1 parent 418ad4a commit b2afe89
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 11 deletions.
134 changes: 128 additions & 6 deletions src/components/TheEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@
<v-icon small class="mr-1">{{ mdiHelp }}</v-icon>
{{ $t('Editor.ConfigReference') }}
</v-btn>
<v-btn
v-if="configFileStructure"
text
tile
target="_blank"
class="d-none d-md-flex"
@click="showFileStructure()">
<v-icon small class="mr-1">{{ mdiFormatListCheckbox }}</v-icon>
{{ $t('Editor.FileStructure') }}
</v-btn>
<v-btn
v-if="restartServiceNameExists"
color="primary"
Expand All @@ -49,12 +59,46 @@
</v-btn>
</template>
<v-card-text class="pa-0">
<codemirror-async
v-if="show"
ref="editor"
v-model="sourcecode"
:name="filename"
:file-extension="fileExtension" />
<div v-if="fileStructureSidebar" class="d-none d-md-flex float-right structure-sidebar cm-editor ͼo">
<div class="cm-scroller" style="width: 100%;">
<v-treeview
activatable
open-on-click
dense
dark
:active="structureActive"
:open="structureOpen"
item-key="line"
:items="configFileStructure"
@update:active="activeChanges"
>
<template v-slot:label="{ item }">

Check warning on line 75 in src/components/TheEditor.vue

View workflow job for this annotation

GitHub Actions / ESLint

src/components/TheEditor.vue#L75

Expected '#label' instead of 'v-slot:label' (vue/v-slot-style)
<div :class="item.type == 'item' ? 'ͼp' : 'ͼt'">{{ item.name }}</div>
</template>
<template v-slot:append="{ item }" v-if="restartServiceName === 'klipper'">

Check warning on line 78 in src/components/TheEditor.vue

View workflow job for this annotation

GitHub Actions / ESLint

src/components/TheEditor.vue#L78

Expected '#append' instead of 'v-slot:append' (vue/v-slot-style)

Check warning on line 78 in src/components/TheEditor.vue

View workflow job for this annotation

GitHub Actions / ESLint

src/components/TheEditor.vue#L78

Attribute "v-if" should go before "v-slot:append" (vue/attributes-order)
<v-btn
v-if="item.type == 'section'"
icon
small
plain
color="grey darken-2"
:href="klipperConfigReference + '#' + item.name.split(' ')[0]"
target="_blank">
<v-icon small class="mr-1">{{ mdiHelpCircle }}</v-icon>
</v-btn>
</template>
</v-treeview>
</div>
</div>
<div :class="fileStructureSidebar?'structure':''">
<codemirror-async
v-if="show"
ref="editor"
v-model="sourcecode"
:name="filename"
:file-extension="fileExtension"
@lineChange="lineChanges"/>
</div>
</v-card-text>
</panel>
</v-dialog>
Expand Down Expand Up @@ -139,16 +183,21 @@ import {
mdiHelpCircle,
mdiRestart,
mdiUsb,
mdiFormatListCheckbox,
} from '@mdi/js'
import type Codemirror from '@/components/inputs/Codemirror.vue'
import DevicesDialog from '@/components/dialogs/DevicesDialog.vue'
import { ConfigFileSection } from '@/store/files/types'
@Component({
components: { DevicesDialog, Panel, CodemirrorAsync },
})
export default class TheEditor extends Mixins(BaseMixin) {
dialogConfirmChange = false
dialogDevices = false
fileStructureSidebar = true
structureActive: number[] = []
structureOpen: number[] = []
formatFilesize = formatFilesize
Expand All @@ -164,6 +213,7 @@ export default class TheEditor extends Mixins(BaseMixin) {
mdiFileDocumentEditOutline = mdiFileDocumentEditOutline
mdiFileDocumentOutline = mdiFileDocumentOutline
mdiUsb = mdiUsb
mdiFormatListCheckbox = mdiFormatListCheckbox
declare $refs: {
editor: Codemirror
Expand Down Expand Up @@ -305,6 +355,44 @@ export default class TheEditor extends Mixins(BaseMixin) {
return url
}
get configFileStructure() {
if (['conf', 'cfg'].includes(this.fileExtension)) {
const sourcecode = this.sourcecode
const lines = sourcecode.split(/\n/gi)
const regex = /^[^#\S]*?(\[(?<section>.*?)]|(?<name>\w+)\s*?[:=])/gim
let section = null
let name = null
let structure: ConfigFileSection[] = []
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
const matches = [...line.matchAll(regex)]
if (matches.length > 0) {
const match = matches[0]
if (match['groups']['section']) {
section = match['groups']['section']
structure.push({
name: section,
type: 'section',
line: i + 1,
children: [],
})
} else if (match['groups']['name']) {
name = match['groups']['name']
structure[structure.length - 1]['children'].push({
name: name,
type: 'item',
line: i + 1,
})
}
}
}
this.fileStructureSidebar = true
return structure
}
this.fileStructureSidebar = false
return null
}
cancelDownload() {
this.$store.dispatch('editor/cancelLoad')
}
Expand Down Expand Up @@ -337,6 +425,29 @@ export default class TheEditor extends Mixins(BaseMixin) {
})
}
showFileStructure() {
this.fileStructureSidebar = !this.fileStructureSidebar
}
activeChanges(key: any) {
this.$refs.editor.gotoLine(key)
}
lineChanges(line: number) {
this.configFileStructure?.map((item) => {
if (item.line == line) {
this.structureActive = [line]
} else {
item.children?.map((child) => {
if (child.line == line) {
this.structureActive = [line]
if (!this.structureOpen.includes(item.line)) this.structureOpen.push(item.line)
}
})
}
})
}
@Watch('changed')
changedChanged(newVal: boolean) {
if (!this.confirmUnsavedChanges) return
Expand Down Expand Up @@ -398,4 +509,15 @@ export default class TheEditor extends Mixins(BaseMixin) {
background-color: var(--color-primary);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E %3Cpath d='M15.88 8.29L10 14.17l-1.88-1.88a.996.996 0 1 0-1.41 1.41l2.59 2.59c.39.39 1.02.39 1.41 0L17.3 9.7a.996.996 0 0 0 0-1.41c-.39-.39-1.03-.39-1.42 0z' fill='%23fffff'/%3E %3C/svg%3E");
}
@media screen and (min-width: 960px) {
.structure {
margin-right: 300px
}
.structure-sidebar {
width: 300px;
overflow-y: auto;
}
}
</style>
13 changes: 12 additions & 1 deletion src/components/inputs/Codemirror.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ export default class Codemirror extends Mixins(BaseMixin) {
setCmValue(content: string) {
this.cminstance?.setState(EditorState.create({ doc: content, extensions: this.cmExtensions }))
}
get cmExtensions() {
const extensions = [
EditorView.theme({}, { dark: true }),
Expand All @@ -88,6 +87,10 @@ export default class Codemirror extends Mixins(BaseMixin) {
indentUnit.of(' '.repeat(this.tabSize)),
keymap.of([indentWithTab]),
EditorView.updateListener.of((update) => {
if(update.selectionSet) {
const line = this.cminstance?.state?.doc.lineAt(this.cminstance?.state?.selection.main.head).number
this.$emit('lineChange', line)
}
this.content = update.state?.doc.toString()
if (this.$emit) {
this.$emit('input', this.content)
Expand All @@ -110,5 +113,13 @@ export default class Codemirror extends Mixins(BaseMixin) {
get tabSize() {
return this.$store.state.gui.editor.tabSize || 2
}
gotoLine(line:number){
const l:any = this.cminstance?.state?.doc.line(line);
this.cminstance?.dispatch({
selection: { head: l.from, anchor: l.to },
scrollIntoView: true
});
}
}
</script>
5 changes: 2 additions & 3 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@
"UnsavedChanges": "Unsaved Changes",
"UnsavedChangesMessage": "Do you want to save your changes made to {filename}?",
"UnsavedChangesSubMessage": "Your changes will be lost if you don't save them. You can disable this message in the editor settings.",
"Uploading": "Uploading"
"Uploading": "Uploading",
"FileStructure": "File Structure"

Check failure on line 207 in src/locales/en.json

View workflow job for this annotation

GitHub Actions / ESLint

src/locales/en.json#L207

Expected object keys to be in insensitive ascending order. 'FileStructure' should be before 'Uploading' (jsonc/sort-keys)
},
"EmergencyStopDialog": {
"AreYouSure": "Are you sure?",
Expand Down Expand Up @@ -375,7 +376,6 @@
"EntryNextPerform": "Next perform:",
"EntryPerformedAt": "Performed at {date}.",
"EntrySince": "Used since:",
"EstimatedFilament": "Estimated Filament",
"EstimatedFilamentWeight": "Estimated Filament Weight",
"EstimatedTime": "Estimated Time",
"FilamentBasedReminder": "Filament",
Expand Down Expand Up @@ -426,7 +426,6 @@
"SelectedJobs": "Selected Jobs",
"SelectedPrinttime": "Selected Print Time",
"Slicer": "Slicer",
"SlicerVersion": "Slicer Version",
"StartTime": "Start Time",
"Statistics": "Statistics",
"Status": "Status",
Expand Down
3 changes: 2 additions & 1 deletion src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@
"UnsavedChanges": "有未保存的更改",
"UnsavedChangesMessage": "是否保存对{filename}的更改?",
"UnsavedChangesSubMessage": "如果不保存,您的更改将丢失。您可以在编辑器设置中关闭此提示。",
"Uploading": "正在上传"
"Uploading": "正在上传",
"FileStructure": "结构"

Check failure on line 203 in src/locales/zh.json

View workflow job for this annotation

GitHub Actions / ESLint

src/locales/zh.json#L203

Expected object keys to be in insensitive ascending order. 'FileStructure' should be before 'Uploading' (jsonc/sort-keys)
},
"EmergencyStopDialog": {
"AreYouSure": "确定要执行此操作吗?",
Expand Down
10 changes: 10 additions & 0 deletions src/store/files/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,13 @@ export interface ApiGetDirectoryReturnFile {
filename: string
permissions: string
}

export interface ConfigFileKey{
name: string,
type: string,
line: number
}

export interface ConfigFileSection extends ConfigFileKey{
children: ConfigFileKey[]
}

0 comments on commit b2afe89

Please sign in to comment.