All Projects → samhinton88 → code-fold

samhinton88 / code-fold

Licence: MIT license
Write the pattern, then let your code write itself.

Programming Languages

javascript
184084 projects - #8 most used programming language
typescript
32286 projects

Projects that are alternatives of or similar to code-fold

islpy
Python wrapper for isl, an integer set library
Stars: ✭ 58 (+346.15%)
Mutual labels:  code-generation
FSharpWrap
Utility that automatically generates F# modules and functions based on your F# project file's references
Stars: ✭ 14 (+7.69%)
Mutual labels:  code-generation
cscg
Code Generation as a Dual Task of Code Summarization.
Stars: ✭ 28 (+115.38%)
Mutual labels:  code-generation
exlcode-chrome
EXLcode - VS Code-based Online IDE Chrome Extension
Stars: ✭ 18 (+38.46%)
Mutual labels:  devtools
AUXify
Introduces macro/meta annotations @ aux, @ self, @ instance, @ apply, @ delegated, @ syntax and String-based type class LabelledGeneric
Stars: ✭ 25 (+92.31%)
Mutual labels:  code-generation
typed-astunparse
Python 3 AST unparser with type comments support.
Stars: ✭ 27 (+107.69%)
Mutual labels:  code-generation
prosemirror-dev-toolkit
Injectable developer tools for ProseMirror rich-text editors implemented in Svelte and TypeScript.
Stars: ✭ 44 (+238.46%)
Mutual labels:  devtools
granate
Code generator for graphql
Stars: ✭ 21 (+61.54%)
Mutual labels:  code-generation
toast
Plugin-driven CLI utility for code generation using Go source as IDL
Stars: ✭ 52 (+300%)
Mutual labels:  code-generation
nxrocks
Set of Nx plugins to enhance your Nx workspace (even more!)
Stars: ✭ 165 (+1169.23%)
Mutual labels:  devtools
tiles
Programmatic code generation
Stars: ✭ 78 (+500%)
Mutual labels:  code-generation
Beef
Business Entity Execution Framework
Stars: ✭ 95 (+630.77%)
Mutual labels:  code-generation
devtools-highlighter
DevTools extension that finds and highlights elements in the page
Stars: ✭ 29 (+123.08%)
Mutual labels:  devtools
chrome-trace
Process Chrome trace logs in Node.
Stars: ✭ 15 (+15.38%)
Mutual labels:  devtools
grav-plugin-devtools
Grav Devtools Plugin
Stars: ✭ 36 (+176.92%)
Mutual labels:  devtools
kobby
Kobby is a codegen plugin of Kotlin DSL Client by GraphQL schema. The generated DSL supports execution of complex GraphQL queries, mutation and subscriptions in Kotlin with syntax similar to native GraphQL syntax.
Stars: ✭ 52 (+300%)
Mutual labels:  code-generation
fling
A fluent API generator
Stars: ✭ 20 (+53.85%)
Mutual labels:  code-generation
Textrude
Code generation from YAML/JSON/CSV models via SCRIBAN templates
Stars: ✭ 79 (+507.69%)
Mutual labels:  code-generation
sample-generator
Xcode Source Editor Extension to generate Swift model samples
Stars: ✭ 19 (+46.15%)
Mutual labels:  code-generation
designto-code
Design to code engine. A design ✌️ code standard. Supports React, Flutter and more.
Stars: ✭ 87 (+569.23%)
Mutual labels:  code-generation

Code Fold

Turn your codebase into an event-driven system.

yarn global add code-fold

Have you ever thought:

I just wish that every time I wrote a function in this file, it would just magically write all the boilerplate for a test and an export, and then import it where I want it to be.

code-fold could be just the thing you need to explore.

Writing code is often about deciding on a pattern and the time spent implementing it is a function of that pattern, code-fold allows you to focus on the pattern, wire your codebase up in the shape of that pattern and let the code write itself.

code-fold transforms a codebase into a reactive, event driven system - it sees a change made to code as an event, a message that is emitted to all other parts of the codebase.

A developer can then decide which other parts of the code should change as a result, and code-fold will make those changes automatically.

Usage

Initialisation

Once installed, navigate in your terminal to the top of your codebase and then run:

unfold

Syntax

code-fold commands currently live with your code and use a JSX-like syntax, placed inside inline comments.

Listeners

Listener folds listen for changes to particular types of syntax in locations you point them at:

// ./some-file.js
// <myFirstFold downstream exported_function />

This fold will listen for any new exported functions in its local directory and any lower directories, and emit an event when this occurs.

code-fold runs queries on the ASTs for the files in your codebase, and so can distinguish between, e.g. a new function being written and a function being exported.

The util recognises all AST types that are recognised by acorn and babel, lowercased. I heartily recommend AST Explorer for playing around and getting to know the different types.

Types in singular form will return the first match in the ast, but they also support simple pluralisation - add an 's' to the end of a given type to return all results which match the query.

There are also a number of aliased types, e.g. exported_function, which are layered on top of the exisiting types. These aliases are an ongoing peice of work.

