or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdcomment-handling.mdglobal-licensing.mdindex.mdproject-management.mdreport-generation.mdreuse-info.mdvcs-integration.md

comment-handling.mddocs/

0

# Comment Handling System

1

2

REUSE provides an extensible comment processing system that supports 25+ file types for adding and parsing copyright headers. The system automatically detects comment styles and provides utilities for managing comment-based REUSE information.

3

4

## Capabilities

5

6

### Comment Style Detection

7

8

Automatically detect and retrieve appropriate comment styles for files.

9

10

```python { .api }

11

def get_comment_style(path: StrPath) -> Optional[Type[CommentStyle]]:

12

"""

13

Detect comment style for file path.

14

15

Args:

16

path: File path to analyze (accepts str or Path-like)

17

18

Returns:

19

CommentStyle class appropriate for the file type, or None if unsupported

20

21

Note:

22

Detection is based on file extension and content analysis.

23

Returns the most appropriate comment style class for the file.

24

"""

25

26

def is_uncommentable(path: Path) -> bool:

27

"""

28

Check if file cannot have comments added.

29

30

Args:

31

path: File path to check

32

33

Returns:

34

True if file type doesn't support comments (e.g., binary files)

35

"""

36

37

def has_style(path: Path) -> bool:

38

"""

39

Check if path has a known comment style.

40

41

Args:

42

path: File path to check

43

44

Returns:

45

True if a comment style exists for this file type

46

"""

47

```

48

49

**Usage Examples:**

50

51

```python

52

from reuse.comment import get_comment_style, is_uncommentable, has_style

53

from pathlib import Path

54

55

# Detect comment style for different file types

56

python_file = Path("example.py")

57

c_file = Path("example.c")

58

html_file = Path("example.html")

59

60

# Get comment styles

61

python_style = get_comment_style(python_file)

62

c_style = get_comment_style(c_file)

63

html_style = get_comment_style(html_file)

64

65

print(f"Python style: {python_style.__name__ if python_style else 'None'}")

66

print(f"C style: {c_style.__name__ if c_style else 'None'}")

67

print(f"HTML style: {html_style.__name__ if html_style else 'None'}")

68

69

# Check if files can be commented

70

print(f"Can comment Python: {not is_uncommentable(python_file)}")

71

print(f"Python has style: {has_style(python_file)}")

72

73

# Check binary file

74

binary_file = Path("example.png")

75

print(f"Can comment PNG: {not is_uncommentable(binary_file)}")

76

```

77

78

### Base Comment Style Class

79

80

The foundation class for all comment style implementations.

81

82

```python { .api }

83

class CommentStyle:

84

"""

85

Base class for different file comment styles.

86

87

Subclasses implement specific comment syntax for different file types.

88

Each style defines how to create single-line and multi-line comments

89

appropriate for the file format.

90

"""

91

92

# Class attributes defined by subclasses:

93

SHORTHAND: str = "" # Short identifier for the style

94

SINGLE_LINE: str = "" # Single-line comment prefix

95

SINGLE_LINE_REGEXP: Optional[re.Pattern] = None # Regex for parsing single-line comments

96

INDENT_AFTER_SINGLE: str = "" # Indentation after single-line prefix

97

MULTI_LINE: MultiLineSegments = MultiLineSegments("", "", "") # Multi-line comment structure

98

INDENT_BEFORE_MIDDLE: str = "" # Indentation before middle marker

99

INDENT_AFTER_MIDDLE: str = "" # Indentation after middle marker

100

INDENT_BEFORE_END: str = "" # Indentation before end marker

101

SHEBANGS: list[str] = [] # Supported shebang patterns

102

103

@classmethod

104

def can_handle_single(cls) -> bool:

105

"""Whether the CommentStyle can handle single-line comments."""

106

107

@classmethod

108

def can_handle_multi(cls) -> bool:

109

"""Whether the CommentStyle can handle multi-line comments."""

110

111

@classmethod

112

def create_comment(cls, text: str, force_multi: bool = False) -> str:

113

"""Comment all lines in text. Single-line comments are preferred unless force_multi is True.

114

115

Raises:

116

CommentCreateError: if text could not be commented.

117

"""

118

119

@classmethod

120

def parse_comment(cls, text: str) -> str:

121

"""Parse and extract comment content from commented text.

122

123

Raises:

124

CommentParseError: if text could not be parsed.

125

"""

126

127

@classmethod

128

def comment_at_first_character(cls, text: str) -> str:

129

"""Create comment starting at the first character of text."""

130

```

