Path: blob/main/src/command/create-project/cmd.ts
6458 views
/*1* cmd.ts2*3* Copyright (C) 2020-2022 Posit Software, PBC4*/56import { basename } from "../../deno_ral/path.ts";78import { Command } from "cliffy/command/mod.ts";910import { executionEngine, executionEngines } from "../../execute/engine.ts";11import { initializeProjectContextAndEngines } from "../command-utils.ts";1213import { projectCreate } from "../../project/project-create.ts";14import {15parseProjectType,16projectType,17projectTypeAliases,18projectTypes,19} from "../../project/types/project-types.ts";20import { kMarkdownEngine } from "../../execute/types.ts";2122// ensures project types are registered23import "../../project/types/register.ts";2425const kProjectTypes = projectTypes();26const kProjectTypeAliases = projectTypeAliases();27const kProjectTypesAndAliases = [...kProjectTypes, ...kProjectTypeAliases];2829const kEditorTypes = ["source", "visual"];3031export const createProjectCommand = new Command()32.name("create-project")33.description("Create a project for rendering multiple documents")34.arguments("[dir:string]")35.hidden()36.option(37"--title <title:string>",38"Project title",39)40.option(41"--type <type:string>",42`Project type (${kProjectTypes.join(", ")})`,43)44.option(45"--template <type:string>",46`Use a specific project template`,47)48.option(49"--engine <engine:string>",50"Use execution engine (jupyter, knitr, markdown, ...)",51{52value: (value: string): string[] => {53value = value || kMarkdownEngine;54// Parse engine:kernel syntax55const match = value.match(/(\w+)(:(.+))?$/);56if (match) {57return [match[1], match[3]];58} else {59return [value];60}61},62},63)64.option(65"--editor <editor:string>",66"Default editor for project ('source' or 'visual')",67)68.option(69"--with-venv [packages:string]",70"Create a virtualenv for this project",71)72.option(73"--with-condaenv [packages:string]",74"Create a condaenv for this project",75)76.option(77"--no-scaffold",78"Don't create initial project file(s)",79)80.example(81"Create a project in the current directory",82"quarto create-project",83)84.example(85"Create a project in the 'myproject' directory",86"quarto create-project myproject",87)88.example(89"Create a website project",90"quarto create-project mysite --type website",91)92.example(93"Create a blog project",94"quarto create-project mysite --type website --template blog",95)96.example(97"Create a book project",98"quarto create-project mybook --type book",99)100.example(101"Create a website project with jupyter",102"quarto create-project mysite --type website --engine jupyter",103)104.example(105"Create a website project with jupyter + kernel",106"quarto create-project mysite --type website --engine jupyter:python3",107)108.example(109"Create a book project with knitr",110"quarto create-project mybook --type book --engine knitr",111)112.example(113"Create jupyter project with virtualenv",114"quarto create-project myproject --engine jupyter --with-venv",115)116.example(117"Create jupyter project with virtualenv + packages",118"quarto create-project myproject --engine jupyter --with-venv pandas,matplotlib",119)120.example(121"Create jupyter project with condaenv ",122"quarto create-project myproject --engine jupyter --with-condaenv",123)124.example(125"Create jupyter project with condaenv + packages",126"quarto create-project myproject --engine jupyter --with-condaenv pandas,matplotlib",127)128// deno-lint-ignore no-explicit-any129.action(async (options: any, dir?: string) => {130// Initialize project context and register engines (including external ones)131await initializeProjectContextAndEngines();132133if (dir === undefined || dir === ".") {134dir = Deno.cwd();135}136137const engine = options.engine || [];138139// Validate the engine (after engines are initialized)140if (engine[0]) {141const engineInstance = executionEngine(engine[0]);142if (!engineInstance) {143throw new Error(144`Unknown execution engine: ${engine[0]}. ` +145`Available engines: ${146executionEngines().map((e) => e.name).join(", ")147}`,148);149}150}151152const envPackages = typeof (options.withVenv) === "string"153? options.withVenv.split(",").map((pkg: string) => pkg.trim())154: typeof (options.withCondaenv) === "string"155? options.withCondaenv.split(",").map((pkg: string) => pkg.trim())156: undefined;157158// Parse the project type and template159const { type, template } = parseProjectType(options.type);160const projectTemplate = options.template || template;161162// Validate the type163if (kProjectTypesAndAliases.indexOf(type) === -1) {164throw new Error(165`Project type must be one of ${166kProjectTypes.join(", ")167}, but got "${type}".`,168);169}170171// Validate the editor172const editorType = options.editor;173if (editorType && !kEditorTypes.includes(editorType)) {174throw new Error(175`Editor type must be one of ${176kEditorTypes.join(", ")177}, but got "${editorType}".`,178);179}180181// Validate the template182const projType = projectType(type);183if (projectTemplate && !projType.templates?.includes(projectTemplate)) {184if (projType.templates) {185throw new Error(186`Project template must be one of ${187projType.templates.join(", ")188}, but got "${projectTemplate}".`,189);190} else {191throw new Error(192`The project type ${type} does not support any templates.`,193);194}195}196197await projectCreate({198dir,199type: type,200title: options.title || basename(dir),201scaffold: !!options.scaffold,202engine: engine[0] || kMarkdownEngine,203kernel: engine[1],204editor: editorType,205venv: !!options.withVenv,206condaenv: !!options.withCondaenv,207envPackages,208template: projectTemplate,209});210});211212213