-
Notifications
You must be signed in to change notification settings - Fork 632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Supporting vue (Was: require new features with {scope}) #1577
Comments
Interesting idea but it needs consideration.
Implementing this is not difficult. I wonder
Ctags can push a language object which is tagged to the scope stack. BTW, matchTagPattern() in main/lregex.c is the function where scope stack is used.
I guess you may want to make the following tag:
We have to fill ???. I know how useful the feature you propose is. With the reference tag, you can capture "Parent" in the code as a reference tag. I'm working on implementing the way to capture reference tags via regex parser very slowly. Your proosal may be implemented on that. Do you have any target language? #. an example input file (shorter is better) You can use any imaginary options in the last item. BTW, matchTagPattern() is the function in which the scope stack is uesd. |
i am writing Vue, like this (i have delete all the function body..) <script>
import _ from 'underscore'
import MTableRow from './m-table-row'
let eachColumn = {
'data': [], // do not want to match this!
'subfields': {},
}
function abyb (a, b) {
.....
}
export default {
name: 'm-table',
props: {
'data': {
'type': [Object],
'default': function () {
return {
'columns': [],
'fixColumnCount': null
}
}
}
},
data () { // want to match this
return {
'addable': false,
'deletable': false
}
},
computed: {
style () {
},
headerIDStr: {
cache: false,
get () {
}
}
},
'methods': {
initData () {
},
getColumn (index) {
},
getColumnShow (index) {
},
updateColumnSort () {
},
getData (data, index) {
},
updateRowSort (sortBy) {
},
onMouseOverHeader () {
}
},
created () {
this.initData()
},
components: {MTableRow}
}
</script> the name, data, props, computed, methods, created in this context (<script></script> ==> export default {} ) are things i want to display, like this
i just want to match the "data ()" in the export default {}, not before that in "let eachColumn = {}", so i want the feature of boolean expression to make a constrain, like
|
also, i tried |
Looks like a job for the JavaScript parser for it to emit something for the |
It is possible to run js parser areas which are embedded in another language like html. As far as seeing https://vuejs.org/images/vue-component.png, Writing the vue parser in C language is one of approach. More interesting one is extending regex
More studying vue is needed. |
After thinking again, we don't have to extend the mline-regex parser right now. Even writing in C language, picking the areas ( |
actually i do not want to run a JavaScript parser in the <script>...</script> area, that will list too many symbols, i want to focus on the overview structure of the .vue file, and list
i don't know if it's possible without write a custom parser and only with improved regex-Vue command =================update================
that is to add variables and if expression into the --regex syntax, i thing it will help a lot and make the ctags much more powerful |
If the requirement are too complex, i'd like to try to write a custom parser, is there any demo or doc for that? |
If it were me, I'd just hack the Vue code to make it emit ctags format, since it already knows how to parse the single file components and embedded languages. |
hi @codebrainz
|
Probably, I'm the wrong person to ask, I only ever wrote a very simple parser for a simple language for the old ctags.
I mean to modify the front-end code of Vue.js and make it only emit ctags' simple tags format to a file rather than doing all the other stuff Vue.js does after the front-end. I have no idea how practical that would be, but on the surface it seems simpler. |
Yes, you are right. i use Webpack to handle my project, so maybe i can write a preload plugin to generate ctag file using javascript, it's much more easier, thanks. |
i read the ctags documents, it says
the universal-ctags add {scope} flag so that we can record the context during parsing, i think the things i talk above are to use the context variable and make the regex-based parser context-sensitive, that will make the parser much more powerful as far as i understand, the parser try all the regex one by one for each line, so i think we can add some 'if' flag or 'set variable' flag in the syntax, the command should run before or after doing actual regex match
like this
that is to make the {flags} a small language with only 'if' expression and basic variable assignment and operation |
Of course, I would like to add the code for parsing javascript source code using vue framework to ctags. I think adding vue parsr as a sub parser of javascript parser is the best. Reducing the information can be done after parsing. Give me time. I'm catching up the discussion and learning vue. |
@masatake Anyway, i still thinks it will make ctags much more powerful adding the "if" and "set" feature(i'd like to use it on some formatted file to generate navigation flags), since it will make the parser context-sensitive. This feature may cost some time to develop, you can think about it later. Also as you said, adding the {scope=replace} flag is not difficult, so please consider to develop this feature first when you have time. |
I have no idea if this makes sense in the context of ctags parsers, but a single-file view component is almost identical to a regular HTML document containing embedded CSS and JS. Does it make sense to improve the HTML parser to somehow be able to handle CSS and JSS (using subparser)? |
@codebrainz, you may correct. Using HTML as a host parser will be better. Anyway, I think we can do very interesting thing with existing code. |
https://vue-loader.vuejs.org/en/start/spec.html @codebrainz, do you think we should run html parser for .vue file? My idea is introducing a small vue parser. |
@Fmajor, my understanding is that what you want is the top level keys in
|
@masatake it's part of JavaScript proper, and I don't believe it's the only way to achieve the same thing for Vue. |
Oh, @b4n already wrote about "export".
If JavaScript parser handling the block well, all parts of ctags may work
fine.
export is something like prototype in C.
I like using reference tag with "unknown" kind and ... "exported" role.
Anyway a special kind for it is needed. Maybe it is what @Fmajor wants.
When thinking about scope, things are not simple. If a::b is exported in c,
I wonder which scope b should have: a or c. Here b is taged as a reference
tag. In natural langauage, I can say b defined b is exported from c.
Or c::a::b?
2017/10/20 午後2:15 "Matthew Brush" <notifications@github.com>:
… @masatake <https://github.com/masatake> it's part of JavaScript proper
<https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export>,
and I don't believe it's the only way to achieve the same thing for Vue.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1577 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAEtFTv5GsERS-SSyxhGV4IrXBRscLyAks5suCyAgaJpZM4P3arD>
.
|
Surprisingly a function can be defiend in export block... |
@b4n, ctags vue parser I implemented can push an area inside So could you consider how JavaScript parser deals with the
VueJavaScript subparser picks up only |
I tried to apply the latest version ctags install from homebrew on some js file, but it failed to extract the "export default" part let me explain my requests (and why i need it) in more detail. But things are different when i change to .vue (javascript). a .vue file are usually like <template>
<!-- some html code -->
<div> ... </div>
<!-- some html code with v-command (like v-if, v-for) and injected js command -->
<div v-if="showTag === true">
<div v-for="eachItem in data"> ... </div>
</div>
</template>
<script>
// local functions and variables
var a = 1, b = 2
function test () {}
var d = function () {}
var e = () => {}
export default {
name: 'name of a component',
props: {
'data': {
'type': [Object],
'default': function () {
return {
'columns': [],
'fixColumnCount': null
}
}
}
},
data () {
return {
'show': false
}
},
computed: {
style () {
},
},
'methods': { // this is usually a LARGE dict and will take 50% of the total file
someMethod0 () {
},
someMethod1 () {
},
someMethod0 () {
}
},
created () {
},
components: {MTableRow}
}
</script>
<style>
</style> vue file descript properties of a vue component, we care only about the overall structure of it my final purpose is to quickly nagivate to the variable/functions i'm working on, in a vue file, those things are
so the export default part is just a normal dict {}, nothing special it seems to parse the vue perfectly if use different parser in the usually in a vue file, the export part will take 80% lines of the file, if we just parse the export dict as a single value, it's useless. what all the vue people what is to
even if the 'default' dict is specially parsed, it's still not enough, we need to recursively parse the dict at least to level tow. as show in 4.3 the 'methods' dict which contains many functions usually take 50% lines of this file, we want to list these functions, so we need to parse the dict like a syntax analyzer. because people usually use vue-cli and webpack to start and manage a vue project, which use eslint as the syntax checker, the vue file are always in good format, its easy to satisfy my requests using custom --regex-vue, i have post a figure above, its not perfect but usable for me, and save me a lot of time in nagivation these days. I understand these features may take a lot of time, i just give my suggestion here. Maybe it's my own minorities and niche interests, but if you think it reasonable, please add these features (maybe in your own ways). if we just want to solve the vue parser problem, we need to write a special parser, the solution of samply applying javascript parser on the <script> part will lose useful symbols of on average 50% lines of the total file, since functions in 'method' is in the second level depth, we need a context-sensitive syntax analyzer like parser to parse it. ps: IF the javascript parse CAN recursively parse all the dict, there will be anohter problem: toooooooooo many tags (since we only care about the overview structure). we can make some program to filter tags file later, but it's hard to integrate that program into plugins in many editer(like tagbar in vim and Symbal-tree-view in atom), these plugins will autorun "ctags" command after you modify the file and then update the visual tree view of the tags file, we need to add some 'filter' properties into ctags itself. The context-sensitive features in {scope} will help do this. |
See #1581. I made a prototype that parsers inside |
The prototype is updated. See 61d77c8 . At least we have to do
This is the first time stacking 3 parsers for single input(Vue/JavaScript/VueJavaScript). @Fmajor, your proposal about extending scope long flags of regex parser is interesting. However, I cannot find the way to implement some parts of the proposal. ( |
See above session:
|
It worked. Thanks! |
@andbar-ru, thak you.
This is not an issue yet because ctags hs not pug parser yet.
This is a critical issue. At least I have to make the guest regex flag stackable.
This is not an issue yet because ctags doesn't have less, sass and stylus parsers.
Do you mean ctags emits too many tags?
There is no choice. Exuberant-ctags introduced "class" kind ago. Universal-ctags follows it. Anyway, I think advanced users like you can enjoy the optlib-based-vue branch. |
Use cases of nested <template>'s can be found on page https://vuejs.org/v2/guide/conditional.html. Nested templates are used when one needs combine multiple tags under common directive, for example v-if, v-else, v-show. 78 lines. Click to expand<template>
<div id="GeoTools">
<basemap
ref="basemap"
class="geotools-basemap"
:geoObjects="geoObjects"
:allowEditing="true"
:drawButtons="config.drawButtons"
:drawnLimit="1"
:drawnStyle="config.drawnStyle"
:useOnlySecuredTiles="false"
:tileSource="config.tileSource"
></basemap> <div id="ButtonPanel" class="ui top fixed inverted thirteen tiny item menu">
<div class="ui left dropdown item" id="sectionsMenu">
{{ section }}
<i class="dropdown icon"></i>
<div class="menu">
<div class="item" id="shapesSection" @click="section = 'Shapes'">Рисование</div>
<div class="item" id="spatialSection" @click="section = 'Spatial'">Данные ГПИ</div>
<div class="item" id="scriptsSection" @click="section = 'Scripts'">Сценарии работы</div>
</div>
</div>
<template v-if="section === 'Spatial'">
<a class="item" id="addToCollection" @click="run('addToCollection', spatialData[0])"><i class="icon download"></i>add to</a>
<a class="item" id="clearCollection" :class="{disabled: !geoObjects.length}" @click="run('clearCollection', [])"><i class="icon remove"></i>clear all</a>
<a class="item" id="replaceCollection" @click="run('replaceCollection', spatialData.slice(1))"><i class="icon block layout"></i>set other</a>
<a class="item" id="dropFromCollection" :class="{disabled: !geoObjects.length}" @click="run('dropFromCollection', geoObjects[0].id)"><i class="icon upload"></i>drop from</a>
<a class="item" id="setSpatialStyle" :class="{disabled: !geoObjects.length}" @click="run('setSpatialStyle', geoObjects[0].id, {color: 'lime', fillColor: 'orange'})"><i class="icon flag"></i>set style</a>
<a class="item" id="resetSpatialStyle" :class="{disabled: !geoObjects.length}" @click="run('resetSpatialStyle')"><i class="icon flag outline"></i>reset style</a>
<a class="item" id="selectItem" :class="{disabled: !geoObjects.length}" @click="run('selectItem', geoObjects[0].id)"><i class="icon plus"></i>select</a>
<a class="item" id="deselectItem" :class="{disabled: !geoObjects.length}" @click="run('deselectItem', geoObjects[0].id)"><i class="icon minus"></i>deselect</a>
<a class="item" id="replaceSelection" :class="{disabled: !selectedGeoObjects.length}" @click="run('replaceSelection', geoObjects.slice(1).map((o) => { return o.id }))"><i class="icon flag exchange"></i>reselect</a>
<a class="item" id="clearSelection" :class="{disabled: !selectedGeoObjects.length}" @click="run('clearSelection')"><i class="icon flag remove"></i>unselect</a>
<a class="item" id="loadAssetTiles" :class="{disabled: !selectedGeoObjects.length}" @click="run('loadAssetTiles', selectedGeoObjects[0].id)"><i class="icon table"></i>load tiles</a>
<a class="item" id="removeAssetTiles" :class="{disabled: !selectedGeoObjects.length}" @click="run('removeAssetTiles', selectedGeoObjects[0].id)"><i class="icon tv"></i>remove tiles</a>
</template> <template v-if="section === 'Shapes'">
<a class="item" id="setViewport" @click="run('setViewport', [[-180, -90], [180, 90]])"><i class="icon location arrow"></i>set view</a>
<a class="item" id="addLabel" @click="run(
'addLabel',
'<myLabelUniqueIdentificator>',
[59.99204, 29.76933],
'Кронштадт. Петровский док',
undefined,
{
'color': 'lime',
'border': '1px solid yellow',
'background-color': 'rgba(0, 0, 0, 0.5)',
'padding': '5px',
}
)"><i class="icon font"></i>add label</a>
<a class="item" id="setLabelStyle" @click="run(
'setLabelStyle',
'<myLabelUniqueIdentificator>',
{'background-color': 'red', 'border': '1px solid lime'}
)"><i class="flag checkered icon"></i>label style</a>
<a class="item" id="removeLabel" @click="run('removeLabel', '<myLabelUniqueIdentificator>')"><i class="icon remove"></i>remove label</a>
<a class="item" id="activateDrawingTool" @click="run('activateDrawingTool', 'polygon')"><i class="icon pencil"></i>act tool</a>
<a class="item" id="deactivateDrawingTool" @click="run('deactivateDrawingTool')"><i class="icon hand paper"></i>deact tool</a>
<a class="item" id="setShapeStyle" @click="run('setShapeStyle', {'color': 'maroon', 'fillColor': 'red'})"><i class="icon flag"></i>set style</a>
<a class="item" id="resetShapeStyle" @click="run('resetShapeStyle')"><i class="icon flag outline"></i>reset style</a>
<a class="item" id="clearAllShapes" @click="run('clearAllShapes')"><i class="icon remove"></i>clear shapes</a>
<a class="item" id="getGeoJsonData" @click="testGetGeoJsonData()"><i class="icon info"></i>log geojson</a>
</template> <template v-if="section === 'Scripts'">
<a class="item" id="loopedSelection" @click="play('loopedSelection')"><i class="icon recycle"></i>loop-style</a>\
<a class="item" id="batchAddAndStyle" @click="play('batchAddAndStyle')"><i class="icon group object"></i>batch-add</a>\
<a class="item" id="addLayerAsDrawn" @click="play('addLayerAsDrawn')"><i class="icon plus object"></i>layer-add</a>\
</template>
</div> <logger ref="logger"></logger>
</div>
</template> |
I think that vue syntax is too complex to be parsed with regular expressions, particularly with |
Can one apply {_guest} to a table defined with |
Yes. The flag is applicable to mtbale parsers. |
The original post is still very meaningful. One is postscript alike language: {{
0 scope-stack-ref dup {
/kind field-ref /method eq {
current-entry scope-replace
} {
current-entry scope-push
} ifelse
} {
pop
} ifelse
}} Another one is scheme alike language: {(scope-action (let1 parent (ref scope-stack 0)
(if (eq? (ref parent 'field) 'method)
'replace
'pop) (current-entry))} I would like to assume there is no circler dependenc. So the interpreter can manage the memory objects with reference counters. I already use scheme alike language in readtags. So we can reuse it...however, I incline to postscript. It will be nice to allow users to define procedures: --init-mylang={
0 scope-stack-ref dup {
/kind field-ref /method eq {
current-entry scope-replace
} {
current-entry scope-push
} ifelse
} {
pop
} ifelse
}
...
--regex-mylang=/...///{{scope-push-or-replace}} --init-mylang=(define scope-push-or-replace ()
(scope-action (let1 parent (ref scope-stack 0)
(if (eq? (ref parent 'field) 'method)
'replace
'pop) (current-entry)))
...
--regex-mylang=/...///{(scope-push-or-replace)} |
What is the current status of Vue support in ctags? Any ETA? |
No visible advance. However, in the user-invisible part, there are many advances. |
I have implemented a postscript-alike language called optscript.
The next step is implementing operators for building control structure: if, ifelse, repeat, for, and so on. |
Tonight, I linked the optscript interpreter to ctags. "hello, world" worked.
|
Other than error handling, the optscript interpreter works well.
{{
sscount 0 gt {
sstop kind: /method eq {
% pop the top of the scope stack only if the top is a tag for a method kind language object.
sspop
} if
% fill the scope field of the newly created tag with the tag at the top of the scope stack.
sstop $$ :scope
} if
% push the newly created tag to the scope stack.
$$ sspush
}} This looks much better than the original one: {{
0 scope-stack-ref dup {
/kind field-ref /method eq {
current-entry scope-replace
} {
current-entry scope-push
} ifelse
} {
pop
} ifelse
}} How can I implement input.x:
I would like to capture
After committing, we can do as we want. |
I decided to use |
scope-related operators are implemented in optscript branch.
|
Suggested by @Fmajor in universal-ctags#1577. Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Suggested by @Fmajor in universal-ctags#1577. Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Suggested by @Fmajor in universal-ctags#1577. Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Suggested by @Fmajor in universal-ctags#1577. Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Suggested by @Fmajor in universal-ctags#1577. Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Suggested by @Fmajor in universal-ctags#1577. Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Suggested by @Fmajor in universal-ctags#1577. Signed-off-by: Masatake YAMATO <yamato@redhat.com>
for scope, now we have these flags
In my custom syntax file, i need to parse the same pattern in different way with different context (or different stack status), so i come up with some new features with {scope}, like
also, i'd like to use some boolean operation for the scope, like
i'm wondering if someone else have the same requirements.
The text was updated successfully, but these errors were encountered: