Skip to content

Commit

Permalink
autocompletion improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Williangalvani committed Jul 8, 2024
1 parent b52e0c8 commit f78ad20
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 48 deletions.
72 changes: 32 additions & 40 deletions src/components/ExpressionEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
:value="value"
@input="updateValue($event.target.value)"
@keydown="handleKeyDown"
@scroll="handleScroll"
ref="codeEditor"/>
<div v-if="showSuggestions" class="suggestions-box" :style="suggestionsBoxStyle">
<div v-for="(suggestion, index) in filteredSuggestions"
Expand Down Expand Up @@ -54,12 +53,11 @@ export default {
handleInput () {
const cursorPosition = this.$refs.codeEditor.selectionStart
const textBeforeCursor = this.value.slice(0, cursorPosition)
const words = textBeforeCursor.split(/\s+/)
this.currentWord = words[words.length - 1]
if (this.currentWord.length > 0) {
if (this.shouldShowSuggestions(textBeforeCursor)) {
const currentWord = this.getCurrentWord(textBeforeCursor)
this.filteredSuggestions = this.suggestions.filter(s =>
s.toLowerCase().startsWith(this.currentWord.toLowerCase())
s.toLowerCase().startsWith(currentWord.toLowerCase())
)
this.showSuggestions = this.filteredSuggestions.length > 0
this.selectedIndex = 0
Expand All @@ -68,6 +66,15 @@ export default {
this.showSuggestions = false
}
},
shouldShowSuggestions (text) {
const lastChar = text.slice(-1)
const operators = ['+', '-', '*', '/', '=', '(', ',', ' ']
return operators.includes(lastChar) || /\w/.test(lastChar)
},
getCurrentWord (text) {
// eslint-disable-next-line no-useless-escape
return text.split(/[\s\(\)\+\-\*\/\=,]+/).pop() || ''
},
handleKeyDown (e) {
if (this.showSuggestions) {
switch (e.key) {
Expand Down Expand Up @@ -95,55 +102,41 @@ export default {
const cursorPosition = this.$refs.codeEditor.selectionStart
const textBeforeCursor = this.value.slice(0, cursorPosition)
const textAfterCursor = this.value.slice(cursorPosition)
const lastSpaceIndex = textBeforeCursor.lastIndexOf(' ')
const newTextBeforeCursor = textBeforeCursor.slice(0, lastSpaceIndex + 1) + suggestion
const currentWord = this.getCurrentWord(textBeforeCursor)
const lastChar = textBeforeCursor.slice(-1)
const operators = ['+', '-', '*', '/', '=', '(', ',', ' ']
let newValue
if (operators.includes(lastChar)) {
// If the last character is an operator or opening parenthesis, add the suggestion
newValue = textBeforeCursor + suggestion + textAfterCursor
} else {
// Otherwise, replace the current word with the suggestion
const textBeforeCurrentWord = textBeforeCursor.slice(0, -currentWord.length)
newValue = textBeforeCurrentWord + suggestion + textAfterCursor
}
const newValue = newTextBeforeCursor + textAfterCursor
this.updateValue(newValue)
this.$nextTick(() => {
this.$refs.codeEditor.selectionStart = this.$refs.codeEditor.selectionEnd = newTextBeforeCursor.length
const newCursorPosition = cursorPosition + (suggestion.length - currentWord.length)
this.$refs.codeEditor.selectionStart = this.$refs.codeEditor.selectionEnd = newCursorPosition
this.$refs.codeEditor.focus()
})
this.showSuggestions = false
},
updateCursorPosition () {
const textarea = this.$refs.codeEditor
const cursorPosition = textarea.selectionStart
const textBeforeCursor = this.value.slice(0, cursorPosition)
// const lines = textBeforeCursor.split('\n')
// const currentLine = lines.length
// const currentLineText = lines[lines.length - 1]
const temp = document.createElement('div')
temp.style.position = 'absolute'
temp.style.top = '-9999px'
temp.style.left = '-9999px'
temp.style.width = textarea.clientWidth + 'px'
temp.style.height = 'auto'
temp.style.whiteSpace = 'pre-wrap'
temp.style.wordWrap = 'break-word'
temp.style.font = window.getComputedStyle(textarea).font
temp.textContent = textBeforeCursor + '\n'
document.body.appendChild(temp)
const input = this.$refs.codeEditor
const inputRect = input.getBoundingClientRect()
const { lineHeight } = window.getComputedStyle(textarea)
// const textareaRect = textarea.getBoundingClientRect()
this.cursorPosition = {
top: temp.clientHeight - parseFloat(lineHeight) + textarea.offsetTop,
left: textarea.offsetLeft + 10
}
document.body.removeChild(temp)
},
handleScroll () {
this.scrollTop = this.$refs.codeEditor.scrollTop
if (this.showSuggestions) {
this.updateCursorPosition()
top: 10,
left: inputRect.left
}
}
}
}
</script>

Expand Down Expand Up @@ -173,7 +166,6 @@ export default {
max-height: 150px;
overflow-y: auto;
z-index: 1000;
width: 200px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.suggestion-item {
Expand Down
1 change: 1 addition & 0 deletions src/components/Globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const store = {
plotLoading: false,
timeRange: null,
textMessages: [],
namedFloats: [],
metadata: null,
// cesium menu:
modelScale: 1.0,
Expand Down
7 changes: 7 additions & 0 deletions src/components/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ export default {
console.log('unable to load metadata')
console.log(error)
}
try {
this.state.namedFloats = this.dataExtractor.extractNamedValueFloatNames(this.state.messages)
console.log(this.state.namedFloats)
} catch (error) {
console.log('unable to load named floats')
console.log(error)
}
Vue.delete(this.state.messages, 'AHR2')
Vue.delete(this.state.messages, 'POS')
Vue.delete(this.state.messages, 'GPS')
Expand Down
18 changes: 11 additions & 7 deletions src/components/PlotSetup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,6 @@ import { store } from './Globals.js'
import debounce from 'v-debounce'
import ExpressionEditor from './ExpressionEditor.vue'
const additionalCompletionItems = [
'mag_heading_df(MAG[0],ATT)',
'mag_heading(RAW_IMU,ATTITUDE)',
'named(NAMED_VALUE_FLOAT,"InputHold")'
]
export default {
name: 'PlotSetup',
components: {
Expand All @@ -105,12 +99,22 @@ export default {
}
},
computed: {
additionalCompletionItems () {
const additionalCompletionItems = [
'mag_heading_df(MAG[0],ATT)',
'mag_heading(RAW_IMU,ATTITUDE)'
]
for (const name of this.state.namedFloats) {
additionalCompletionItems.push(`named(NAMED_VALUE_FLOAT,"${name}")`)
}
return additionalCompletionItems
},
completionOptions () {
const messageOptions = Object.keys(this.state.messageTypes).flatMap(key => {
const fields = this.state.messageTypes[key].expressions.map(field => `${key}.${field}`)
return [key, ...fields]
})
return [...additionalCompletionItems, ...messageOptions]
return [...this.additionalCompletionItems, ...messageOptions]
}
},
methods: {
Expand Down
5 changes: 5 additions & 0 deletions src/tools/dataflashDataExtractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,11 @@ export class DataflashDataExtractor {
return ret
}

static extractNamedValueFloatNames (_messages) {
// this mechanism is not used for dataflash logs
return []
}

static extractStartTime (messages) {
return extractStartTime(messages)
}
Expand Down
7 changes: 7 additions & 0 deletions src/tools/mavlinkDataExtractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,13 @@ export class MavlinkDataExtractor {
return texts
}

static extractNamedValueFloatNames (messages) {
if ('NAMED_VALUE_FLOAT' in messages) {
return Array.from(new Set(messages.NAMED_VALUE_FLOAT.name))
}
return []
}

static extractStartTime (messages) {
return undefined
}
Expand Down
3 changes: 2 additions & 1 deletion src/tools/parsers/mavlinkParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ export class MavlinkParser {
'PARAM_VALUE',
'STATUSTEXT',
'AHRS2',
'AHRS3']
'AHRS3',
'NAMED_VALUE_FLOAT',]
for (const i in preparseList) {
this.mavlinkParser.parseType(preparseList[i])
self.postMessage({ percentage: (i / preparseList.length) * 100 })
Expand Down

0 comments on commit f78ad20

Please sign in to comment.