131

132

### Multi-line Comment Structure

133

134

Data structure for multi-line comment formatting.

135

136

```python { .api }

137

class MultiLineSegments(NamedTuple):

138

"""

139

Structure for multi-line comment formatting.

140

141

Attributes:

142

start: str - Start marker for multi-line comment

143

middle: str - Middle prefix for each line in multi-line comment

144

end: str - End marker for multi-line comment

145

"""

146

start: str

147

middle: str

148

end: str

149

```

150

151

**Usage Examples:**

152

153

```python

154

from reuse.comment import MultiLineSegments, CommentStyle

155

156

# Example multi-line segments for C-style comments

157

c_multiline = MultiLineSegments(

158

start="/*",

159

middle=" *",

160

end=" */"

161

)

162

163

print(f"C comment start: {c_multiline.start}")

164

print(f"C comment middle: {c_multiline.middle}")

165

print(f"C comment end: {c_multiline.end}")

166

```

167

168

### Supported Comment Styles

169

170

The system provides built-in support for 25+ file types through specialized comment style classes.

171

172

```python { .api }

173

# Programming Languages

174

class PythonCommentStyle(CommentStyle):

175

"""Python files (.py) - # single-line comments"""

176

pass

177

178

class CCommentStyle(CommentStyle):

179

"""C files (.c, .h) - /* multi-line */ comments"""

180

pass

181

182

class CppCommentStyle(CommentStyle):

183

"""C++ files (.cpp, .hpp) - /* multi-line */ comments"""

184

pass

185

186

class CppSingleCommentStyle(CommentStyle):

187

"""C++ files - // single-line comments"""

188

pass

189

190

class JavaCommentStyle(CommentStyle):

191

"""Java files (.java) - /* multi-line */ and // single-line"""

192

pass

193

194

class HaskellCommentStyle(CommentStyle):

195

"""Haskell files (.hs) - -- single-line comments"""

196

pass

197

198

class JuliaCommentStyle(CommentStyle):

199

"""Julia files (.jl) - # single-line comments"""

200

pass

201

202

class FortranCommentStyle(CommentStyle):

203

"""Fortran files (.f, .for) - C or * in column 1"""

204

pass

205

206

class ModernFortranCommentStyle(CommentStyle):

207

"""Modern Fortran files (.f90, .f95) - ! single-line comments"""

208

pass

209

210

class LispCommentStyle(CommentStyle):

211

"""Lisp files (.lisp, .cl) - ; single-line comments"""

212

pass

213

214

class MlCommentStyle(CommentStyle):

215

"""ML files (.ml, .mli) - (* multi-line *) comments"""

216

pass

217

218

class LeanCommentStyle(CommentStyle):

219

"""Lean files (.lean) - -- single-line comments"""

220

pass

221

222

# Markup and Templates

223

class HtmlCommentStyle(CommentStyle):

224

"""HTML files (.html, .htm) - <!-- multi-line --> comments"""

225

pass

226

227

class JinjaCommentStyle(CommentStyle):

228

"""Jinja templates (.j2, .jinja) - {# multi-line #} comments"""

229

pass

230

231

class HandlebarsCommentStyle(CommentStyle):

232

"""Handlebars templates (.hbs) - {{! multi-line }} comments"""

233

pass

234

235

class VelocityCommentStyle(CommentStyle):

236

"""Velocity templates (.vm) - ## single-line comments"""

237

pass

238

239

class TexCommentStyle(CommentStyle):

240

"""TeX/LaTeX files (.tex, .sty) - % single-line comments"""

241

pass

242

243

class ReStructedTextCommentStyle(CommentStyle):

244

"""reStructuredText files (.rst) - .. single-line comments"""

245

pass

246

247

# Configuration and Data

248

class BibTexCommentStyle(CommentStyle):

249

"""BibTeX files (.bib) - % single-line comments"""

250

pass

251

252

class M4CommentStyle(CommentStyle):

253

"""M4 files (.m4) - dnl single-line comments"""

254

pass

255

256

class FtlCommentStyle(CommentStyle):

257

"""FTL files (.ftl) - <#-- multi-line --> comments"""

258

pass

259

260

# Scripting and System

261

class BatchFileCommentStyle(CommentStyle):

262

"""Batch files (.bat, .cmd) - REM single-line comments"""

263

pass

264

265

class AppleScriptCommentStyle(CommentStyle):

266

"""AppleScript files (.scpt) - -- single-line comments"""

267

pass

268

269

class VimCommentStyle(CommentStyle):

270

"""Vim script files (.vim) - \" single-line comments"""

271

pass

272

273

class UnixManCommentStyle(CommentStyle):

274

"""Unix manual pages (.1, .2, etc.) - .\\\" single-line comments"""

275

pass

276

277

# Other Formats

278

class AspxCommentStyle(CommentStyle):

279

"""ASPX files (.aspx) - <%-- multi-line --%> comments"""

280

pass

281

282

class XQueryCommentStyle(CommentStyle):

283

"""XQuery files (.xq, .xquery) - (: multi-line :) comments"""

284

pass

285

286

class PlantUmlCommentStyle(CommentStyle):

287

"""PlantUML files (.puml) - ' single-line comments"""

288

pass

289

290

class SemicolonCommentStyle(CommentStyle):

291

"""Files using semicolon comments - ; single-line comments"""

292

pass

293

294

# Special Cases

295

class EmptyCommentStyle(CommentStyle):

296

"""Files that support comments but with empty prefix"""

297

pass

298

299

class UncommentableCommentStyle(CommentStyle):

300

"""Files that cannot have comments (binary files, etc.)"""

301

pass

302

```

