Skip to content

Commit

Permalink
Merge pull request #83 from lukashornych/dev
Browse files Browse the repository at this point in the history
feat(#70): codemirror status bar with selection info and spaces info
  • Loading branch information
lukashornych authored Dec 6, 2023
2 parents 8151308 + 41cff2a commit 12c7b17
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 8 deletions.
21 changes: 18 additions & 3 deletions src/components/base/CodemirrorFull.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ import { EditorState, Extension } from '@codemirror/state'
import { keymap } from '@codemirror/view'
import { basicSetup } from 'codemirror'
import { dracula } from '@ddietr/codemirror-themes/dracula.js'
import { ref } from 'vue'
import CodemirrorFullStatusBar from '@/components/base/CodemirrorFullStatusBar.vue'
const props = withDefaults(
defineProps<{
modelValue: string
additionalExtensions?: Extension[]
placeholder?: string
readOnly?: boolean,
disabled?: boolean
disabled?: boolean,
statusBar?: boolean
}>(),
{
readOnly: false,
disabled: false,
statusBar: true,
additionalExtensions: () => []
}
)
Expand All @@ -43,18 +47,24 @@ const extensions: Extension[] = [
if (props.readOnly) {
extensions.push(EditorState.readOnly.of(true))
}
const state = ref<EditorState>()
</script>

<template>
<div class="cm-full">
<div :class="['cm-full', { 'cm-full--with-status-bar': statusBar }]">
<Codemirror
:model-value="modelValue"
:extensions="extensions"
:placeholder="placeholder"
:disabled="disabled"
@update="state = $event.state"
@update:model-value="$emit('update:modelValue', $event)"
style="height: 100%; cursor: text;"
/>
<VSheet v-if="statusBar" class="status-bar">
<CodemirrorFullStatusBar :state="state" />
</VSheet>
</div>
</template>

Expand All @@ -65,6 +75,11 @@ if (props.readOnly) {
left: 0;
right: 0;
top: 0;
bottom: 0;
bottom: 2rem;
}
.status-bar {
display: flex;
justify-content: right;
}
</style>
37 changes: 37 additions & 0 deletions src/components/base/CodemirrorFullStatusBar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script setup lang="ts">
/**
* Render the status bar of a single editor with info like selection, spaces, and so on.
*/
import { EditorState } from '@codemirror/state'
import CodemirrorFullStatusBarSelection from '@/components/base/CodemirrorFullStatusBarSelection.vue'
const props = defineProps<{
state?: EditorState
}>()
</script>

<template>
<div v-if="state" class="status-bar">
<span v-if="state.selection.ranges.length > 1">
{{ state.selection.ranges.length }} selections
</span>
<span v-else-if="state.selection.ranges.length === 1">
<CodemirrorFullStatusBarSelection :doc="state.doc" :selection-range="state.selection.ranges[0]" />
</span>

<span class="text-no-wrap">
{{state.tabSize}} spaces
</span>
</div>
</template>

<style lang="scss" scoped>
.status-bar {
height: 2rem;
display: flex;
column-gap: 1rem;
align-items: center;
padding: 0 0.5rem;
}
</style>
49 changes: 49 additions & 0 deletions src/components/base/CodemirrorFullStatusBarSelection.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<script setup lang="ts">
/**
* Render detailed info about the current text selection.
*/
import { Text, SelectionRange, Line } from '@codemirror/state'
import { computed } from 'vue'
const props = defineProps<{
doc: Text,
selectionRange: SelectionRange
}>()
const headLine = computed<Line>(() => {
return props.doc.lineAt(props.selectionRange.head)
})
const anchorLine = computed<Line>(() => {
return props.doc.lineAt(props.selectionRange.anchor)
})
const headPositionInLine = computed<number>(() => {
return props.selectionRange.head - headLine.value.from + 1
})
const selectedCharsCount = computed<number>(() => {
if (props.selectionRange.empty) {
return 0
}
return Math.abs(props.selectionRange.anchor - props.selectionRange.head)
})
const selectedLinesCount = computed<number>(() => {
if (props.selectionRange.empty) {
return 0
}
return Math.abs(anchorLine.value.number - headLine.value.number)
})
</script>

<template>
<span class="text-no-wrap">
Ln {{ headLine.number }}, Col {{ headPositionInLine }}
<template v-if="!selectionRange.empty">
({{ selectedCharsCount }} chars<template v-if="selectedLinesCount">, {{ selectedLinesCount }} line breaks</template>)
</template>
</span>
</template>

<style lang="scss" scoped>
</style>
13 changes: 8 additions & 5 deletions src/model/lab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ export class EvitaDBConnection {
readonly id: EvitaDBConnectionId
readonly name: string
readonly preconfigured: boolean
readonly labApiUrl: string
readonly restUrl: string
readonly gqlUrl: string
readonly labApiUrl?: string
readonly restUrl?: string
readonly gqlUrl?: string

constructor(id: EvitaDBConnectionId | undefined, name: string, preconfigured: boolean, labApiUrl: string, restUrl: string, gqlUrl: string) {
constructor(id: EvitaDBConnectionId | undefined, name: string, preconfigured: boolean, labApiUrl?: string, restUrl?: string, gqlUrl?: string) {
this.id = id ? id : uuidv4()
this.name = name
this.preconfigured = preconfigured
Expand All @@ -29,7 +29,10 @@ export class EvitaDBConnection {
return new EvitaDBConnection(json.id, json.name, preconfigured, json.labApiUrl, json.restUrl, json.gqlUrl)
}

private normalizeApiUrl(url: string): string {
private normalizeApiUrl(url: string | undefined): string | undefined {
if (url == undefined) {
return undefined
}
return url.endsWith('/') ? url.substring(0, url.length - 1) : url
}
}
Expand Down

0 comments on commit 12c7b17

Please sign in to comment.