Skip to content

Commit f8a9bfe

Browse files
committed
added test and documentation
1 parent 100feae commit f8a9bfe

23 files changed

+4795
-13
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
*.pdf
33
*_files/
44
/.luarc.json
5+
6+
/.quarto/

README.md

+34-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Filter to include code from source files.
44

55
The filter is largely inspired by
6-
[pandoc-include-code](https://github.com/owickstrom/pandoc-include-code).
6+
[pandoc-include-code](https://github.com/owickstrom/pandoc-include-code) and [sphinx-literalinclude](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-literalinclude).
77

88
## Installing
99

@@ -41,18 +41,47 @@ You can still use other attributes, and classes, to control the code blocks:
4141
```{.python include="script.py" code-line-numbers="true"}
4242
```
4343

44+
### Dedent
45+
46+
Using the `dedent` attribute, you can have whitespaces removed on each line, where possible (non-whitespace character will not be removed even if they occur
47+
in the dedent area).
48+
49+
```{.python include="script.py" dedent=4}
50+
```
51+
4452
### Ranges
4553

4654
If you want to include a specific range of lines, use `start-line` and `end-line`:
4755

4856
```{.python include="script.py" start-line=35 end-line=80}
4957
```
5058

51-
### Dedent
59+
#### New in Version 1.1
5260

53-
Using the `dedent` attribute, you can have whitespaces removed on each line, where possible (non-whitespace character will not be removed even if they occur
54-
in the dedent area).
61+
`include-code-files` now supports additional attributes to specify ranges:
5562

56-
```{.python include="script.py" dedent=4}
63+
* `start-after`: Start immediately after the specified line
64+
* `end-before`: End immediately before the specified line
65+
66+
Furthermore, all range attributes (including `start-line` and `end-line`) now support both numeric and string values.
67+
68+
Using string comments in code, in combination with the `start-after` and `end-before` range attributes allows for
69+
editing of the include file without requiring you to re-determine the proper numeric values after the changes are complete.
70+
71+
For example, in this python file:
72+
73+
```python
74+
# [my_method start]
75+
def my_method():
76+
print("do work")
77+
# [my_method end]
5778
```
5879

80+
To include just the method in your code block, you can do the following:
81+
82+
```{.python include="script.py" start-after="[my_method start]" end-after="[my_method end]"}
83+
```
84+
85+
Then as you edit your method, only the lines between `[my_method start]` and `[my_method end]` will be included in the output.
86+
87+
Note that any combination of start and end attributes is supported. See the test setup in `index.qmd` for more examples.

_extensions/include-code-files/_extension.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
title: Include Code Files
2-
author: Bruno Beaufils
3-
version: 1.0.0
2+
author: Bruno Beaufils, Eric Pinzur
3+
version: 1.1.0
44
quarto-required: ">=1.2"
55
contributes:
66
filters:

_extensions/include-code-files/include-code-files.lua

-6
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ local function transclude (cb)
6262
start = 1
6363
end
6464

65-
quarto.log.output("start: " .. start)
66-
6765
-- set finish and skipLast based on end params
6866
if cb.attributes.endLine then
6967
finish = tonumber(cb.attributes.endLine)
@@ -80,18 +78,14 @@ local function transclude (cb)
8078
-- if no end specified, end at the last line
8179
end
8280

83-
quarto.log.output("finish: " .. finish)
84-
8581
for line in fh:lines ("L")
8682
do
8783
number = number + 1
8884
-- if start or finish is a string, check if it exists on the current line
8985
if type(start) == "string" and string.find(line, start, 1, true) then
9086
start = number
91-
quarto.log.output("convererted start to : " .. start)
9287
elseif type(finish) == "string" and string.find(line, finish, 1 , true) then
9388
finish = number
94-
quarto.log.output("convererted finish to : " .. finish)
9589
end
9690

9791
-- if haven't found start yet, then continue

_quarto.yml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
project:
2+
type: website
3+
output-dir: test
4+
preview:
5+
browser: true # Open a web browser to view the preview
6+
watch-inputs: true # Re-render input files when they change
7+
8+
website:
9+
title: "Quarto + Include-Code-Files"

index.qmd

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: Test of Include-Code-Files Quarto Extension
3+
filters:
4+
- include-code-files
5+
---
6+
7+
**In this post, we will show a simple implementation of `Tic-Tac-Toe` generated by ChatGPT4**
8+
9+
Here is the initial class definition:
10+
11+
```{.python include="tic_tac_toe.py" end-before="[TicTacToe init start]"}
12+
```
13+
14+
15+
Here is a short description of each method within the TicTacToe class in the provided Python file.
16+
17+
18+
1. `__init__(self)`: The constructor for the TicTacToe class. It initializes the game board as a 3x3 grid of spaces and sets the current player to 'X'.
19+
20+
```{.python include="tic_tac_toe.py" dedent=4 start-after="[TicTacToe init start]" end-before="[TicTacToe init end]"}
21+
```
22+
23+
1. `print_board(self)`: Prints the current state of the game board to the console, including the grid lines.
24+
25+
```{.python include="tic_tac_toe.py" dedent=4 start-line="def print_board(self)" end-line=13}
26+
```
27+
28+
1. `is_valid_move(self, row, col)`: Checks whether the specified move (by row and column indices) is valid; that is, if the chosen cell on the board is empty (' ').
29+
30+
```{.python include="tic_tac_toe.py" dedent=4 start-line=15 end-line=16}
31+
```
32+
33+
1. `place_mark(self, row, col)`: Places the current player's mark ('X' or 'O') on the board at the specified location if the move is valid, and returns False if the move is invalid (i.e., if the spot is already taken).
34+
35+
```{.python include="tic_tac_toe.py" dedent=4 start-line=18 end-before=23}
36+
```
37+
38+
1. `switch_player(self)`: Switches the current player from 'X' to 'O' or 'O' to 'X', toggling back and forth after each valid move.
39+
40+
```{.python include="tic_tac_toe.py" dedent=4 start-after=23 end-line=25}
41+
```
42+
43+
1. `check_winner(self)`: Checks all possible winning combinations (rows, columns, and diagonals) to see if either player has won the game. It returns the winning player's mark ('X' or 'O') if there is a winner, or None if there isn't one yet.
44+
45+
```{.python include="tic_tac_toe.py" dedent=4 start-line=27 end-line="return None"}
46+
```
47+
48+
1. `is_board_full(self)`: Checks whether the board is completely filled with players' marks; returns True if full, indicating a tie if there's no winner, or False if there are still empty spaces.
49+
50+
```{.python include="tic_tac_toe.py" dedent=4 start-line=40 end-line=41}
51+
```
52+
53+
1. `play_game(self)`: The main game loop that repeatedly asks the current player for their move, checks for a win or a tie, and switches players. This method controls the game flow, displaying the board and prompting the players until the game ends with a winner or a tie.
54+
55+
```{.python include="tic_tac_toe.py" dedent=4 start-line="def play_game(self)" end-before="# Main game execution"}
56+
```
57+
58+
Here is the main game execution:
59+
60+
```{.python include="tic_tac_toe.py" start-after="# Main game execution"}
61+
```
62+
63+
64+
Finally, here is the full implementation:
65+
66+
```{.python include="tic_tac_toe.py" code-line-numbers="true"}
67+
```

test/search.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[
2+
{
3+
"objectID": "index.html",
4+
"href": "index.html",
5+
"title": "Test of Include-Code-Files Quarto Extension",
6+
"section": "",
7+
"text": "In this post, we will show a simple implementation of Tic-Tac-Toe generated by ChatGPT4\nHere is the initial class definition:\n# tic_tac_toe.py\n\nclass TicTacToe:\nHere is a short description of each method within the TicTacToe class in the provided Python file.\n\n__init__(self): The constructor for the TicTacToe class. It initializes the game board as a 3x3 grid of spaces and sets the current player to ‘X’.\ndef __init__(self):\n self.board = [[' ' for _ in range(3)] for _ in range(3)]\n self.current_turn = 'X'\nprint_board(self): Prints the current state of the game board to the console, including the grid lines.\ndef print_board(self):\n for row in self.board:\n print('|'.join(row))\n print('-'*5)\nis_valid_move(self, row, col): Checks whether the specified move (by row and column indices) is valid; that is, if the chosen cell on the board is empty (’ ’).\ndef is_valid_move(self, row, col):\n return self.board[row][col] == ' '\nplace_mark(self, row, col): Places the current player’s mark (‘X’ or ‘O’) on the board at the specified location if the move is valid, and returns False if the move is invalid (i.e., if the spot is already taken).\ndef place_mark(self, row, col):\n if not self.is_valid_move(row, col):\n return False\n self.board[row][col] = self.current_turn\n return True\nswitch_player(self): Switches the current player from ‘X’ to ‘O’ or ‘O’ to ‘X’, toggling back and forth after each valid move.\ndef switch_player(self):\n self.current_turn = 'O' if self.current_turn == 'X' else 'X'\ncheck_winner(self): Checks all possible winning combinations (rows, columns, and diagonals) to see if either player has won the game. It returns the winning player’s mark (‘X’ or ‘O’) if there is a winner, or None if there isn’t one yet.\ndef check_winner(self):\n # Check rows, columns and diagonals\n for i in range(3):\n if self.board[i][0] == self.board[i][1] == self.board[i][2] != ' ':\n return self.board[i][0]\n if self.board[0][i] == self.board[1][i] == self.board[2][i] != ' ':\n return self.board[0][i]\n if self.board[0][0] == self.board[1][1] == self.board[2][2] != ' ':\n return self.board[0][0]\n if self.board[0][2] == self.board[1][1] == self.board[2][0] != ' ':\n return self.board[0][2]\n return None\nis_board_full(self): Checks whether the board is completely filled with players’ marks; returns True if full, indicating a tie if there’s no winner, or False if there are still empty spaces.\ndef is_board_full(self):\n return all(self.board[row][col] != ' ' for row in range(3) for col in range(3))\nplay_game(self): The main game loop that repeatedly asks the current player for their move, checks for a win or a tie, and switches players. This method controls the game flow, displaying the board and prompting the players until the game ends with a winner or a tie.\ndef play_game(self):\n while True:\n self.print_board()\n\n # Try to place a mark, if the move is invalid, retry.\n try:\n row = int(input(f\"Player {self.current_turn}, enter your move row (0-2): \"))\n col = int(input(f\"Player {self.current_turn}, enter your move column (0-2): \"))\n except ValueError:\n print(\"Please enter numbers between 0 and 2.\")\n continue\n\n if row < 0 or row > 2 or col < 0 or col > 2:\n print(\"Invalid move. Try again.\")\n continue\n\n if not self.place_mark(row, col):\n print(\"This spot is taken. Try another spot.\")\n continue\n\n winner = self.check_winner()\n if winner:\n self.print_board()\n print(f\"Player {winner} wins!\")\n break\n elif self.is_board_full():\n self.print_board()\n print(\"It's a tie!\")\n break\n\n self.switch_player()\n\n\nHere is the main game execution:\nif __name__ == \"__main__\":\n game = TicTacToe()\n game.play_game()\nFinally, here is the full implementation:\n# tic_tac_toe.py\n\nclass TicTacToe:\n # [TicTacToe init start]\n def __init__(self):\n self.board = [[' ' for _ in range(3)] for _ in range(3)]\n self.current_turn = 'X'\n # [TicTacToe init end]\n\n def print_board(self):\n for row in self.board:\n print('|'.join(row))\n print('-'*5)\n\n def is_valid_move(self, row, col):\n return self.board[row][col] == ' '\n\n def place_mark(self, row, col):\n if not self.is_valid_move(row, col):\n return False\n self.board[row][col] = self.current_turn\n return True\n\n def switch_player(self):\n self.current_turn = 'O' if self.current_turn == 'X' else 'X'\n\n def check_winner(self):\n # Check rows, columns and diagonals\n for i in range(3):\n if self.board[i][0] == self.board[i][1] == self.board[i][2] != ' ':\n return self.board[i][0]\n if self.board[0][i] == self.board[1][i] == self.board[2][i] != ' ':\n return self.board[0][i]\n if self.board[0][0] == self.board[1][1] == self.board[2][2] != ' ':\n return self.board[0][0]\n if self.board[0][2] == self.board[1][1] == self.board[2][0] != ' ':\n return self.board[0][2]\n return None\n\n def is_board_full(self):\n return all(self.board[row][col] != ' ' for row in range(3) for col in range(3))\n\n def play_game(self):\n while True:\n self.print_board()\n\n # Try to place a mark, if the move is invalid, retry.\n try:\n row = int(input(f\"Player {self.current_turn}, enter your move row (0-2): \"))\n col = int(input(f\"Player {self.current_turn}, enter your move column (0-2): \"))\n except ValueError:\n print(\"Please enter numbers between 0 and 2.\")\n continue\n\n if row < 0 or row > 2 or col < 0 or col > 2:\n print(\"Invalid move. Try again.\")\n continue\n\n if not self.place_mark(row, col):\n print(\"This spot is taken. Try another spot.\")\n continue\n\n winner = self.check_winner()\n if winner:\n self.print_board()\n print(f\"Player {winner} wins!\")\n break\n elif self.is_board_full():\n self.print_board()\n print(\"It's a tie!\")\n break\n\n self.switch_player()\n\n# Main game execution\nif __name__ == \"__main__\":\n game = TicTacToe()\n game.play_game()"
8+
}
9+
]

0 commit comments

Comments
 (0)