{"id":13607783,"url":"https://github.com/romainl/ctags-patterns-for-javascript","last_synced_at":"2025-04-05T15:09:42.783Z","repository":{"id":56715833,"uuid":"86923212","full_name":"romainl/ctags-patterns-for-javascript","owner":"romainl","description":"Exuberant Ctags Patterns for JavaScript","archived":false,"fork":false,"pushed_at":"2023-05-14T02:42:17.000Z","size":114,"stargazers_count":416,"open_issues_count":7,"forks_count":52,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-03-29T14:11:38.208Z","etag":null,"topics":["ctags","es6","javascript","vim"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/romainl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-01T15:35:00.000Z","updated_at":"2024-11-30T17:04:34.000Z","dependencies_parsed_at":"2024-08-01T19:53:46.344Z","dependency_job_id":null,"html_url":"https://github.com/romainl/ctags-patterns-for-javascript","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romainl%2Fctags-patterns-for-javascript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romainl%2Fctags-patterns-for-javascript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romainl%2Fctags-patterns-for-javascript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romainl%2Fctags-patterns-for-javascript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/romainl","download_url":"https://codeload.github.com/romainl/ctags-patterns-for-javascript/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247353749,"owners_count":20925329,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ctags","es6","javascript","vim"],"created_at":"2024-08-01T19:01:21.554Z","updated_at":"2025-04-05T15:09:42.765Z","avatar_url":"https://github.com/romainl.png","language":"JavaScript","readme":"# Exuberant Ctags Patterns for JavaScript\n\nThe purpose of this project is to modernize and augment the many custom JavaScript Patterns for Exuberant Ctags that have been floating the web for years.\n\nWe want to make sure Exuberant Ctags doesn't miss a single named symbol in our whole code base and do so without unnecessary duplication:\n\n* [Tags](#tags),\n* [Array literals](#array-literals),\n* [Object literals](#object-literals),\n* [Object properties](#object-properties),\n* [Generator functions](#generator-functions),\n* [Free-form functions](#free-form-functions),\n* [Constructors and classes](#constructors-and-classes),\n* [Methods](#methods),\n* [Variables](#variables),\n* [Named imports](#name-imports),\n* [Named exports](#named-exports),\n* [Styled components](#styled-components)\n\nThis is done by disabling the default \"kinds\", creating new ones, and crafting as many patterns as necessary.\n\n## Reminders\n\n### Compatibility\n\nThese patterns are only usable with Exuberant Ctags. Universal Ctags is *not* currently supported and there's no plan to support it in the foreseeable future.\n\n### A note about disabling the default \"kinds\".\n\nThe option `--javascript-kinds=-c-f-m-p-v` in [ctagsrc](ctagsrc) will disable the default kinds, `c` (classes), `f` (functions), `m` (methods), `p` (properties), and `v` (global variables), for JavaScript files.\n\nThis means your ctags program's builtin regex patterns or any user defined patterns registered against these kinds will no longer function and the patterns defined in [ctagsrc](ctagsrc) will be the only patterns active for the JavaScript language.\n\nThis is done to have a single source of patterns and avoid duplicated tags.\n\n## Try\n\n1. Clone this repository:\n\n        $ git clone https://github.com/romainl/ctags-patterns-for-javascript.git\n\n2. Build a `tags` file against the provided `index.js`:\n\n        $ make tags\n\n   or:\n\n        $ ctags --options=NONE --options=./ctagsrc -f tags index.js\n\n## Use\n\n1. Clone this repository:\n\n        $ git clone https://github.com/romainl/ctags-patterns-for-javascript.git\n\n2. In your shell, run the following command to tell Exuberant Ctags to use the options defined in the provided `ctagsrc` file:\n\n        $ echo \"--options=/absolute/path/to/ctags-patterns-for-javascript/ctagsrc\" \u003e\u003e ~/.ctags\n\n   with `/absolute/path/to/ctags-patterns-for-javascript/ctagsrc` being your actual path, of course.\n\n3. Use this command to generate a `tags` file at the root of your JavaScript project:\n\n        $ ctags -R .\n\nIf for some reason the above instructions sound like Klingon to you, just copy the content of [this file](https://raw.githubusercontent.com/romainl/ctags-patterns-for-javascript/master/ctagsrc) and paste it *into* your own `~/.ctags` file. If that file doesn't exist, create it.\n\n## Tags\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    // FIXME: fix non-working Patterns                  | FIXME               | T\n    // TODO: better ES6+ support                        | TODO                | T\n    // BUG: there's really something fishy about this   | BUG                 | T\n    // ???: what the flying fuck?                       | ???                 | T\n    // !!!: dear god!                                   | !!!                 | T\n    // HACK: deployment is in 15 minutes                | HACK                | T\n    // XXX: I. Must. Finish. That. Mess. Quickly.       | XXX                 | T\n\n## Array literals\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    var|let|const array_name = [...                     | array_name          | A\n\n## Object literals\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    var|let|const object_name = {...                    | object_name         | O\n\n## Object properties\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    foo: 123,                                           | foo                 | P\n    foo: 123                                            | foo                 | P\n    bar: \"eee\",                                         | bar                 | P\n    bar: \"eee\"                                          | bar                 | P\n    baz: /regexp/,                                      | baz                 | P\n    baz: /regexp/                                       | baz                 | P\n    quux: []                                            | quux                | P\n    flax: {}                                            | flax                | P\n    var obj = { sluf: 1 };                              | sluf                | P\n    this.foo = {}                                       | foo                 | P\n\n## Generator functions\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    function* generator_name() {...                     | generator_name      | G\n    function *generator_name() {...                     | generator_name      | G\n    function * generator_name() {...                    | generator_name      | G\n    function*generator_name() {...                      | generator_name      | G\n    const generator_name = function* () {...            | generator_name      | G\n    const generator_name = function * () {...           | generator_name      | G\n    * generator_name() {...                             | generator_name      | G\n\n\n## Free-form functions\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    function func_name() {...                           | func_name           | F\n    (function func_name() {...                          | func_name           | F\n    var|let|const func_name = function() {...           | func_name           | F\n    var|let|const function_name = (arg) =\u003e ...          | func_name           | F\n    var|let|const function_name = arg =\u003e ...            | func_name           | F\n    var|let|const function_name = (\\n...) =\u003e ...        | func_name           | F\n    async function function_name() {...                 | func_name           | F\n    (async function function_name() {...                | func_name           | F\n    var|let|const function_name = async function() {... | func_name           | F\n    var|let|const function_name = async () =\u003e {...      | func_name           | F\n    var|let|const function_name = async arg =\u003e {...     | func_name           | F\n\n## Constructors and classes\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    class ClassName {...                                | ClassName           | C\n\n## Methods\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    this.method_name = function() {...                  | method_name         | M\n    method_name : function() {...                       | method_name         | M\n    method_name: (param) =\u003e ...                         | method_name         | M\n    method_name: param =\u003e ...                           | method_name         | M\n    static method_name() {...                           | method_name         | M\n    method_name() {...                                  | method_name         | M\n    method_name = (param) =\u003e ...                        | method_name         | M\n    method_name = param =\u003e ...                          | method_name         | M\n\n## Variables\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    var|let|const var_name = 1;                         | var_name            | V\n    var|let|const var_name = /regexp/;                  | var_name            | V\n    var|let|const var_name = 'foo';                     | var_name            | V\n    var|let|const var_name = \"bar\";                     | var_name            | V\n    var|let|const var_name = new ClassName();           | var_name            | V\n    var|let|const var_name;                             | var_name            | V\n    var|let|const ..., var_name;                        | var_name            | V\n    var|let|const ..., ..., var_name;                   | var_name            | V\n    var|let|const [ var1, var2, var3 ] = useState([]);  | var1, var2, var3    | V\n    var|let|const { var1, var2, var3 } = props;         | var1, var2, var3    | V\n        var_name,                                       | var_name            | V\n        var_name                                        | var_name            | V\n\n## Named imports\n\nTagging direct imports would be redundant so we only tag named imports.\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    import { * as imp1 }                                | imp1                | I\n    import { foo as imp2 }                              | imp2                | I\n    import { imp3, * as imp4 }                          | imp4                | I\n    import { imp5, bar as imp6 }                        | imp6                | I\n    import { imp7, imp8, * as imp9 }                    | imp9                | I\n    import { imp10, imp11, baz as imp12 }               | imp12               | I\n    import { * as imp13, * as imp14, * as imp15 }       | imp13, imp14, imp15 | I\n    import { foo as imp16, bar as imp17, baz as imp18 } | imp16, imp17, imp18 | I\n    import * as imp19                                   | imp19               | I\n    import foo as imp20                                 | imp20               | I\n    import imp21, * as imp22                            | imp22               | I\n    import imp23, bar as imp24                          | imp24               | I\n    import imp25, imp26, * as imp27                     | imp27               | I\n    import imp28, imp29, baz as imp30                   | imp30               | I\n    import * as imp31, * as imp32, * as imp33           | imp31, imp32, imp33 | I\n    import foo as imp34, bar as imp35, baz as imp36     | imp34, imp35, imp36 | I\n    foo as imp37                                        | imp37               | I\n\n## Flow imports\n\nSame story as imports, tagging direct imports would be redundant so we only tag named imports.\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    import type {foo as impFlow01} from ...             | impFlow01           | I\n    import type * as impFlow02 from ...                 | impFlow02           | I\n    import typeof {foo as impFlow03} from ...           | impFlow03           | I\n    import typeof * as impFlow04 from ...               | impFlow04           | I\n\n## Named exports\n\nSame story as imports, tagging direct exports would be redundant so we only tag named exports.\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    export { var1 as exp04, var2 as exp05 };            | exp04, exp05        | E\n    export let exp06, exp07;                            | exp06, exp07        | E\n    export var exp08, exp09, exp09b;                    | exp08, exp09        | E\n    export let exp10 = 1, exp11 = 2;                    | exp10, exp11        | E\n    export const exp12 = 1, exp13 = 2;                  | exp12, exp13        | E\n    export var exp14 = 1, exp15 = 2;                    | exp14, exp15        | E\n    export function exp16() {}                          | exp16               | E\n    export default { var1 as exp20, var2 as exp21};     | exp20; exp21        | E\n    export default let exp22, exp23;                    | exp22, exp23        | E\n    export default var exp24, exp25;                    | exp24, exp25        | E\n    export default let exp26 = 1, exp27 = 2;            | exp26, exp27        | E\n    export default const exp28 = 1, exp29 = 2;          | exp28, exp29        | E\n    export default var exp30 = 1, exp31 = 2;            | exp30, exp31        | E\n    export default function exp32() {}                  | exp32               | E\n\n## Styled components\n\n\"Visual primitives for the component age.\", as they say [on the site](https://www.styled-components.com/), are not exactly native types but they are certainly named and very likely to be reused so they deserve a spot, here.\n\n    CODE                                                | TAG                 | KIND\n    ----------------------------------------------------|---------------------|-----\n    var|let|const Component = styled...                 | Component           | S\n    var|let|const Component = createGlobalStyle...      | Component           | S\n\n## Hack\n\n### Regular expressions dialect\n\nBecause Exuberant Ctags takes no responsibility about the regular expression engine it uses under the hood, we must use the dumbest dialect, BRE, for portability. This has a number of consequences:\n\n* no alternation,\n* no lookbehind,\n* no backreference,\n* a verbose and frustrating syntax.\n\nBut we are hackers, so we see challenges where others see obstacles, right?\n\n### Watch and re-index\n\nThe bundled `Makefile` has a very simple and very cheap `watch` phony target that will run `make tags` every second. In turn, the `tags` target will run `ctags --options=./ctagsrc -f tags index.js` *only* if `ctagsrc` or `index.js` have changed since last run.\n\nThis allows us to start the watcher in a terminal:\n\n    $ make watch\n\nopen `ctagsrc`, `index.js`, and the `tags` file in Vim in another terminal:\n\n    $ vim -O tags ctagsrc index.js +'set autoread' +'autocmd! CursorHold,CursorHoldI * checktime'\n\nand watch our `tags` file change as we edit existing patterns in `ctagsrc` or add expressions in `index.js`.\n\n\n[//]: # ( Vim: set spell spelllang=en: )\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromainl%2Fctags-patterns-for-javascript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fromainl%2Fctags-patterns-for-javascript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromainl%2Fctags-patterns-for-javascript/lists"}