303

304

### Comment Style Registry

305

306

Access the mapping between style names and comment style classes.

307

308

```python { .api }

309

NAME_STYLE_MAP: dict[str, Type[CommentStyle]]

310

"""Dictionary mapping style names to comment style classes."""

311

```

312

313

**Usage Examples:**

314

315

```python

316

from reuse.comment import NAME_STYLE_MAP

317

318

# List all available comment styles

319

print("Available comment styles:")

320

for name, style_class in NAME_STYLE_MAP.items():

321

print(f" {name}: {style_class.__name__}")

322

323

# Get specific style by name

324

python_style = NAME_STYLE_MAP.get("python")

325

if python_style:

326

print(f"Python style class: {python_style.__name__}")

327

328

# Check if style exists

329

has_rust_style = "rust" in NAME_STYLE_MAP

330

print(f"Has Rust style: {has_rust_style}")

331

```

332

333

## Comment Style Usage Examples

334

335

### Working with Different Comment Styles

336

337

```python

338

from reuse.comment import get_comment_style, PythonCommentStyle, CCommentStyle

339

from pathlib import Path

340

341

def demonstrate_comment_styles():

342

"""Demonstrate comment style detection and usage."""

343

344

# File type detection

345

files = [

346

Path("example.py"),

347

Path("example.c"),

348

Path("example.html"),

349

Path("example.js"),

350

Path("example.tex")

351

]

352

353

for file_path in files:

354

style_class = get_comment_style(file_path)

355

if style_class:

356

print(f"\n{file_path.suffix} files use: {style_class.__name__}")

357

358

# Create style instance

359

style = style_class()

360

361

# Show single-line comment prefix

362

if hasattr(style, 'SINGLE_LINE') and style.SINGLE_LINE:

363

print(f" Single-line: '{style.SINGLE_LINE}'")

364

365

# Show multi-line comment structure

366

if hasattr(style, 'MULTI_LINE') and style.MULTI_LINE:

367

ml = style.MULTI_LINE

368

print(f" Multi-line: '{ml.start}' ... '{ml.middle}' ... '{ml.end}'")

369

370

demonstrate_comment_styles()

371

```

