1+ """
2+ This module provides a CLI tool to assist with the Anoma specification writing process.
3+ """
14import re
25from pathlib import Path
36
47import click
5- import questionary
68from colorama import Fore # type: ignore
79
810ROOT_PATH = Path ("./" ).resolve ()
911DOCS_PATH = ROOT_PATH / "docs"
10- TEMPLATE_MIN_PATH = DOCS_PATH / "tutorial" / "engines"
11- ARCH_NODE_PATH = DOCS_PATH / "arch" / "node"
12- ENGINE_PATH = ARCH_NODE_PATH / "engines"
13-
14-
15- def transform_file (
16- input_path : Path , output_path : Path , replacements : list [tuple [str , str ]]
17- ):
18- output_path .parent .mkdir (parents = True , exist_ok = True )
19- try :
20- content = input_path .read_text ()
21- for pattern , replacement in replacements :
22- content = re .sub (pattern , replacement , content )
23- output_path .write_text (content )
24- click .echo (
25- f"Created { Fore .GREEN } { output_path .relative_to (ENGINE_PATH )} { Fore .RESET } from { Fore .GREEN } { input_path .relative_to (TEMPLATE_MIN_PATH )} { Fore .RESET } "
26- )
27- except FileNotFoundError :
28- click .echo (f"Error: Could not find file { input_path } " , err = True )
29- except Exception as e :
30- click .echo (f"Error processing { input_path } : { str (e )} " , err = True )
3112
3213
3314# -- CLI --
@@ -36,117 +17,9 @@ def cli():
3617 """Command line tool to assist with the Anoma specification writing process"""
3718 pass
3819
39-
40- @cli .group ()
41- def new ():
42- """Create new stuff"""
43- pass
44-
45-
46- @new .command ()
47- @click .argument ("name" , type = click .STRING , required = False )
48- def engine (name ):
49- """Create a new engine from template"""
50- while not name :
51- name = questionary .text (
52- "What is the name of the new engine? (CamelCase is recommended, e.g: `Indexer`)"
53- ).ask ()
54-
55- # use snake case
56- snake_name = (
57- name .lower ().replace (" " , "_" ).replace ("-" , "_" ).replace ("." , "_" ).strip ()
58- )
59- click .echo (f"Creating engine { Fore .GREEN } { name } { Fore .RESET } " )
60-
61- template_minimum_prefix = "template_minimum"
62- base_files = ["" , "_messages" , "_config" , "_environment" , "_behaviour" ]
63-
64- for base_name in base_files :
65- input_path = (
66- TEMPLATE_MIN_PATH / f"{ template_minimum_prefix } { base_name } .juvix.md"
67- )
68- output_path = ENGINE_PATH / f"{ snake_name } { base_name } .juvix.md"
69- replacements = [
70- (r"tutorial\.engines" , "arch.node.engines" ),
71- (r"template([_-])minimum" , snake_name ),
72- (r"Template( )?Minimum" , name ),
73- ]
74- transform_file (input_path , output_path , replacements )
75-
76- # add the engine to the engines list in docs/everything.juvix.md
77- everything_path = DOCS_PATH / "everything.juvix.md"
78- everything_content = everything_path .read_text ()
79- if f"import arch.node.engines.{ snake_name } _messages;" not in everything_content :
80- more_start = "-- Add more engines here"
81- more_start_index = everything_content .find (more_start ) + len (more_start )
82- everything_content = (
83- everything_content [:more_start_index ]
84- + "\n \n "
85- + f"import arch.node.engines.{ snake_name } _messages;\n "
86- + f"import arch.node.engines.{ snake_name } _config;\n "
87- + f"import arch.node.engines.{ snake_name } _environment;\n "
88- + f"import arch.node.engines.{ snake_name } _behaviour;\n "
89- + f"import arch.node.engines.{ snake_name } ;\n "
90- + everything_content [more_start_index :]
91- )
92- everything_path .write_text (everything_content )
93-
94- def add_import (content : str , import_name : str ):
95- if f"import arch.node.engines.{ import_name } open;" not in content :
96- import_start = "-- Add imports here"
97- import_end = content .find (import_start ) + len (import_start )
98- content = (
99- content [:import_end ]
100- + f"\n import arch.node.engines.{ import_name } open;\n "
101- + content [import_end :]
102- )
103- return content
104-
105- def update_anoma_registry (
106- file_suffix , type_prefix , type_suffix , import_suffix , more_marker
107- ):
108- file_path = ARCH_NODE_PATH / "types" / f"anoma_{ file_suffix } .juvix.md"
109- file_content = file_path .read_text ()
110- if (
111- f"import arch.node.engines.{ snake_name } _{ import_suffix } ;"
112- not in file_content
113- ):
114- file_content = add_import (file_content , snake_name + f"_{ import_suffix } " )
115- if more_marker in file_content :
116- more_start_index = file_content .find (more_marker ) + len (more_marker )
117- new_line = f" | { type_prefix } { name } { name } { type_suffix } \n "
118- if new_line .strip () not in file_content [more_start_index :]:
119- file_content = (
120- file_content [:more_start_index ]
121- + "\n \n "
122- + new_line
123- + file_content [more_start_index :]
124- )
125- file_path .write_text (file_content )
126-
127- update_anoma_registry (
128- "message" , "Msg" , "Msg" , "messages" , "-- Add more messages here"
129- )
130- update_anoma_registry (
131- "config" , "Cfg" , "Cfg" , "config" , "-- Add more configurations here"
132- )
133- update_anoma_registry (
134- "environment" , "Env" , "Env" , "environment" , "-- Add more environments here"
135- )
136-
137- click .echo (f"Engine { Fore .GREEN } { name } { Fore .RESET } created successfully" )
138- click .echo (
139- "Don't forget to:\n "
140- "- update `mkdocs.yml` to add the new engine to the navigation menu\n "
141- f"- review `docs/arch/node/types/anoma_config.juvix.md`, specially where we put new stuff for { name } \n "
142- f"- review `docs/arch/node/types/anoma_message.juvix.md`, specially where we put new stuff for { name } \n "
143- f"- review `docs/arch/node/types/anoma_environment.juvix.md`, specially where we put new stuff for { name } \n "
144- )
145-
146-
147- @new .command ()
148- def version ():
149- """Create a new version of the specification"""
20+ @cli .command ()
21+ def bump ():
22+ """Bump the version of the specification"""
15023 version = questionary .text (
15124 "What is the version of the new version? (e.g: `1.0.0`)"
15225 ).ask ()
0 commit comments