Skip to main content

A code generator for iOS

Project description

igen - A code generator for iOS app

Installation:

Install using pip:

Open Terminal and run:

$ pip3 install igen

Update:

$ pip3 install -U igen

or

$ pip3 uninstall igen
$ pip3 install igen --no-cache-dir

Uninstall:

$ pip3 uninstall igen

How to install pip3:

pip3 is already installed if you are using Python 3 (>=3.4)

In order to install Python 3, you need to install Homebrew, run the following command in Terminal:

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Then install Python 3:

$ brew install python

1. Create Template:

1.1. Base Template:

The Base Template contains necessary files for a screen using the Clean Architecture pattern.

Open Terminal, navigate to the folder you want to save the files and run:

$ igen template base <Scene_Name> [--window]

Options:

--window: use UIWindow instead of UINavigationController in the Navigator.

The first time you use the template command, you need to enter your project information:

Enter project name: Your Project
Enter developer name: Your Name
Enter company name: Your Company

Later, if you want to update the information you can run:

$ igen config project

Example:

$ igen template base Login

Output:

Successfully created files:
    Login/LoginViewModel.swift
    Login/LoginNavigator.swift
    Login/LoginUseCase.swift
    Login/LoginViewController.swift
    Login/LoginAssembler.swift
    Login/Test/LoginViewModelTests.swift
    Login/Test/LoginUseCaseMock.swift
    Login/Test/LoginNavigatorMock.swift
    Login/Test/LoginViewControllerTests.swift

1.2. Skeleton Template:

To create a Clean Architecture skeleton project, run:

$ igen template skeleton <Folder_Name>

Example:

Run the following command in Terminal:

$ igen template skeleton DemoApp

Output:

Successfully created files:
    DemoApp/Podfile
    DemoApp/gitignore
    DemoApp/Localizable.strings
    DemoApp/pull_request_template.md
    DemoApp/swiftlint.yml
    DemoApp/DemoApp-Bridging-Header.h
    DemoApp/Sources/UnitTestViewController.swift
    DemoApp/Sources/AppDelegate.swift
    DemoApp/Sources/Assembler.swift
    DemoApp/Sources/Support/Utils.swift
    DemoApp/Sources/Support/Extensions/UIViewController+.swift
    DemoApp/Sources/Support/Extensions/UIViewController+Rx.swift
    DemoApp/Sources/Data/Gateways/GatewaysAssembler.swift
    DemoApp/Sources/Data/API/APIError.swift
    DemoApp/Sources/Data/API/APIService.swift
    DemoApp/Sources/Data/API/APIInput.swift
    DemoApp/Sources/Data/API/APIOutput.swift
    DemoApp/Sources/Config/APIUrls.swift
    DemoApp/Sources/Scenes/App/AppAssembler.swift
    DemoApp/Sources/Scenes/App/AppNavigator.swift
    DemoApp/Sources/Scenes/App/AppUseCase.swift
    DemoApp/Sources/Scenes/App/AppViewModel.swift
    DemoApp/Sources/Scenes/Storyboards/Storyboards.swift

1.3. List Template:

The List Template shows a list of objects in a UITableView or a UICollectionView.

Copy the model to the pasteboard (clipboard) then run:

$ igen template list <Scene_Name> [--section] [--collection] [--window] [--paging]

Options:

--paging: use pagination.

--section: show the list with header sections.

--collection: use UICollectionView instead of UITableView.

--window: use UIWindow instead of UINavigationController in the Navigator.

Example:

Copy the model:

struct Product {
    let id: Int
    let name: String
    let price: Double
}

then run:

$ igen template list ProductList

Output:

Successfully created files:
    ProductList/ProductListViewModel.swift
    ProductList/ProductItemViewModel.swift
    ProductList/ProductListNavigator.swift
    ProductList/ProductListUseCase.swift
    ProductList/ProductListViewController.swift
    ProductList/ProductCell.swift
    ProductList/ProductListAssembler.swift
    ProductList/Test/ProductListViewModelTests.swift
    ProductList/Test/ProductListUseCaseMock.swift
    ProductList/Test/ProductListNavigatorMock.swift
    ProductList/Test/ProductListViewControllerTests.swift
    ProductList/Test/ProductCellTests.swift

1.4. Detail Template:

The Detail Template shows details of an object in a UITableView.

Copy the model then run:

$ igen template detail <Scene_Name> [--static] [--window]

Options:

--static: display details of the object in a static UITableViewController.

--window: use UIWindow instead of UINavigationController in the Navigator.

Example:

Copy the model:

struct Product {
    let id: Int
    let name: String
    let price: Double
}

then run:

$ igen template detail ProductDetail

Output:

Successfully created files:
    ProductDetail/ProductDetailViewModel.swift
    ProductDetail/ProductDetailNavigator.swift
    ProductDetail/ProductDetailUseCase.swift
    ProductDetail/ProductDetailViewController.swift
    ProductDetail/ProductIdCell.swift
    ProductDetail/ProductNameCell.swift
    ProductDetail/ProductPriceCell.swift
    ProductDetail/ProductDetailAssembler.swift
    ProductDetail/Test/ProductDetailViewModelTests.swift
    ProductDetail/Test/ProductDetailUseCaseMock.swift
    ProductDetail/Test/ProductDetailNavigatorMock.swift
    ProductDetail/Test/ProductDetailViewControllerTests.swift
    ProductDetail/Test/ProductDetailCellsTests.swift