372

373

### Creating Custom Comment Headers

374

375

```python

376

from reuse.comment import get_comment_style, MultiLineSegments

377

from pathlib import Path

378

379

def create_comment_header(file_path: Path, copyright_text: str, license_id: str) -> str:

380

"""Create a properly formatted comment header for a file."""

381

382

style_class = get_comment_style(file_path)

383

if not style_class:

384

return ""

385

386

style = style_class()

387

388

# Prepare header content

389

header_lines = [

390

f"SPDX-FileCopyrightText: {copyright_text}",

391

f"SPDX-License-Identifier: {license_id}"

392

]

393

394

# Format based on comment style

395

if hasattr(style, 'MULTI_LINE') and style.MULTI_LINE:

396

# Use multi-line comment format

397

ml = style.MULTI_LINE

398

formatted_lines = [ml.start]

399

for line in header_lines:

400

formatted_lines.append(f"{ml.middle} {line}")

401

formatted_lines.append(ml.end)

402

return "\n".join(formatted_lines)

403

404

elif hasattr(style, 'SINGLE_LINE') and style.SINGLE_LINE:

405

# Use single-line comment format

406

prefix = style.SINGLE_LINE

407

indent = getattr(style, 'INDENT_AFTER_SINGLE', ' ')

408

formatted_lines = []

409

for line in header_lines:

410

formatted_lines.append(f"{prefix}{indent}{line}")

411

return "\n".join(formatted_lines)

412

413

return ""

414

415

# Usage examples

416

python_header = create_comment_header(

417

Path("example.py"),

418

"2023 Jane Doe <jane@example.com>",

419

"MIT"

420

)

421

print("Python header:")

422

print(python_header)

423

424

c_header = create_comment_header(

425

Path("example.c"),

426

"2023 Jane Doe <jane@example.com>",

427

"GPL-3.0-or-later"

428

)

429

print("\nC header:")

430

print(c_header)

431

```

432

433

### File Type Comment Style Reference

434

435

```python

436

from reuse.comment import get_comment_style

437

from pathlib import Path

438

439

def show_comment_reference():

440

"""Show comment styles for common file types."""

441

442

file_extensions = [

443

".py", ".c", ".cpp", ".java", ".rs", ".go", ".js", ".ts",

444

".html", ".css", ".scss", ".php", ".rb", ".pl", ".sh",

445

".tex", ".md", ".rst", ".yaml", ".json", ".xml", ".sql"

446

]

447

448

print("File Type Comment Style Reference:")

449

print("=" * 50)

450

451

for ext in file_extensions:

452

test_file = Path(f"test{ext}")

453

style_class = get_comment_style(test_file)

454

455

if style_class:

456

style = style_class()

457

comment_info = []

458

459

if hasattr(style, 'SINGLE_LINE') and style.SINGLE_LINE:

460

comment_info.append(f"single: '{style.SINGLE_LINE}'")

461

462

if hasattr(style, 'MULTI_LINE') and style.MULTI_LINE:

463

ml = style.MULTI_LINE

464

comment_info.append(f"multi: '{ml.start}...{ml.end}'")

465

466

print(f"{ext:8} -> {style_class.__name__:25} ({', '.join(comment_info)})")

467

else:

468

print(f"{ext:8} -> No comment style available")

469

470

show_comment_reference()

471

```