strcase-cli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Marcus
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,57 @@
1
+ Metadata-Version: 2.4
2
+ Name: strcase-cli
3
+ Version: 0.1.0
4
+ Summary: Convert strings between camelCase, snake_case, kebab-case, PascalCase, and more
5
+ Author-email: Marcus <marcus@marcusbuilds.ai>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/marcusbuildsthings-droid/strcase
8
+ Project-URL: Issues, https://github.com/marcusbuildsthings-droid/strcase/issues
9
+ Keywords: cli,string,case,convert,camelCase,snake_case
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Text Processing
15
+ Classifier: Topic :: Utilities
16
+ Requires-Python: >=3.8
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: click>=8.0
20
+ Dynamic: license-file
21
+
22
+ # strcase-cli
23
+
24
+ Convert strings between naming conventions from the command line.
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ pip install strcase-cli
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ```bash
35
+ strcase snake "myVariableName" # my_variable_name
36
+ strcase camel "my_variable_name" # myVariableName
37
+ strcase pascal "my-variable-name" # MyVariableName
38
+ strcase kebab "MyVariableName" # my-variable-name
39
+ strcase screaming "myVar" # MY_VAR
40
+ strcase dot "myVar" # my.var
41
+ strcase title "my_var_name" # My Var Name
42
+ strcase train "myVarName" # My-Var-Name
43
+ strcase cobol "myVarName" # MY-VAR-NAME
44
+ strcase all "myVariableName" # Show all conversions
45
+ strcase detect "my_variable_name" # snake
46
+ strcase types # List all styles
47
+ ```
48
+
49
+ All commands support `--json` for machine-readable output and `-f FILE` for batch processing.
50
+
51
+ ## For AI Agents
52
+
53
+ See [SKILL.md](SKILL.md) for agent-optimized documentation.
54
+
55
+ ## License
56
+
57
+ MIT
@@ -0,0 +1,36 @@
1
+ # strcase-cli
2
+
3
+ Convert strings between naming conventions from the command line.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install strcase-cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ strcase snake "myVariableName" # my_variable_name
15
+ strcase camel "my_variable_name" # myVariableName
16
+ strcase pascal "my-variable-name" # MyVariableName
17
+ strcase kebab "MyVariableName" # my-variable-name
18
+ strcase screaming "myVar" # MY_VAR
19
+ strcase dot "myVar" # my.var
20
+ strcase title "my_var_name" # My Var Name
21
+ strcase train "myVarName" # My-Var-Name
22
+ strcase cobol "myVarName" # MY-VAR-NAME
23
+ strcase all "myVariableName" # Show all conversions
24
+ strcase detect "my_variable_name" # snake
25
+ strcase types # List all styles
26
+ ```
27
+
28
+ All commands support `--json` for machine-readable output and `-f FILE` for batch processing.
29
+
30
+ ## For AI Agents
31
+
32
+ See [SKILL.md](SKILL.md) for agent-optimized documentation.
33
+
34
+ ## License
35
+
36
+ MIT
@@ -0,0 +1,29 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "strcase-cli"
7
+ version = "0.1.0"
8
+ description = "Convert strings between camelCase, snake_case, kebab-case, PascalCase, and more"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.8"
12
+ authors = [{name = "Marcus", email = "marcus@marcusbuilds.ai"}]
13
+ keywords = ["cli", "string", "case", "convert", "camelCase", "snake_case"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "Programming Language :: Python :: 3",
19
+ "Topic :: Text Processing",
20
+ "Topic :: Utilities",
21
+ ]
22
+ dependencies = ["click>=8.0"]
23
+
24
+ [project.scripts]
25
+ strcase = "strcase.cli:cli"
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/marcusbuildsthings-droid/strcase"
29
+ Issues = "https://github.com/marcusbuildsthings-droid/strcase/issues"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,2 @@
1
+ """strcase-cli — Convert strings between naming conventions."""
2
+ __version__ = "0.1.0"
@@ -0,0 +1,95 @@
1
+ """CLI for strcase."""
2
+ import json
3
+ import sys
4
+
5
+ import click
6
+
7
+ from .converter import CONVERTERS, convert_all, detect_case, tokenize
8
+
9
+
10
+ def _read_input(text: str | None, file: str | None) -> list[str]:
11
+ """Get input strings from args, stdin, or file."""
12
+ if file:
13
+ with open(file) as f:
14
+ return [line.rstrip('\n') for line in f if line.strip()]
15
+ if text:
16
+ return [text]
17
+ if not sys.stdin.isatty():
18
+ return [line.rstrip('\n') for line in sys.stdin if line.strip()]
19
+ raise click.UsageError('Provide TEXT argument, --file, or pipe via stdin.')
20
+
21
+
22
+ def _output(results, as_json: bool):
23
+ if as_json:
24
+ click.echo(json.dumps(results, indent=2))
25
+ elif isinstance(results, list):
26
+ for r in results:
27
+ click.echo(r)
28
+ else:
29
+ click.echo(results)
30
+
31
+
32
+ @click.group()
33
+ @click.version_option()
34
+ def cli():
35
+ """Convert strings between naming conventions."""
36
+
37
+
38
+ def _make_command(case_name: str, converter):
39
+ @cli.command(name=case_name)
40
+ @click.argument('text', required=False)
41
+ @click.option('-f', '--file', help='Read lines from file')
42
+ @click.option('--json', 'as_json', is_flag=True, help='JSON output')
43
+ def cmd(text, file, as_json):
44
+ f"""Convert to {case_name} case."""
45
+ lines = _read_input(text, file)
46
+ results = [converter(l) for l in lines]
47
+ if as_json:
48
+ _output([{'input': i, 'output': o} for i, o in zip(lines, results)], True)
49
+ else:
50
+ for r in results:
51
+ click.echo(r)
52
+ cmd.__doc__ = f'Convert to {case_name} case.'
53
+ return cmd
54
+
55
+
56
+ for _name, _fn in CONVERTERS.items():
57
+ _make_command(_name, _fn)
58
+
59
+
60
+ @cli.command()
61
+ @click.argument('text', required=False)
62
+ @click.option('-f', '--file', help='Read lines from file')
63
+ @click.option('--json', 'as_json', is_flag=True, help='JSON output')
64
+ def all(text, file, as_json):
65
+ """Convert to all case styles at once."""
66
+ lines = _read_input(text, file)
67
+ if as_json:
68
+ _output([{'input': l, **convert_all(l)} for l in lines], True)
69
+ else:
70
+ for l in lines:
71
+ click.echo(f'Input: {l}')
72
+ for name, val in convert_all(l).items():
73
+ click.echo(f' {name:12s} → {val}')
74
+ click.echo()
75
+
76
+
77
+ @cli.command()
78
+ @click.argument('text')
79
+ @click.option('--json', 'as_json', is_flag=True, help='JSON output')
80
+ def detect(text, as_json):
81
+ """Detect the case style of a string."""
82
+ style = detect_case(text)
83
+ tokens = tokenize(text)
84
+ if as_json:
85
+ _output({'input': text, 'detected': style, 'tokens': tokens}, True)
86
+ else:
87
+ click.echo(f'{style} (tokens: {tokens})')
88
+
89
+
90
+ @cli.command()
91
+ def types():
92
+ """List all supported case styles."""
93
+ examples = convert_all('myVariableName')
94
+ for name, ex in examples.items():
95
+ click.echo(f' {name:12s} {ex}')
@@ -0,0 +1,115 @@
1
+ """Core conversion logic."""
2
+ import re
3
+
4
+
5
+ def tokenize(s: str) -> list[str]:
6
+ """Split a string into word tokens regardless of input case style."""
7
+ # Replace common separators with space
8
+ s = re.sub(r'[-_./\\]', ' ', s)
9
+ # Insert space before uppercase letters that follow lowercase (camelCase boundaries)
10
+ s = re.sub(r'([a-z\d])([A-Z])', r'\1 \2', s)
11
+ # Insert space between consecutive uppercase and lowercase (e.g., HTMLParser -> HTML Parser)
12
+ s = re.sub(r'([A-Z]+)([A-Z][a-z])', r'\1 \2', s)
13
+ return [w for w in s.split() if w]
14
+
15
+
16
+ def to_snake(s: str) -> str:
17
+ return '_'.join(w.lower() for w in tokenize(s))
18
+
19
+
20
+ def to_camel(s: str) -> str:
21
+ words = tokenize(s)
22
+ if not words:
23
+ return ''
24
+ return words[0].lower() + ''.join(w.capitalize() for w in words[1:])
25
+
26
+
27
+ def to_pascal(s: str) -> str:
28
+ return ''.join(w.capitalize() for w in tokenize(s))
29
+
30
+
31
+ def to_kebab(s: str) -> str:
32
+ return '-'.join(w.lower() for w in tokenize(s))
33
+
34
+
35
+ def to_screaming(s: str) -> str:
36
+ return '_'.join(w.upper() for w in tokenize(s))
37
+
38
+
39
+ def to_dot(s: str) -> str:
40
+ return '.'.join(w.lower() for w in tokenize(s))
41
+
42
+
43
+ def to_path(s: str) -> str:
44
+ return '/'.join(w.lower() for w in tokenize(s))
45
+
46
+
47
+ def to_title(s: str) -> str:
48
+ return ' '.join(w.capitalize() for w in tokenize(s))
49
+
50
+
51
+ def to_sentence(s: str) -> str:
52
+ words = tokenize(s)
53
+ if not words:
54
+ return ''
55
+ return words[0].capitalize() + ' ' + ' '.join(w.lower() for w in words[1:]) if len(words) > 1 else words[0].capitalize()
56
+
57
+
58
+ def to_flat(s: str) -> str:
59
+ return ''.join(w.lower() for w in tokenize(s))
60
+
61
+
62
+ def to_cobol(s: str) -> str:
63
+ return '-'.join(w.upper() for w in tokenize(s))
64
+
65
+
66
+ def to_train(s: str) -> str:
67
+ return '-'.join(w.capitalize() for w in tokenize(s))
68
+
69
+
70
+ CONVERTERS = {
71
+ 'snake': to_snake,
72
+ 'camel': to_camel,
73
+ 'pascal': to_pascal,
74
+ 'kebab': to_kebab,
75
+ 'screaming': to_screaming,
76
+ 'dot': to_dot,
77
+ 'path': to_path,
78
+ 'title': to_title,
79
+ 'sentence': to_sentence,
80
+ 'flat': to_flat,
81
+ 'cobol': to_cobol,
82
+ 'train': to_train,
83
+ }
84
+
85
+
86
+ def detect_case(s: str) -> str:
87
+ """Best-effort detection of the current case style."""
88
+ if '_' in s and s == s.upper():
89
+ return 'screaming'
90
+ if '_' in s and s == s.lower():
91
+ return 'snake'
92
+ if '-' in s and s == s.upper():
93
+ return 'cobol'
94
+ if '-' in s and s == s.lower():
95
+ return 'kebab'
96
+ if '-' in s and s[0].isupper():
97
+ return 'train'
98
+ if '.' in s:
99
+ return 'dot'
100
+ if '/' in s:
101
+ return 'path'
102
+ if ' ' in s:
103
+ if s[0].isupper() and all(w[0].isupper() for w in s.split() if w):
104
+ return 'title'
105
+ return 'sentence'
106
+ if s[0].islower() and any(c.isupper() for c in s):
107
+ return 'camel'
108
+ if s[0].isupper() and any(c.isupper() for c in s[1:]):
109
+ return 'pascal'
110
+ return 'unknown'
111
+
112
+
113
+ def convert_all(s: str) -> dict[str, str]:
114
+ """Convert to all styles."""
115
+ return {name: fn(s) for name, fn in CONVERTERS.items()}
@@ -0,0 +1,57 @@
1
+ Metadata-Version: 2.4
2
+ Name: strcase-cli
3
+ Version: 0.1.0
4
+ Summary: Convert strings between camelCase, snake_case, kebab-case, PascalCase, and more
5
+ Author-email: Marcus <marcus@marcusbuilds.ai>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/marcusbuildsthings-droid/strcase
8
+ Project-URL: Issues, https://github.com/marcusbuildsthings-droid/strcase/issues
9
+ Keywords: cli,string,case,convert,camelCase,snake_case
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Text Processing
15
+ Classifier: Topic :: Utilities
16
+ Requires-Python: >=3.8
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: click>=8.0
20
+ Dynamic: license-file
21
+
22
+ # strcase-cli
23
+
24
+ Convert strings between naming conventions from the command line.
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ pip install strcase-cli
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ```bash
35
+ strcase snake "myVariableName" # my_variable_name
36
+ strcase camel "my_variable_name" # myVariableName
37
+ strcase pascal "my-variable-name" # MyVariableName
38
+ strcase kebab "MyVariableName" # my-variable-name
39
+ strcase screaming "myVar" # MY_VAR
40
+ strcase dot "myVar" # my.var
41
+ strcase title "my_var_name" # My Var Name
42
+ strcase train "myVarName" # My-Var-Name
43
+ strcase cobol "myVarName" # MY-VAR-NAME
44
+ strcase all "myVariableName" # Show all conversions
45
+ strcase detect "my_variable_name" # snake
46
+ strcase types # List all styles
47
+ ```
48
+
49
+ All commands support `--json` for machine-readable output and `-f FILE` for batch processing.
50
+
51
+ ## For AI Agents
52
+
53
+ See [SKILL.md](SKILL.md) for agent-optimized documentation.
54
+
55
+ ## License
56
+
57
+ MIT
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ strcase/__init__.py
5
+ strcase/cli.py
6
+ strcase/converter.py
7
+ strcase_cli.egg-info/PKG-INFO
8
+ strcase_cli.egg-info/SOURCES.txt
9
+ strcase_cli.egg-info/dependency_links.txt
10
+ strcase_cli.egg-info/entry_points.txt
11
+ strcase_cli.egg-info/requires.txt
12
+ strcase_cli.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ strcase = strcase.cli:cli
@@ -0,0 +1 @@
1
+ click>=8.0
@@ -0,0 +1 @@
1
+ strcase