1.5. Form Input Template:

To create a form input template for a model, copy the model then run:

$ igen template form <Scene_Name> [--submit SUBMIT] [--dynamic] [--window]

Options:

--submit: set the name of the submit action.

--dynamic: use the dynamic form instead of the static form.

--window: use UIWindow instead of UINavigationController in the Navigator.

Example:

Copy the model:

struct Product {
    var id: Int
    var name: String
    var price: Double
}

then run:

$ igen template form CreateProduct --submit Create

Output:

Successfully created files:
    CreateProduct/CreateProductAssembler.swift
    CreateProduct/CreateProductNavigator.swift
    CreateProduct/CreateProductViewModel.swift
    CreateProduct/CreateProductUseCase.swift
    CreateProduct/CreateProductViewController.swift
    CreateProduct/Test/CreateProductUseCaseMock.swift
    CreateProduct/Test/CreateProductNavigatorMock.swift
    CreateProduct/Test/CreateProductViewModelTests.swift
    CreateProduct/Test/CreateProductViewControllerTests.swift

1.6. Setting Template:

To create a setting template, copy the setting enum then run:

$ igen template setting <Scene_Name> [--section] [--window]

Options:

--section: show the list with header sections.

--window: use UIWindow instead of UINavigationController in the Navigator.

Example:

Copy the enum:

enum SettingMenu {
    case about
    case support
    case facebook
    case email
    case rating
}

then run:

$ igen template setting Setting

Output:

Successfully created files:
    Setting/SettingAssembler.swift
    Setting/SettingNavigator.swift
    Setting/SettingViewModel.swift
    Setting/SettingUseCase.swift
    Setting/SettingViewController.swift
    Setting/SettingMenuCell.swift
    Setting/Test/SettingUseCaseMock.swift
    Setting/Test/SettingNavigatorMock.swift
    Setting/Test/SettingViewModelTests.swift
    Setting/Test/SettingViewControllerTests.swift
    Setting/Test/SettingMenuCellTests.swift

1.7. Login template:

To create a login template, run:

$ igen template login <Scene_Name> [--window]

Options:

--window: use UIWindow instead of UINavigationController in the Navigator.

Example:

Run:

$ igen template login Login

Output:

Successfully created files:
    Login/LoginAssembler.swift
    Login/LoginNavigator.swift
    Login/LoginViewModel.swift
    Login/LoginUseCase.swift
    Login/LoginViewController.swift
    Login/LoginDto.swift
    Login/Test/LoginUseCaseMock.swift
    Login/Test/LoginNavigatorMock.swift
    Login/Test/LoginViewModelTests.swift
    Login/Test/LoginViewControllerTests.swift

2. Create a mock class for a protocol/function:

Copy the protocol/function then run:

$ igen mock [-p]

Options:

-p, --print: print the result.

Example:

Copy the protocol:

protocol ProductsNavigatorType {
    func toProducts()
    func toProductDetail(product: Product)
    func toEditProduct(_ product: Product) -> Driver<EditProductDelegate>
}

then run:

$ igen mock

Output:

The result has been copied to the pasteboard.

Content in the pasteboard:

final class ProductsNavigatorMock: ProductsNavigatorType {

    // MARK: - toProducts

    var toProductsCalled = false

    func toProducts() {
        toProductsCalled = true
    } 

    // MARK: - toProductDetail

    var toProductDetailCalled = false

    func toProductDetail(product: Product) {
        toProductDetailCalled = true
    } 

    // MARK: - toEditProduct

    var toEditProductCalled = false
    var toEditProductReturnValue = Driver<EditProductDelegate>.empty()

    func toEditProduct(_ product: Product) -> Driver<EditProductDelegate> {
        toEditProductCalled = true
        return toEditProductReturnValue
    } 
}

3. Create unit tests for a view model:

Copy the view model then run:

$ igen test [-p]

Options:

-p, --print: print the result.

Example:

Copy the view model:

struct LoginViewModel: ViewModel {
    struct Input {
        let usernameTrigger: Driver<String>
        let passwordTrigger: Driver<String>
        let loginTrigger: Driver<Void>
    }

    struct Output {
        @Property var usernameValidationMessage = ""
        @Property var passwordValidationMessage = ""
        @Property var isLoginEnabled = true
        @Property var isLoading = false
        @Property var error: Error?
    }

then run:

$ igen test

Output:

The result has been copied to the pasteboard.

Content in the pasteboard:

final class LoginViewModelTests: XCTestCase {
    private var viewModel: LoginViewModel!
    private var navigator: LoginNavigatorMock!
    private var useCase: LoginUseCaseMock!
    private var input: LoginViewModel.Input!
    private var output: LoginViewModel.Output!
    private var disposeBag: DisposeBag!

