Skip to content

Latest commit

 

History

History
275 lines (175 loc) · 21.1 KB

cookiecutter.md

File metadata and controls

275 lines (175 loc) · 21.1 KB

Cookiecutter

  • Cookiecutter 的存在,提供了一個可供參考的標準;隨著時間過去,不同類型專案的 cookiecutter 會被不斷地改善 (透過 code review),之後要新起一個專案時,就不會搞不清楚要參考哪一個專案。

參考資料:

新手上路 {: #getting-started }

  • 先試用過 cookiecutter gh:audreyr/cookiecutter-pypackage,發現有 choice 可以產生不同的檔案、有 y/n 的選項可以決定要不要產生哪些檔案或設定,彈性很大!

參考資料:

  • audreyr/cookiecutter: A command-line utility that creates projects from cookiecutters (project templates). E.g. Python package projects, jQuery plugin projects.

    • 要從 https://github.com/audreyr/cookiecutter-pypackage 快速建立一個 Python package,執行 cookiecutter gh:audreyr/cookiecutter-pypackage (其中 gh 是 GitHub 的意思),會被要求輸入一些值 (template variables),之後 Cookiecutter 就可以根據那些值在 CWD 建立專案。
    • 也可以用 local template,用 cookiecutter path/to/cookiecutter-pypackage/ 即可,其中 cookiecutter-pypackage 下就是 project template 的結構。
    • Template variables 以 key-value pairs 的型式定義在 cookiecutter.json 裡,除非搭配 --no-input 使用,否則會被依序提示要提供 cookiecutter.json 裡不同 key 的值 (value 做為預設值)。
    • 使用過的 remote cookiecutter (不含 local cookiecutter),都會儲存一份在 cookiecutters dir 裡 (預設是 ~/.cookiecutters/),之後就可以直接用 directory name,例如 cookiecutter cookiecutter-pypackage 會去找 ~/.cookiecutters/cookiecutter-pypackage/
    • Cookiecutter 自己的設定可以寫在 ~/.cookiecutterrc (YAML),裡面可以設定 default context (自訂 key/value pair,覆寫 template 裡的預設值)、cookiecutters dir。
    • 除了 ~/.cookiecutterrc 裡用 default_context: 自訂 key-value pair 之外,也可以從 command line 覆寫 (相對於 default context,稱做 extra context),例如 cookiecutter --no-input gh:msabramo/cookiecutter-supervisor program_name=foobar startsecs=10
    • 支援 pre-/post-generate hooks -- 在產生專案前後呼叫外部 Python/shell script;用 Python script 才能跨平台,能跑 Cookiecutter 一定有 Python。
    • "Use it from Python" 可以包裝進自己的工具;這裡 以 web framework 為例,若需要提供快速產生 project 的工具 (例如 Django 的 django-admin.py startprojectnpm init)。
  • Overview — cookiecutter 1.6.0 documentation 簡單介紹 Cookiecutter 運作的原理 -- Input & Output

    cookiecutter-something/
    ├── {{ cookiecutter.project_name }}/  <--------- Project template
    │   └── ...
    ├── blah.txt                      <--------- Non-templated files/dirs
    │                                            go outside
    │
    └── cookiecutter.json             <--------- Prompts & default values
    
    • Template 在 {{cookiecutter.xxx}} 底下 (其中 xxx 通常是 project_name),外面的檔案除了 cookiecutter.json 宣告 template variables (與預設值) 外,都與 template 無關。
    • 產生 project 時並不是在 CWD 直接放 project template 內的檔案,而是會產生一個 subdir,而 subdir 的名字就是 {{cookiecutter.xxx}} 的運算結果。
  • Getting to Know Cookiecutter — cookiecutter 1.6.0 documentation 詳細介紹 Cookiecutter 的運作原理

    • 一樣以 cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git 為例,會先 clone 進 ~/.cookiecutters/,再 "fill in the blanks for your project",重點會在 Step 3: Observe How It Was Generated,對照 template 與最後的產出。

    • This happens in find.py, where the find_template() method looks for the first jinja-like directory name that starts with cookiecutter. 這裡講的是 Cookiecutter 的內部實作 -- Determine which child directory of repo_dir is the project template.

      根據 source code if 'cookiecutter' in item and '{{' in item and '}}' in item: 會找有 cookiecutter{{}} 的目錄,不一定要以 {{cookiecutter. 開頭。

  • Additional Tutorials — cookiecutter 1.6.0 documentation #ril

Local/Remote Template/Cookiecutter {: #template }

  • 雖然 cookiecutter 是專案名稱,但也習慣將 project template 稱做 cookiecutter,也之所以 local/remote template 的另一種說法是 local/remote cookiecutter。

參考資料:

Template Variables, Context {: #variable }

自製 Cookiecutter {: #create-your-own-cookiecutter }

  • Local cookiecutter 在開發自己的 cookiecutter 時很方便。
  • 將一個現成可運作的專案 "參數化",是比較有效的做法。
  • 需要 Jinja 的快速入門,過程中會用到 Jinja 的進階語法。

參考資料:

  • Template Extensions — cookiecutter 1.6.0 documentation #ril

  • Learn the Basics of Cookiecutter by Creating a Cookiecutter — cookiecutter 1.6.0 documentation

    • 瞭解 Cookiecutter 最簡單的方法是建立一個簡單的 (local) template,看它如何運作 -- 簡單來說:複製 source directory tree,並將 templating tags ({{...}}) 取代成 cookiecutter.json 裡定義的值。

    • 這裡用一個名叫 HelloCookieCutter1 的 (local) template 說明 -- 會產生一個 .py 檔,執行時會印 Hello, xxx!,會詢問 .py 的檔名,以及 xxx 的值。

      HelloCookieCutter/
      |- {{cookiecutter.directory_name}}/
      |  |- {{cookiecutter.file_name}}.py # 內容 print("Hello, {{cookiecutter.greeting_recipient}}!")
      |- cookiecutter.json
      

      cookiecutter.json:

      {
          "directory_name": "Hello",
          "file_name": "Howdy",
          "greeting_recipient": "Julie"
      }
      
    • Template tagging 裡的東西可以有 namespace,例如 cookiecutter.directory_name 是指 cookiecutter 這個 namespace 上的 directory_name,而 cookiecutter namespace 下的 variable,主要是來自 cookiecutter.json

  • I’m having trouble generating Jinja templates from Jinja templates - Troubleshooting — cookiecutter 1.6.0 documentation #ril

  • Templates in Context Values — cookiecutter 1.6.0 documentation 出現 "project_slug": "{{ cookiecutter.project_name|lower|replace(' ', '-') }}""pkg_name": "{{ cookiecutter.project_slug|replace('-', '') }}" 的用法。

  • Create a Cookiecutter From Scratch — cookiecutter 1.6.0 documentation 這份 tutorial 沒寫完,採用 {{cookiecutter.project_slug}} 做為目錄名稱。

  • A Pantry Full of Cookiecutters - audreyr/cookiecutter 社群提供的 remote cookiecutters,通常命名 cookiecutter-*

  • Replay Project Generation — cookiecutter 1.6.0 documentation

    • On invocation Cookiecutter dumps a json file to ~/.cookiecutter_replay/ which enables you to replay later on.

      In other words, it persists your input for a template and fetches it when you run the SAME TEMPLATE again.

      所以 ~/.cookiecutter_replay/ 底下會分不同的 cookiecutter,例如 cookiecutter gh:audreyr/cookiecutter-pypackage 會自動產生 ~/.cookiecutter_replay/cookiecutter-pypackage.json,不用加其他參數。

    • Example for a replay file (which was created via cookiecutter gh:hackebrot/cookiedozer):

      {
          "cookiecutter": {
              "app_class_name": "FooBarApp",
              "app_title": "Foo Bar",
              "email": "[email protected]",
              "full_name": "Raphael Pierzina",
              "github_username": "hackebrot",
              "kivy_version": "1.8.0",
              "project_slug": "foobar",
              "short_description": "A sleek slideshow app that supports swipe gestures.",
              "version": "0.1.0",
              "year": "2015"
          }
      }
      
    • To fetch this CONTEXT DATA without being prompted on the command line you can use either of the following methods.

      Pass the according option on the CLI:

      cookiecutter --replay gh:hackebrot/cookiedozer
      

      Or use the Python API:

      from cookiecutter.main import cookiecutter
      cookiecutter('gh:hackebrot/cookiedozer', replay=True)
      
    • This feature is comes in handy if, for instance, you want to create a new project FROM AN UPDATED TEMPLATE.

      由於同一個 template 可能被用來生成多個專案,導致存在 ~/.cookiecutter_replay 底下的資料會被覆寫,加上 --replay 無法指定檔案,使得 replay 只適合用在開發 template 時。

  • Create your own Cookiecutter template (2015-01-07) #ril

    • Are you doing the same steps over and over again every time you start a new programming project? It prompts users for input and uses the given information to RENDER templates.
    • 這裡以 Android 上的 Kivy app 為例,教大家先做一個 cookiedozer (Cookiecutter for i18n Kivy Apps)。
    • 雖然 Kivy 本身跨平台,但建立 APK 的工具 Buildozr 並不是 (目前 2018-08-11 支援 Linux 與 macOS),若目的是 debugging 則可以用 Kivy Launcher (Google Play Store)
    • 接下來的內容,對 Kivy 要有一些瞭解比較好 ...
  • Extending our Cookiecutter template (2015-01-18) #ril

  • Wrapping up our Cookiecutter template (2015-02-02) #ril

Copy without Render

Pre-/Post-generate Hooks {: #hook }

Conditional Files / Directories ??

Conditional Follow-up Questions ??

  • 感覺可以在 variable 名稱後面加上 _if_xxx 來識別,例如 pytest_version_if_use_pytest;使用者看到 if_xxx 不成立時,就可以按 Enter 跳過 (採用預設值)。

參考資料:

User Configuration ??

同一個 Repo 提供多個 Cookiecutter {: #multiple-cookiecutters-in-a-repo }

Python Integration

安裝設置 {: #setup }

$ python3 -m venv ~/dev/cookiecutter
$ ~/dev/cookiecutter/bin/pip install cookiecutter
$ ln -s ~/dev/cookiecutter/bin/cookiecutter ~/bin
$ cookiecutter --version
...

參考資料:

參考資料 {: #reference }

文件:

社群:

相關:

手冊: