React native projections and templates using vim-projectionist

Veezus Kreist
Adorable
Published in
3 min readSep 29, 2017

Recently I had the opportunity to solve some long-standing file navigation and templating complaints with my react-native vim setup.

The Problem

While developing ruby on rails applications, which I’ve been doing for ten years, I’ve relied on the powerful and popular rails.vim written by tpope. I like that rails.vim makes me decide what I want before going and getting it (so I don’t sit and stare at a list of files) and another part is the built-in templates for new files that rails.vim provides. For example, :Emodel user! will generate a blank ActiveRecord model class that inherits from ActiveRecord::Base.

I’ve been developing react-native apps for some time now, and I’ve been relying on vim’s built-in :e command combined with tab-completing directories and files. This has been tedious, to say the least. I wished I had the familiar navigation and new-file templates from rails.vim. I recalled, though, that rails.vim had been rewritten some time ago and vim-projectionist had come out of the refactoring.

The Solution

I installed vim-projectionist, created a .projections.json in the project root, and set up some simple file navigations with ease. When I got to writing templates, however, I had some issues with curly braces. The line import React, { Component } from 'react-native';, as an example, would fail to be imported into the template. This is because vim-projectionist uses curly braces to denote placeholders and Component is not a valid placeholder. To output curly braces in your template, you’ll need to use the {open} and {close} placeholders.

vim-projectionist supports easy navigation to and from test files and to “alternate” and “related” files. I haven’t yet decided how I’d like to use those, so I’m leaving those sections empty until I’ve decided on a sensical set of defaults.

Here’s what I’ve got so far for my react-native `.projections.json` file:

{
"app/actions/*.js": {
"type": "action"
},
"app/containers/*.js": {
"type": "container",
"template": [
"import React, {open} Component {close} from 'react';\n",
"export default class {capitalize} extends Component {",
" render () {",
" return (",
" );",
" };",
"}",
"",
"export default connect(",
" state => ({open}state: state{close}),",
" dispatch => ({open}actions: bindActionCreators(actions, dispatch){close})",
")({capitalize});"
]
},
"app/components/*.js": {
"type": "component",
"template": [
"import React, {open} Component {close} from 'react';\n",
"export default class \{} extends Component {",
" render () {",
" return (",
" );",
" };",
"}"
]
},
"app/reducers/*.js": {
"type": "reducer"
},
"package.json": {
"type": "package"
},
"app/services/*Service.js": {
"type": "service"
},
"app/styles/*.js": {
"type": "style",
"template": [
"import {open} Platform, StyleSheet {close} from 'react-native';",
"import COLORS from '../config/Colors';",
"import FONTS from '../config/Fonts';\n",
"export default StyleSheet.create({",
"});"
]
},
"app/Store.js": {
"type": "store"
},
"app/Root.js": {
"type": "root"
}
}

Reference

vim-projectionist supports the following placeholders. With the exception of {open} and {close}, which output curly braces, the ones you’ll be most interested in are case transformations. You can always see all the available transformations inside your vim session with
:let g:projectionist_transformations.

{dot}
{underscore}
{backslash}
{colons}
{hyphenate}
{blank}
{uppercase}
{camelcase}
{capitalize} — aliased as \{}
{snakecase}
{dirname}
{basename}
{singular}
{plural}
{open}
{close}

Big thanks to tpope for making my life so much easier!

--

--