    // Triggers
    private let usernameTriggerTrigger = PublishSubject<String>()
    private let passwordTriggerTrigger = PublishSubject<String>()
    private let loginTriggerTrigger = PublishSubject<Void>()

    override func setUp() {
        super.setUp()
        navigator = LoginNavigatorMock()
        useCase = LoginUseCaseMock()
        viewModel = LoginViewModel(navigator: navigator, useCase: useCase)

        input = LoginViewModel.Input(
            usernameTrigger: usernameTrigger.asDriverOnErrorJustComplete(),
            passwordTrigger: passwordTrigger.asDriverOnErrorJustComplete(),
            loginTrigger: loginTrigger.asDriverOnErrorJustComplete()
        )

        disposeBag = DisposeBag()
        output = viewModel.transform(input, disposeBag: disposeBag)
    }

    func test_usernameTriggerTrigger_() {
        // arrange


        // act


        // assert
        XCTAssert(true)
    }

    func test_passwordTriggerTrigger_() {
        // arrange


        // act


        // assert
        XCTAssert(true)
    }

    func test_loginTriggerTrigger_() {
        // arrange


        // act


        // assert
        XCTAssert(true)
    }

}

4. Create an initialize method for a class/struct:

Copy the class/struct then run the command:

$ igen init [-p]

Options:

-p, --print: print the result.

Example:

Copy the model:

struct Product {
    var id: Int
    var name: String
    var price: Double
}

then run:

$ igen init

Output:

The result has been copied to the pasteboard.

Content in the pasteboard:

extension Product {
    init() {
        self.init(
            id: 0,
            name: "",
            price: 0.0
        )
    }
}

5. Create models from JSON:

Copy the json then run the command:

$ igen json <Model_Name> [-p]

Options:

—-return-classes: return classes instead of structs.

-p, --print: print the result.

Example:

Copy the json:

{
    "id": 989,
    "content": "Hello world!",
    "is_read": false,
    "created_at": "2018-06-29T17:15:36+09:00"
}

then run:

$ igen json Notice

Output:

The result has been copied to the pasteboard.

Content in the pasteboard:

struct Notice {
    var id = 0
    var content = ""
    var isRead = false
    var createdAt = Date()
}

extension Notice: Then { }

extension Notice: Mappable {
    init?(map: Map) {
        self.init()
    }

    mutating func mapping(map: Map) {
        id <- map["id"]
        content <- map["content"]
        isRead <- map["is_read"]
        createdAt <- (map["created_at"], DateTransform())
    }
}

6. File header command:

To update files’ headers, run:

$ igen header [--file-name] [--project] [--developer] [--created-date] [--copyright-year] [--company] <File_Paths>

Options:

--file-name: update file name.

--project: update project.

--developer: update developer.

--created-date: update created date.

--copyright-year: update copyright year.

--company: update company.

If you don’t set any options, the tool will update all header information base on its configuration file.

Example:

Update the company and the developer in AppDelegate’s header.

$ igen header AppDelegate.swift --company --developer

You can use wildcard as well:

Update all Swift files:

$ igen header *.swift

Update all Swift files in the Domain folder and its child folders (recursive) :

$ igen header Domain/**/*.swift

7. Configuration:

7.1. Configure the project information:

To update the project information, run:

$ igen config project [--global]

Options:

--global: global configuration.

7.2. View the configuration:

To view the configuration, run:

$ igen config [--global]

Options:

--global: global configuration.

7.3. Update a configuration:

$ igen config key value [--global] [--unset]

Options:

--global: global configuration. --unset: delete a configuration.

Configure the project id:

$ igen config project.id <Project_ID>

Use the special value @project if you want to use the MD5 encoded project name as the project id.

$ igen config project.id @project

The project id will be used in file headers.

//
//  AppDelegate.swift
//  MGiGen (d18ea2a2902863a858af4f0e0911ed35)
//
//  Created by Tuan Truong on 3/27/19.
//  Copyright © 2019 Sun Asterisk. All rights reserved.
//

Configure the output path:

$ igen config output.path <Path>

Example:

Set the current working directory as the output path (relative path):

$ igen config output.path .

Set the desktop as the output path:

$ igen config output.path /Users/<Your_Name>/Desktop/

You can use a special value @here to set the current working directory as the output path (absolute path):

$ igen config output.path @here

Other special values: @desktop, @downloads, @documents

7.4. View the available configurations:

To view the available configurations, run:

$ igen config keys

Output:

Available configuration keys:
    project.name
    project.developer
    project.company
    project.id
    output.path

7.5. Delete the configuration file:

To delete the configuration file, run:

$ igen config delete [--global]

Options:

--global: global configuration.

8. Install Xcode templates:

Install Clean Architecture templates for Xcode:

$ igen xcode install-templates

Uninstall templates:

$ igen xcode uninstall-templates

9. Other commands:

Run:

$ igen -h

Links:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

igen-3.0.0.tar.gz (67.2 kB view hashes)

Uploaded Source

Built Distribution

igen-3.0.0-py3-none-any.whl (116.2 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page