Current aliases (add an 's' to the end for the plural verion):

exported_function
arrow_function_assignment
exported_async_function

The downstream prop instructs the fold to watch all files in the local directory and any lower directories.

Using a non-self-closing fold instructs it to listen to only what is between its opening and closing tags.

// <myFirstFold exported_function >
// Just watch the JavaScript in here!
export const foo = () => {} // <-- this will trigger
// </myFirstFold>
export const bar = () => {} // <-- this will not trigger

Consumers

Consumer folds listen for those emitted events and make modifications to the codebase based on those events:

// ./some-other-dir/some-other-file.js
// <*myFirstFold overwrite snippet="{{ name }}">

// </*myFirstFold>

This fold will fire when myFirstFold emits an event, it will then write the names of the downstream exported functions between its opening and closing tags.

The snippet prop allows a developer to write an inline template for whatever new code they want to be added. These templates use HandlebarsJS and are called with data coming through on the event.

So in the above example, were I to create a new function like this:

const myFilter = (data, predicate) => data.filter(predicate) 

The consumer would write:

myFilter

Consumers also accept a where prop, which allows us to get greater control over when a consumer should do its work.

where accepts JavaScript as a string, and will execute it in the context of the data coming through on the event.

// <*myFirstFold overwrite snippet="{{ name }}" where="name.startsWith('user')">

// </*myFirstFold>

This consumer fold is listening to the same event, but will only write the names of functions that start with the token user.

Consumer folds take a number of commands when deciding how to make modifications:

  • overwrite
    • used non-self-closing folds and will overwrite anything between its opening and closing tags.
  • overwrite_below
    • used in self-closing folds and will overwrite everything below

Tiny Example

Wire up your code:

// ./my-math.js
// <newFunction arrow_function>
// </newFunction>

export {
// <*newFunction overwrite snippet={"{{name}},"}>
// </*newFunction
}

Make a change:

// ./my-math.js
// <newFunction arrow_function>
const add = () => {}
const subtract = () => {}
const divide = () => {}
const multiply = () => {}
// </newFunction>

export {
// <*newFunction overwrite snippet={"{{name}},"}>
// </*newFunction
}

Save and let code-fold write the rest of your code:

// ./my-math.js
// <newFunction arrow_function>
const add = () => {}
const subtract = () => {}
const divide = () => {}
const multiply = () => {}
// </newFunction>

export {
// <*newFunction overwrite_below snippet={"  {{name}},"}>
    add,
    subtract,
    divide,
    multiply,
// </*newFunction
}

Case Study: index file

Often we'll want to organise functions into directories and then for ease of use export them all from an index file at a higher level.

Copy this into your index file:

// utils/index.js

// <newFunctionExportedBelowThis downstream exported_function />
// <*newFunctionExportedBelowThis overwrite_below snippet="export { {{ name }} } from './{{ relativePath }}'"/>

And code-fold will magically find any exported functions below or at the same level as that index, and export them.

Case Study: Redux

Redux is a popular, powerful state management system for front-end applications; as developers we enumerate a number of actions which describe the behaviour of the application, and we write types, reducers and action creators as the boilerplate to allow our views to access it.

code-fold allows us to declare up front "for each of my types I need this code", write the types, and let the code write itself.

// ./types.js
// <newType named_exports>
// </newType>

// ./actions/user.js
import {
// <*newType overwrite snippet='  {{name}},' where="data.name.startsWith('user')">
// </*newType> 
} from './types'

// <*newType where="data.name.startsWith('user')" snippet="export const {{ name }}Action = (data) => ({ type: {{ name }}, data })">
// </*newType>

// ./actions/auth.js
import {
// <*newType overwrite snippet='  {{name}},' where="data.name.startsWith('auth')">
// </*newType> 
} from './types'
// <*newType where="data.name.startsWith('auth')" snippet="export const {{ name }}Action = (data) => ({ type: {{ name }}, data })>
// </*newType>

Make a change.

// ./types.js
// <newType named_exports >
export const userCreate = 'userCreate';
export const authLogin = 'authLogin';
// </newType>

Hit save and code-fold writes the rest of the code for you in the way you've described it.

// ./actions/user.js
import {
// <*newType overwrite snippet='  {{name}},' where="data.name.startsWith('user')">
    userCreate
// </*newType> 
} from './types'
// <*newType where="data.name.startsWith('user')" snippet="export const {{ name }}Action = (data) => ({ type: {{ name }}, data })">
export const userCreateAction = (data) => ({ type: userCreate, data });
// </*newType>

// ./actions/auth.js
import {
// <*newType overwrite snippet='  {{name}},' where="data.name.startsWith('user')">
    authLogin
// </*newType> 
} from './types'
// <*newType where="data.name.startsWith('auth')" snippet="export const {{ name }}Action = (data) => ({ type: {{ name }}, data })>
export const authLoginAction = (data) => ({ type: authLogin, data });
// </*newType>
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].