Skip to content

Commit 4197db5

Browse files
authored
Merge pull request #651 from JunoLab/avi/partialdots
RFC: strip trailing dots
2 parents 0ceb274 + d4358c0 commit 4197db5

File tree

5 files changed

+106
-30
lines changed

5 files changed

+106
-30
lines changed

lib/misc/blocks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export function get (ed) {
130130
export function getLocalContext (editor, row) {
131131
const range = getRange(editor, row)
132132
const context = range ? editor.getTextInBufferRange(range) : ''
133-
const startRow = range ? range[0][0] : null
133+
const startRow = range ? range[0][0] : undefined
134134
return {
135135
context,
136136
startRow

lib/misc/words.js

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,51 @@ export const wordRegex = /[\u00A0-\uFFFF\w_!´\.]*@?[\u00A0-\uFFFF\w_!´]+/
99
* function `fn` with arguments `word` and `range`.
1010
*/
1111
export function withWord (editor, fn) {
12-
const { word, range } = getWord(editor)
12+
const { word, range } = getWordAndRange(editor)
1313
// If we only find numbers or nothing, return prematurely
1414
if (!isValidWordToInspect(word)) return
1515
fn(word, range)
1616
}
1717

1818
/**
19-
* Gets the word and its range in the `editor`
19+
* Returns the word and its range in the `editor`.
2020
*
21-
* `bufferPosition` {Point}: If given returns the word at the `bufferPosition`, returns the word at the current cursor otherwise.
21+
* `options`
22+
* - `bufferPosition` {Point}: If given returns the word at the `bufferPosition`, returns the word at the current cursor otherwise.
23+
* - `wordRegex` {RegExp} : A RegExp indicating what constitutes a “word” (default: `wordRegex`).
2224
*/
23-
export function getWord (editor, bufferPosition) {
25+
export function getWordAndRange (editor, options = {
26+
bufferPosition: undefined,
27+
wordRegex: wordRegex
28+
}) {
2429
// @TODO?:
2530
// The following lines are kinda iffy: The regex may or may not be well chosen
2631
// and it duplicates the efforts from atom-language-julia.
2732
// It might be better to select the current word via finding the smallest <span>
2833
// containing the bufferPosition/cursor which also has `function` or `macro` as its class.
29-
const range = bufferPosition ?
30-
getWordRangeAtBufferPosition(editor, bufferPosition) :
31-
editor.getLastCursor().getCurrentWordBufferRange({ wordRegex })
34+
const bufferPosition = options.bufferPosition ?
35+
options.bufferPosition :
36+
editor.getLastCursor().getBufferPosition()
37+
const range = getWordRangeAtBufferPosition(editor, bufferPosition, {
38+
wordRegex: options.wordRegex ? options.wordRegex : wordRegex
39+
})
3240
const word = editor.getTextInBufferRange(range)
3341
return { word, range }
3442
}
3543

3644
/**
37-
* get the word under `bufferPosition` in `editor`
38-
* adapted from https://github.com/atom/atom/blob/v1.38.2/src/cursor.js#L606-L616
45+
* Returns the range of a word containing the `bufferPosition` in `editor`.
3946
*
40-
* - optionalWordRegex: if not given, the toplevel `wordRegex` would be used
47+
* `options`
48+
* - `wordRegex` {RegExp}: A RegExp indicating what constitutes a “word” (default: `wordRegex`).
4149
*/
42-
export function getWordRangeAtBufferPosition(editor, bufferPosition, optionalWordRegex) {
50+
export function getWordRangeAtBufferPosition (editor, bufferPosition, options = {
51+
wordRegex: wordRegex
52+
}) {
53+
// adapted from https://github.com/atom/atom/blob/v1.38.2/src/cursor.js#L606-L616
4354
const { row, column } = bufferPosition
4455
const ranges = editor.getBuffer().findAllInRangeSync(
45-
optionalWordRegex || wordRegex,
56+
options.wordRegex ? options.wordRegex : wordRegex,
4657
new Range(new Point(row, 0), new Point(row, Infinity))
4758
)
4859
const range = ranges.find(range =>
@@ -51,6 +62,35 @@ export function getWordRangeAtBufferPosition(editor, bufferPosition, optionalWor
5162
return range ? Range.fromObject(range) : new Range(bufferPosition, bufferPosition)
5263
}
5364

65+
/**
66+
* Examples: `|` represents `bufferPosition`:
67+
* - `"he|ad.word.foot"` => `Range` of `"head"`
68+
* - `"head|.word.foot"` => `Range` of `"head"`
69+
* - `"head.|word.foot"` => `Range` of `"head.word"`
70+
* - `"head.word.fo|ot"` => `Range` of `"head.word.field"`
71+
*/
72+
export function getWordRangeWithoutTrailingDots (word, range, bufferPosition) {
73+
const { start } = range
74+
const { column: startColumn } = start
75+
const { row: endRow } = range.end
76+
let endColumn = startColumn
77+
78+
const { column } = bufferPosition
79+
80+
const elements = word.split('.')
81+
for (const element of elements) {
82+
endColumn += element.length
83+
if (column <= endColumn) {
84+
break
85+
} else {
86+
endColumn += 1
87+
}
88+
}
89+
90+
const end = new Point(endRow, endColumn)
91+
return new Range(start, end)
92+
}
93+
5494
/**
5595
* Returns `true` if `word` is valid word to be inspected.
5696
*/

lib/runtime/datatip.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111
import { client } from '../connection'
1212
import modules from './modules'
1313
import { isValidScopeToInspect } from '../misc/scopes'
14-
import { getWord, isValidWordToInspect } from '../misc/words'
14+
import {
15+
getWordAndRange,
16+
getWordRangeWithoutTrailingDots,
17+
isValidWordToInspect
18+
} from '../misc/words'
1519
import { getLocalContext } from '../misc/blocks'
1620

1721
const datatip = client.import('datatip')
@@ -34,9 +38,15 @@ class DatatipProvider {
3438
// If the scope at `bufferPosition` is not valid code scope, do nothing
3539
if (!isValidScopeToInspect(editor, bufferPosition)) return
3640

37-
// Check the validity of code to be inspected
38-
const { range, word } = getWord(editor, bufferPosition)
39-
if (!isValidWordToInspect(word)) return
41+
// get word without trailing dot accessors at the buffer position
42+
let { range, word } = getWordAndRange(editor, {
43+
bufferPosition
44+
})
45+
range = getWordRangeWithoutTrailingDots(word, range, bufferPosition)
46+
word = editor.getTextInBufferRange(range)
47+
48+
// check the validity of code to be inspected
49+
if (!(isValidWordToInspect(word))) return
4050

4151
const { main, sub } = await modules.getEditorModule(editor, bufferPosition)
4252
const mod = main ? (sub ? `${main}.${sub}` : main) : 'Main'

lib/runtime/evaluation.coffee

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,13 @@ module.exports =
8585
workspace.update()
8686

8787
toggleDocs: (word, range) ->
88-
{editor, mod, edpath} = @_currentContext()
89-
{word, range} = words.getWord(editor) unless word? and range?
90-
if word.length == 0 || !isNaN(word) then return
88+
{ editor, mod, edpath } = @_currentContext()
89+
# get word without trailing dot accessors at the buffer position
90+
{ word, range } = words.getWordAndRange(editor) unless word? and range?
91+
range = words.getWordRangeWithoutTrailingDots(word, range, bufferPosition)
92+
word = editor.getTextInBufferRange(range)
93+
94+
return unless words.isValidWordToInspect(word)
9195
searchDoc({word: word, mod: mod}).then (result) =>
9296
if result.error then return
9397
v = views.render result

lib/runtime/goto.js

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ import { CompositeDisposable, Range } from 'atom'
77
import { client } from '../connection'
88
import modules from './modules'
99
import { isValidScopeToInspect } from '../misc/scopes'
10-
import { getWord, getWordRangeAtBufferPosition, isValidWordToInspect } from '../misc/words'
10+
import {
11+
getWordAndRange,
12+
getWordRangeAtBufferPosition,
13+
getWordRangeWithoutTrailingDots,
14+
isValidWordToInspect
15+
} from '../misc/words'
1116
import { getLocalContext } from '../misc/blocks'
1217

1318
const {
@@ -34,11 +39,15 @@ class Goto {
3439
}
3540

3641
getJumpFilePath(editor, bufferPosition) {
37-
const includeRange = getWordRangeAtBufferPosition(editor, bufferPosition, includeRegex)
42+
const includeRange = getWordRangeAtBufferPosition(editor, bufferPosition, {
43+
wordRegex: includeRegex
44+
})
3845
if (includeRange.isEmpty()) return false
3946

4047
// return if the bufferPosition is not on the path string
41-
const filePathRange = getWordRangeAtBufferPosition(editor, bufferPosition, filePathRegex)
48+
const filePathRange = getWordRangeAtBufferPosition(editor, bufferPosition, {
49+
wordRegex: filePathRegex
50+
})
4251
if (filePathRange.isEmpty()) return false
4352

4453
const filePathText = editor.getTextInBufferRange(filePathRange)
@@ -71,8 +80,15 @@ class Goto {
7180

7281
if (!this.isClientAndInkReady()) return
7382

74-
const { word } = getWord(editor, bufferPosition)
75-
if (!isValidWordToInspect(word)) return
83+
// get word without trailing dot accessors at the buffer position
84+
let { word, range } = getWordAndRange(editor, {
85+
bufferPosition
86+
})
87+
range = getWordRangeWithoutTrailingDots(word, range, bufferPosition)
88+
word = editor.getTextInBufferRange(range)
89+
90+
// check the validity of code to be inspected
91+
if (!(isValidWordToInspect(word))) return
7692

7793
// local context
7894
const { column, row } = bufferPosition
@@ -123,12 +139,18 @@ class Goto {
123139
// If Julia is not running, do nothing
124140
if (!this.isClientAndInkReady()) return
125141

126-
const { word, range } = getWord(textEditor, bufferPosition)
127-
128142
// If the scope at `bufferPosition` is not valid code scope, do nothing
129143
if (!isValidScopeToInspect(textEditor, bufferPosition)) return
130-
// Check the validity of code to be inspected
131-
if (!isValidWordToInspect(word)) return
144+
145+
// get word without trailing dot accessors at the buffer position
146+
let { word, range } = getWordAndRange(textEditor, {
147+
bufferPosition
148+
})
149+
range = getWordRangeWithoutTrailingDots(word, range, bufferPosition)
150+
word = textEditor.getTextInBufferRange(range)
151+
152+
// check the validity of code to be inspected
153+
if (!(isValidWordToInspect(word))) return
132154

133155
// local context
134156
const { column, row } = bufferPosition
@@ -139,7 +161,7 @@ class Goto {
139161
const mod = main ? (sub ? `${main}.${sub}` : main) : 'Main'
140162
const text = textEditor.getText() // buffer text that will be used for fallback entry
141163

142-
return new Promise((resolve, reject) => {
164+
return new Promise((resolve) => {
143165
gotoSymbol({
144166
word,
145167
path: textEditor.getPath(),

0 commit comments

Comments
 (0)