Modify Rakefile and lib_src2md.rb. Rename and modify lib_sec_file.rb to lib_src_file.rb. Change the directory structure.

This commit is contained in:
Toshio Sekiya 2021-04-27 21:08:30 +09:00
parent 1da8dec297
commit 0d3967da0b
18 changed files with 1366 additions and 197 deletions

228
Rakefile
View file

@ -1,21 +1,58 @@
require 'rake/clean' require 'rake/clean'
require_relative 'lib/lib_sec_file.rb' require_relative 'lib/lib_src_file.rb'
require_relative 'lib/lib_src2md.rb' require_relative 'lib/lib_src2md.rb'
require_relative 'lib/lib_gen_main_tex.rb' require_relative 'lib/lib_gen_main_tex.rb'
require_relative 'lib/lib_add_head_tail_html.rb' require_relative 'lib/lib_add_head_tail_html.rb'
srcfiles = [] secfiles = []
FileList['src/sec*.src.md'].each do |file| FileList['src/sec*.src.md'].each do |file|
srcfiles << Sec_file.new(file) secfiles << Sec_file.new(file)
end end
srcfiles = Sec_files.new srcfiles secfiles = Sec_files.new secfiles
srcfiles.renum! secfiles.renum!
def basename srcfile
File.basename(srcfile, ".src.md")
end
abstract = Src_file.new "src/abstract.src.md"
otherfiles = ["src/turtle/turtle_doc.src.md",
"src/tfetextview/tfetextview_doc.src.md",
"src/Readme_for_developers.src.md"]
otherfiles = otherfiles.map {|file| Src_file.new file}
srcfiles = secfiles + otherfiles
file_table = srcfiles.map do |srcfile|
[
srcfile,
"gfm/" + srcfile.to_md,
"html/" + srcfile.to_html,
"latex/" + srcfile.to_tex
]
end
# Paths are relative from the directory "src".
file_table_src = srcfiles.map do |srcfile|
[
srcfile.sub(/^src\//, ""),
"../gfm/" + srcfile.to_md,
"../html/" + srcfile.to_html,
"../latex/" + srcfile.to_tex
]
end
othermdfiles = otherfiles.map {|file| "gfm/" + file.to_md}
otherhtmlfiles = otherfiles.map {|file| "html/" + file.to_html}
othertexfiles = otherfiles.map {|file| "latex/" + file.to_tex}
mdfiles = srcfiles.map {|file| "gfm/" + file.to_md}
htmlfiles = srcfiles.map {|file| "html/" + file.to_html}
sectexfiles = secfiles.map {|file| "latex/" + file.to_tex}
othertexfiles = otherfiles.map {|file| "latex/" + file.to_tex}
texfiles = srcfiles.map {|file| "latex/" + file.to_tex}
mdpathnames = srcfiles.map {|srcfile| "gfm/#{srcfile.to_md}"}
htmlpathnames = srcfiles.map {|srcfile| "html/#{srcfile.to_html}"}
texpathnames = srcfiles.map {|srcfile| "latex/#{srcfile.to_tex}"}
texfilenames = srcfiles.map {|srcfile| srcfile.to_tex}
["gfm", "html", "latex"].each do |d| ["gfm", "html", "latex"].each do |d|
if ! Dir.exist?(d) if ! Dir.exist?(d)
@ -23,7 +60,7 @@ texfilenames = srcfiles.map {|srcfile| srcfile.to_tex}
end end
end end
CLEAN.append(*mdpathnames) CLEAN.append(*mdfiles)
CLEAN << "Readme.md" CLEAN << "Readme.md"
# tasks # tasks
@ -31,61 +68,57 @@ CLEAN << "Readme.md"
task default: :md task default: :md
task all: [:md, :html, :pdf] task all: [:md, :html, :pdf]
task md: ["Readme.md", "src/turtle/turtle_doc.md"] task md: %w[Readme.md] + mdfiles
file "Readme.md" => mdpathnames+["src/abstract.src.md"] do file "Readme.md" => [abstract] + secfiles do
buf = [ "# Gtk4 Tutorial for beginners\n", "\n" ] buf = [ "# Gtk4 Tutorial for beginners\n", "\n" ]
src2md "src/abstract.src.md", "abstract.md" src2md abstract, abstract.to_md, file_table_src, "gfm"
buf += File.readlines("abstract.md") buf += File.readlines(abstract.to_md)
File.delete("abstract.md") File.delete(abstract.to_md)
buf.append("\n", "## Table of contents\n", "\n") buf.append("\n", "## Table of contents\n", "\n")
0.upto(srcfiles.size-1) do |i| 0.upto(secfiles.size-1) do |i|
h = File.open(srcfiles[i].path) { |file| file.readline } h = File.open(secfiles[i].path) { |file| file.readline }
h = h.gsub(/^#* */,"").chomp h = h.gsub(/^#* */,"").chomp
buf << "1. [#{h}](gfm/#{srcfiles[i].to_md})\n" buf << "1. [#{h}](gfm/#{secfiles[i].to_md})\n"
end end
File.write("Readme.md", buf.join) File.write("Readme.md", buf.join)
end end
0.upto(srcfiles.size - 1) do |i| file_table.each do |tbl|
file "gfm/#{srcfiles[i].to_md}" => (srcfiles[i].c_files << srcfiles[i].path) do file tbl[1] => tbl[0] do
src2md srcfiles[i].path, "gfm/#{srcfiles[i].to_md}" src2md tbl[0], tbl[1], file_table_src, "gfm"
if srcfiles.size == 1 if tbl[0].instance_of? Sec_file
nav = "Up: [Readme.md](../Readme.md)\n" i = tbl[0].num.to_i - 1
elsif i == 0 if secfiles.size == 1
nav = "Up: [Readme.md](../Readme.md), Next: [Section 2](#{srcfiles[1].to_md})\n" nav = "Up: [Readme.md](../Readme.md)\n"
elsif i == srcfiles.size - 1 elsif i == 0
nav = "Up: [Readme.md](../Readme.md), Prev: [Section #{i}](#{srcfiles[i-1].to_md})\n" nav = "Up: [Readme.md](../Readme.md), Next: [Section 2](#{secfiles[1].to_md})\n"
else elsif i == secfiles.size - 1
nav = "Up: [Readme.md](../Readme.md), Prev: [Section #{i}](#{srcfiles[i-1].to_md}), Next: [Section #{i+2}](#{srcfiles[i+1].to_md})\n" nav = "Up: [Readme.md](../Readme.md), Prev: [Section #{i}](#{secfiles[i-1].to_md})\n"
else
nav = "Up: [Readme.md](../Readme.md), Prev: [Section #{i}](#{secfiles[i-1].to_md}), Next: [Section #{i+2}](#{secfiles[i+1].to_md})\n"
end
buf = [nav, "\n"]
buf += File.readlines tbl[1]
buf.append("\n", nav)
File.write tbl[1], buf.join
end end
buf = File.readlines "gfm/#{srcfiles[i].to_md}"
buf.insert(0, nav, "\n")
buf.append("\n", nav)
File.write "gfm/#{srcfiles[i].to_md}", buf.join
end end
end end
file "src/turtle/turtle_doc.md" => "src/turtle/turtle_doc.src.md" do task html: ["html/index.html"] + htmlfiles
src2md "src/turtle/turtle_doc.src.md", "src/turtle/turtle_doc.md"
end
task html: ["html/index.html", "html/tfetextview_doc.html", "html/turtle_doc.html", "html/Readme_for_developers.html"] file "html/index.html" => [abstract] + secfiles do
file "html/index.html" => htmlpathnames+["src/abstract.src.md"] do
buf = [ "# Gtk4 Tutorial for beginners\n", "\n" ] buf = [ "# Gtk4 Tutorial for beginners\n", "\n" ]
src2md "src/abstract.src.md", "html/abstract.md" abstract_md = "html/#{abstract.to_md}"
buf += File.readlines("html/abstract.md") src2md abstract, abstract_md, file_table_src, "html"
File.delete("html/abstract.md") buf += File.readlines(abstract_md)
File.delete(abstract_md)
buf.append("\n", "## Table of contents\n", "\n") buf.append("\n", "## Table of contents\n", "\n")
0.upto(srcfiles.size-1) do |i| 0.upto(secfiles.size-1) do |i|
h = File.open(srcfiles[i].path) { |file| file.readline } h = File.open(secfiles[i].path) { |file| file.readline }
h = h.gsub(/^#* */,"").chomp h = h.gsub(/^#* */,"").chomp
buf << "1. [#{h}](#{srcfiles[i].to_html})\n" buf << "1. [#{h}](#{secfiles[i].to_html})\n"
end
buf.each do |line|
line.gsub!(/doc\/Readme_for_developers.md/,"html/Readme_for_developers.html")
line.gsub!(/(\[[^\]]*\])\((.+)\.md\)/,"\\1(\\2.html)")
end end
File.write("html/index.md", buf.join) File.write("html/index.md", buf.join)
sh "pandoc -o html/index.html html/index.md" sh "pandoc -o html/index.html html/index.md"
@ -93,47 +126,29 @@ file "html/index.html" => htmlpathnames+["src/abstract.src.md"] do
add_head_tail_html "html/index.html" add_head_tail_html "html/index.html"
end end
file "html/tfetextview_doc.html" => "src/tfetextview/tfetextview_doc.md" do file_table.each do |tbl|
sh "pandoc -o html/tfetextview_doc.html src/tfetextview/tfetextview_doc.md" file tbl[2] => tbl[0] do
add_head_tail_html "html/tfetextview_doc.html" html_md = "html/" + tbl[0].to_md
end src2md tbl[0], html_md, file_table_src, "html"
if tbl[0].instance_of? Sec_file
file "html/turtle_doc.html" => "src/turtle/turtle_doc.src.md" do i = tbl[0].num.to_i - 1 # 0 based index
src2md "src/turtle/turtle_doc.src.md", "html/turtle_doc.md" if secfiles.size == 1
sh "pandoc -o html/turtle_doc.html html/turtle_doc.md" nav = "Up: [index.html](index.html)\n"
File.delete "html/turtle_doc.md" elsif i == 0
add_head_tail_html "html/turtle_doc.html" nav = "Up: [index.html](index.html), Next: [Section 2](#{secfiles[1].to_html})\n"
end elsif i == secfiles.size - 1
nav = "Up: [index.html](index.html), Prev: [Section #{i}](#{secfiles[i-1].to_html})\n"
file "html/Readme_for_developers.html" => "doc/Readme_for_developers.md" do else
sh "pandoc -o html/Readme_for_developers.html doc/Readme_for_developers.md" nav = "Up: [index.html](index.html), Prev: [Section #{i}](#{secfiles[i-1].to_html}), Next: [Section #{i+2}](#{secfiles[i+1].to_html})\n"
add_head_tail_html "html/Readme_for_developers.html" end
end buf = [nav, "\n"]
buf += File.readlines html_md
0.upto(srcfiles.size - 1) do |i| buf.append("\n", nav)
html_md = "html/#{srcfiles[i].to_md}" File.write html_md, buf.join
html_html = "html/#{srcfiles[i].to_html}"
file html_html => (srcfiles[i].c_files << srcfiles[i].path) do
src2md srcfiles[i].path, html_md
if srcfiles.size == 1
nav = "Up: [index.html](index.html)\n"
elsif i == 0
nav = "Up: [index.html](index.html), Next: [Section 2](#{srcfiles[1].to_html})\n"
elsif i == srcfiles.size - 1
nav = "Up: [index.html](index.html), Prev: [Section #{i}](#{srcfiles[i-1].to_html})\n"
else
nav = "Up: [index.html](index.html), Prev: [Section #{i}](#{srcfiles[i-1].to_html}), Next: [Section #{i+2}](#{srcfiles[i+1].to_html})\n"
end end
buf = File.readlines html_md sh "pandoc -o #{tbl[2]} #{html_md}"
buf.insert(0, nav, "\n")
buf.append("\n", nav)
buf.each do |line|
line.gsub!(/(\[[^\]]*\])\((.+)\.md\)/,"\\1(\\2.html)")
end
File.write html_md, buf.join
sh "pandoc -o #{html_html} #{html_md}"
File.delete(html_md) File.delete(html_md)
add_head_tail_html html_html add_head_tail_html tbl[2]
end end
end end
@ -145,33 +160,24 @@ end
task latex: ["latex/main.tex"] task latex: ["latex/main.tex"]
file "latex/main.tex" => ["latex/abstract.tex", "latex/tfetextview_doc.tex", "latex/turtle_doc.tex"] + texpathnames do file "latex/main.tex" => ["latex/abstract.tex"]+texfiles do
gen_main_tex "latex", texfilenames, ["tfetextview_doc.tex", "turtle_doc.tex"] gen_main_tex "latex", sectexfiles, othertexfiles
end end
file "latex/abstract.tex" => "src/abstract.src.md" do abstract_tex = "latex/"+abstract.to_tex
src2md "src/abstract.src.md", "latex/abstract.md" file abstract_tex => abstract do
sh "pandoc --listings -o latex/abstract.tex latex/abstract.md" abstract_md = "latex/"+abstract.to_md
File.delete("latex/abstract.md") src2md abstract, abstract_md, file_table_src, "latex"
sh "pandoc --listings -o #{abstract_tex} #{abstract_md}"
File.delete(abstract_md)
end end
file "latex/tfetextview_doc.tex" => "src/tfetextview/tfetextview_doc.md" do file_table.each do |tbl|
sh "pandoc --listings -o latex/tfetextview_doc.tex src/tfetextview/tfetextview_doc.md" file tbl[3] => tbl[0] do
end tex_md = "latex/" + tbl[0].to_md
src2md tbl[0], tex_md, file_table_src, "latex"
file "latex/turtle_doc.tex" => "src/turtle/turtle_doc.src.md" do sh "pandoc --listings -o #{tbl[3]} #{tex_md}"
src2md "src/turtle/turtle_doc.src.md", "latex/turtle_doc.md" File.delete(tex_md)
sh "pandoc --listings -o latex/turtle_doc.tex latex/turtle_doc.md"
File.delete("latex/turtle_doc.md")
end
0.upto(srcfiles.size - 1) do |i|
latex_md = "latex/#{srcfiles[i].to_md}"
latex_tex = "latex/#{srcfiles[i].to_tex}"
file latex_tex => (srcfiles[i].c_files << srcfiles[i].path) do
src2md srcfiles[i].path, latex_md
sh "pandoc --listings -o #{latex_tex} #{latex_md}"
File.delete(latex_md)
end end
end end

View file

@ -20,7 +20,7 @@ The latest version of the tutorial is located at [Gtk4-tutorial github repositor
You can read it without download. You can read it without download.
If you want to get a html or pdf version, you can make them with `rake`, which is a ruby version of make. If you want to get a html or pdf version, you can make them with `rake`, which is a ruby version of make.
There is a documentation \("[How to build Gtk4 Tutorial](doc/Readme_for_developers.md)"\) that describes how to make them. There is a documentation \("[How to build Gtk4 Tutorial](gfm/Readme_for_developers.md)"\) that describes how to make them.
If you have a question, feel free to post it to the issue. If you have a question, feel free to post it to the issue.
Any question is helpful to make this tutorial get better. Any question is helpful to make this tutorial get better.

View file

@ -49,11 +49,9 @@ It is @@@ command.
The command starts with a line that begins with "@@@" and it ends with a line "@@@". The command starts with a line that begins with "@@@" and it ends with a line "@@@".
For example, For example,
~~~ @@@include
@@@include tfeapplication.c
tfeapplication.c @@@
@@@
~~~
There are four types of @@@ command. There are four types of @@@ command.
@ -61,29 +59,23 @@ There are four types of @@@ command.
This type of @@@ command starts with a line "@@@include". This type of @@@ command starts with a line "@@@include".
~~~ @@@include
@@@include tfeapplication.c
tfeapplication.c @@@
@@@
~~~
This command replaces itself with the text read from the C source files surrounded by `@@@include` and `@@@`. This command replaces itself with the text read from the C source files surrounded by `@@@include` and `@@@`.
If a function list follows the filename, only the functions are read. If a function list follows the filename, only the functions are read.
If no function list is given, the command can read any text file other than C source file. If no function list is given, the command can read any text file other than C source file.
~~~ @@@include
@@@include tfeapplication.c main startup
tfeapplication.c main startup @@@
@@@
~~~
The command above is replaced by the contents of `main` and `startup` functions in `tfeapplication.c`. The command above is replaced by the contents of `main` and `startup` functions in `tfeapplication.c`.
~~~ @@@include
@@@include lib_src2md.rb
lib_src2md.rb @@@
@@@
~~~
This command is replaced by the contents of `lib_src2md.rb` which is a ruby script (not C file). This command is replaced by the contents of `lib_src2md.rb` which is a ruby script (not C file).
@ -192,7 +184,7 @@ The markdwon above is converted to the following latex source file.
Listing package can color or emphasize keywords, strings, comments and directives. Listing package can color or emphasize keywords, strings, comments and directives.
But it doesn't analyze the syntax or token of the language, so the kind of emphasis target is limited. But it doesn't analyze the syntax or token of the language, so the kind of emphasis target is limited.
@@@include command have two advantages. @@@include command have two advantages.
1. Less typing. 1. Less typing.
2. You don't need to modify your src.md file, even if the C source file is modified. 2. You don't need to modify your src.md file, even if the C source file is modified.
@ -201,12 +193,10 @@ But it doesn't analyze the syntax or token of the language, so the kind of empha
This type of @@@ command starts with a line begins with "@@@shell". This type of @@@ command starts with a line begins with "@@@shell".
~~~ @@@shell
@@@shell shell command
shell command ... ...
... ... @@@
@@@
~~~
This command replaces itself with: This command replaces itself with:
@ -215,11 +205,9 @@ This command replaces itself with:
For example, For example,
~~~ @@@shell
@@@shell wc Rakefile
wc Rakefile @@@
@@@
~~~
This is converted to: This is converted to:
@ -234,15 +222,13 @@ This type of @@@ command starts with a line begins with "@@@if", "@@@elif", "@@@
This command is similar to "#if", "#elif", #else" and "#end" directives in C preprocessor. This command is similar to "#if", "#elif", #else" and "#end" directives in C preprocessor.
For example, For example,
~~~ @@@if gfm
@@@if gfm Refer to [tfetextview API reference](tfetextview/tfetextview_doc.src.md)
Refer to [tfetextview API reference](tfetextview/tfetextview_doc.md) @@@elif html
@@@elif html Refer to [tfetextview API reference](tfetextview/tfetextview_doc.src.html)
Refer to [tfetextview API reference](tfetextview_doc.html) @@@elif latex
@@@elif latex Refer to tfetextview API reference in appendix.
Refer to tfetextview API reference in appendix. @@@end
@@@end
~~~
`@@@if` and `@@@elif` have conditions. `@@@if` and `@@@elif` have conditions.
They are `gfm`, `html` or `latex` so far. They are `gfm`, `html` or `latex` so far.
@ -400,17 +386,17 @@ Navigation lines are added at the top and bottom of each markdown section file.
You can describe width and height of images in src.md files. You can describe width and height of images in src.md files.
For example, For example,
![sample image](../image/sample_image.png){width=10cm height=6cm} ![sample image](../image/sample_image.png)
The size between left brace and right brace is used in latex file and it is not fit to GFM syntax. The size between left brace and right brace is used in latex file and it is not fit to GFM syntax.
So the size is removed in the conversion. So the size is removed in the conversion.
If a src.md file has relative URL link, it will be changed by conversion. If a src.md file has relative URL link, it will be changed by conversion.
Because src.md files are located under `src` directory and GFM files are located under `gfm` directory, base URL of GFM files is different from base URL of src.md files. Because src.md files are located under `src` directory and GFM files are located under `gfm` directory, base URL of GFM files is different from base URL of src.md files.
For example, `[src/sample.c](sample.c)` is translated to `[src/sample.c](../src/sample.c)`. For example, `[src/sample.c](../src/sample.c)` is translated to `[src/sample.c](../src/sample.c)`.
If a link points another src.md file, then the target filename will be changed to .md file. If a link points another src.md file, then the target filename will be changed to .md file.
For example, `[Section 5](sec5.src.md)` is translated to `[Section 5](sec5.md)`. For example, `[Section 5](sec5.md)` is translated to `[Section 5](../src/sec5.md)`.
If you want to clean the directory, that means remove all the generated markdown files, type `rake clean`. If you want to clean the directory, that means remove all the generated markdown files, type `rake clean`.
@ -462,7 +448,7 @@ Links to files or directories are removed because latex doesn't support them.
However, links to full URL are kept. However, links to full URL are kept.
Image size is set with the size between the left brace and right brace. Image size is set with the size between the left brace and right brace.
![sample image](../image/sample_image.png){width=10cm height=6cm} ![sample image](../image/sample_image.png)
You need to specify appropriate width and height. You need to specify appropriate width and height.
It is almost `0.015 x pixels` cm. It is almost `0.015 x pixels` cm.

View file

@ -415,11 +415,11 @@ Otherwise, if the caller frees the GFile object, `tv->file` is no more guarantee
## API document and source file of tfetextview.c ## API document and source file of tfetextview.c
Refer [API document of TfeTextView](../src/tfetextview/tfetextview_doc.md). Refer [API document of TfeTextView](tfetextview/tfetextview_doc.src.md).
It is under the directory `src/tfetextview`. It is under the directory `src/tfetextview`.
All the source files are listed in [Section 15](sec15.md). All the source files are listed in [Section 15](sec15.md).
You can find them under [src/tfe5](../src/tfe5) and [src/tfetextview](../tfetextview) directories. You can find them under [src/tfe5](../src/tfe5) and [src/tfetextview](../src/tfetextview) directories.
Up: [Readme.md](../Readme.md), Prev: [Section 11](sec11.md), Next: [Section 13](sec13.md) Up: [Readme.md](../Readme.md), Prev: [Section 11](sec11.md), Next: [Section 13](sec13.md)

View file

@ -5,7 +5,7 @@ Up: [Readme.md](../Readme.md), Prev: [Section 14](sec14.md), Next: [Section 16]
## How to compile and execute tfe text editor. ## How to compile and execute tfe text editor.
First, source files are shown in the later subsections. First, source files are shown in the later subsections.
How to download them is written at the end of the [previous section](../src/sec14.src.md). How to download them is written at the end of the [previous section](sec14.md).
The following is the instruction of compilation and execution. The following is the instruction of compilation and execution.

View file

@ -18,7 +18,7 @@ So, readers can skip that part of this sections.
## How to use turtle ## How to use turtle
The documentation of turtle is [here](../src/turtle/turtle_doc.md). The documentation of turtle is [here](turtle_doc.md).
I'll show you a simple example. I'll show you a simple example.
~~~ ~~~
@ -529,7 +529,7 @@ FC '(' NUM ',' NUM ',' NUM ')';
You can find this is a primary_procedure easily. You can find this is a primary_procedure easily.
The parser of the turtle language analyzes the turtle source code in the same way. The parser of the turtle language analyzes the turtle source code in the same way.
The grammar of turtle is described in the [document](../src/turtle/turtle_doc.md). The grammar of turtle is described in the [document](turtle_doc.md).
The following is an extract from the document. The following is an extract from the document.
~~~ ~~~

203
gfm/tfetextview_doc.md Normal file
View file

@ -0,0 +1,203 @@
# TfeTextView API reference
TfeTextView -- Child widget of GtkTextView. It holds GFile the contents of GtkTextBuffer correponds to.
## Functions
- GFile *[tfe_text_view_get_file ()](../src/tfetextview/#tfe_text_view_get_file)
- void [tfe_text_view_open ()](../src/tfetextview/#tfe_text_view_open)
- void [tfe_text_view_save ()](../src/tfetextview/#tfe_text_view_save)
- void [tfe_text_view_saveas ()](../src/tfetextview/#tfe_text_view_saveas)
- GtkWidget *[tfe_text_view_new_with_file ()](../src/tfetextview/#tfe_text_view_new_with_file)
- GtkWidget *[tfe_text_view_new ()](../src/tfetextview/#tfe_text_view_new)
## Signals
- void [change-file](../src/tfetextview/#change-file)
- void [open-response](../src/tfetextview/#open-response)
## Types and Values
- [TfeTextView](../src/tfetextview/#tfetextview-1)
- [TfeTextViewClass](../src/tfetextview/#tfetextviewclass)
- [TfeTextViewOpenResponseType](../src/tfetextview/#enum-tfetextviewopenresponsetype)
## Object Hierarchy
~~~
GObject
+--GInitiallyUnowned
+--GtkWidget
+--GtkTextView
+--TfeTextView
~~~
## Includes
~~~
#include <gtk/gtk.h>
~~~
## Description
TfeTextView holds GFile the contents of GtkTextBuffer corresponds to.
File manipulation functions have been added to this object.
## Functions
### tfe_text_view_get_file()
~~~
GFile *
tfe_text_view_get_file (TfeTextView *tv);
~~~
Returns the copy of the GFile in the TfeTextView.
Parameters
- tv: a TfeTextView
### tfe_text_view_open()
~~~
void
tfe_text_view_open (TfeTextView *tv, GtkWidget *win);
~~~
Just shows a GtkFileChooserDialog so that a user can choose a file to read.
This function doesn't do any I/O operations.
They are done by the signal handler connected to the `response` signal emitted by GtkFileChooserDialog.
Therefore the caller can't know the I/O status directly from the function.
Instead, the status is informed by `open-response` signal.
The caller needs to set a handler to this signal in advance.
parameters
- tv: a TfeTextView
- win: the top level window
### tfe_text_view_save()
~~~
void
tfe_text_view_save (TfeTextView *tv);
~~~
Saves the content of a TfeTextView to a file.
If `tv` holds a GFile, it is used.
Otherwise, this function calls GtkFileChosserDialog so that a user can choose a file to save.
Parameters
- tv: a TfeTextView
### tfe_text_view_saveas()
~~~
void
tfe_text_view_saveas (TfeTextView *tv);
~~~
Saves the content of a TfeTextView to a file.
This function calls GtkFileChosserDialog so that a user can choose a file to save.
Parameters
- tv: a TfeTextView
### tfe_text_view_new_with_file()
~~~
GtkWidget *
tfe_text_view_new_with_file (GFile *file);
~~~
Creates a new TfeTextView and read the contents of the `file` and set it to the GtkTextBuffer corresponds to the newly created TfeTextView.
Then returns the TfeTextView as GtkWidget.
If I/O error happens, it returns `NULL`.
Parameters
- file: a GFile
Returns
- a new TfeTextView.
### tfe_text_view_new()
~~~
GtkWidget *
tfe_text_view_new (void);
~~~
Creates a new TfeTextView and returns the TfeTextView as GtkWidget.
Returns
- a new TfeTextView.
## Types and Values
### TfeTextView
~~~
typedef struct _TfeTextView TfeTextView
struct _TfeTextView
{
GtkTextView parent;
GFile *file;
};
~~~
The members of this structure are not allowed to be accessed by any outer objects.
If you want to obtain GFile, use `tfe_text_view_get_file`.
### TfeTextViewClass
~~~
typedef struct {
GtkTextViewClass parent_class;
} TfeTextViewClass;
~~~
No member is added because TfeTextView is a final type object.
### enum TfeTextViewOpenResponseType
Predefined values for the response id given by `open-response` signal.
Members:
- TFE_OPEN_RESPONSE_SUCCESS: The file is successfully opened.
- TFE_OPEN_RESPONSE_CANCEL: Reading file is canceled by the user.
- TFE_OPEN_RESPONSE_ERROR: An error happened during the opening or reading process.
## Signals
### change-file
~~~
void
user_function (TfeTextView *tv,
gpointer user_data)
~~~
Emitted when the GFile in the TfeTextView object is changed.
The signal is emitted when:
- a new file is opened and read
- a user choose a file with GtkFileChooserDialog and save the contents.
- an error occured during I/O operation, and GFile removed as a result.
### open-response
~~~
void
user_function (TfeTextView *tv,
TfeTextViewOpenResponseType response-id,
gpointer user_data)
~~~
Emitted after the user called `tfe_text_view_open`.
This signal informs the status of file opening and reading.

445
gfm/turtle_doc.md Normal file
View file

@ -0,0 +1,445 @@
# Turtle's manual
Turtle is a simple interpreter for turtle graphics.
## Prerequisite and compiling
Turtle is written in C language.
You need:
- Linux. Turtle is tested on ubuntu 20.10
- gcc, meson and ninja
- gtk4
It is easy to compile the source file of turtle.
If you have installed gtk4 with an option `--prefix=$HOME/local`, put the same option to meson so that you can install `turtle` under the directory `$HOME/local/bin`.
The instruction is:
~~~
$ meson --prefix=$HOME/local _build
$ ninja -C _build
$ ninja -C _build install
~~~
Type the following command then turtle shows the following window.
~~~
$ turtle
~~~
![Screenshot just after it's executed](../src/turtle/image/turtle1.png)
The left half is a text editor and the right half is a surface.
Surface is like a canvas to draw shapes.
Write turtle language in the text editor and click on `run` button, then the program will be executed and it draws shapes on the surface.
![Tree](../src/turtle/image/turtle_tree.png)
If you add the following line in `turtle.h`, then codes to inform the status will also be compiled.
However, the speed will be quite slow because of the output messages.
~~~
# define debug 1
~~~
## Example
Imagine a turtle.
The turtle has a pen and initially he is at the center of the screen, facing to the north (to the north means up on the screen).
You can let the turtle down the pen or up the pen.
You can order the turtle to move forward.
~~~
pd
fd 100
~~~
- pd: Pen Down. The turtle put the pen down so that the turtle will draw a line if he/she moves.
- fd 100: move ForwarD 100. The turtle goes forward 100 pixels.
If you click on `run` button, then a line segment appears on the screen.
One of the endpoints of the line segment is at the center of the surface and the other is at 100 pixels up from the center.
The point at the center is the start point of the turtle and the other endpoint is the end point of the movement.
If the turtle picks the pen up, then no line segment appears.
~~~
pu
fd 100
~~~
The command `pu` means "Pen Up".
The turtle can change the direction.
~~~
pd
fd 100
tr 90
fd 100
~~~
The command `tr` is "Turn Right".
The argument is angle with degrees.
Therefore, `tr 90` means "Turn right by 90 degrees".
If you click on `run`button, then two line segment appears.
One is vertical and the other is horizontal.
![Two line segments on the surface](../src/turtle/image/turtle2.png)
## Background and foreground color
Colors are specified by RGB.
A vector (r, g, b) denotes RGB color.
Each of the elements is a real number between 0 and 1.
- Red is (1.0, 0.0, 0.0).
You can write (1, 0, 0) instead.
- Green is (0.0, 1.0, 0.0)
- Blue is (0.0, 0.0, 1.0)
- Black is (0.0, 0.0, 0.0)
- White is (1.0, 1.0, 1.0)
You can express a variety of colors by changing each element.
There are two commands to change colors.
- bc: Background Color. `bc (1,0,0)` changes the background color to red.
This command clear the surface and change the background color.
So, the shapes on the surface disappears.
- fc: Foreground Color. `fc (0,1,0)` changes the foreground color to green.
This command changes the pen color.
The prior shapes on the surface aren't affected.
After this command, the turtle draws lines with the new color.
![Change the foreground color](../src/turtle/image/turtle3.png)
## Other simple commands
- pw: Pen Width. This is the same as pen size or line width.
For example, `pw 5` makes lines thick and `pw 1` makes it thin.
- rs: ReSet. The turtle moves back to the initial position and direction.
In addition, The command initialize the pen, line width (pen size), and foreground color.
The pen is down, the line width is 2 and the foreground color is black.
An order such as `fd 100`, `pd` and so on is a statement.
Statements are executed in the order from the top to the end
## Comment and spaces
Characters between `#` (hash mark) and `\n` (new line) inclusive are comment.
Characters between `#` and `EOF` (end of file) are also comment.
Comments are ignored.
~~~
# draw a triangle
fd 100 # forward 100 pixels<NEW LINE>
tr 120 # turn right by 90 degrees<NEW LINE>
fd 100<NEW LINE>
tr 120<NEW LINE>
fd 100 # Now a triangle appears.<EOF>
~~~
\<NEW LINE\> and \<EOF\> are newline code and end of file respectively.
The comments in the line 1, 2, 3 and 6 are correct syntactically.
Spaces (white space, tab and new line) are ignored.
They are used only as delimiters.
Tabs are recognized as eight spaces to calculate the column number.
## Variables and expressions
Variable begins alphabet followed by alphabet or digit except key words like `fd`, `tr` and so on.
`Distance` and `angle5` can be variables, but `1step` isn't a variable because the first character isn't alphabet.
Variable names are case sensitive.
Variables keep real numbers.
Their type is the same as `double` in C language.
Integers are casted to real numbers automatically.
So 1 and 1.0 are the same value.
Numbers begins digits, not signs (`+` or `-`).
- 100, 20.34 and 0.01 are numbers
- +100 isn't a number. It causes syntax error. Use 100 instead.
- -100 isn't a number. But turtle recognizes it unary minus and a number 100.
So turtle calculate it and the result is -100.
- 100 + -20: This is recognized 100 + (- 20).
However, using bracket, 100 + (-20), is better for easy reading.
~~~
distance = 100
fd distance
~~~
A value 100 is assigned to the variable `distance` in the first line.
Assignment is a statement.
Most of statements begin with commands like `fd`.
Assignment is the only exception.
This program draws a line segment of 100 pixels long.
You can use variables in any places in expressions.
There are 8 kinds of calculations available.
- addition: x + y
- subtraction: x - y
- multiplication: x * y
- division: x / y
- unary minus: - x
- logical equal: x = y. This symbol `=` works as `==` in C language.
- greater than: x > y
- less than: x < y
The last three symbols are mainly used in the condition of if statement.
Variables are registered to a symbol table when it is assigned a value for the first time.
Evaluating a variable before the registration isn't allowed and occurs an error.
## If statement
Turtle language has very simple if statement.
~~~
if (x > 50) {
fd x
}
~~~
There is no else part.
## Procedures
Procedures are similar to functions in C language.
The difference is that procedures don't have return values.
~~~
dp triangle (side) {
fd side
tr 120
fd side
tr 120
fd side
}
triangle (100)
~~~
`dp` (Define Procedure) is a key word followed by procedure name, parameters, and body.
Procedure names start alphabet followed by alphabet or digit.
Parameters are a list of variables.
For example
~~~
dp abc (a) { ... ... }
dp abc (a, b) { ... ... }
dp abc (a, b, c) { ... ... }
~~~
Body is a sequence of statements.
The statements aren't executed when the procedure is defined.
They will be executed when the procedure is called later.
Procedures are called by the name followed by arguments.
~~~
dp proc (a, b, c) { ... ... }
proc (100, 0, -20*3)
~~~
The number of parameters and arguments must be the same.
Arguments can be any expressions.
When you call a procedure, brackets following the procedure name must exist even if the procedure has no argument.
Procedure names and variable names don't conflict.
~~~
dp a () {fd a}
a=100
a ()
~~~
This is a correct program.
- 1: Defines a procedure `a`.
A variable `a` is in its body.
- 2: Assigns 100 to a variable `a`.
- 3: Procedure `a` is called.
However, using the same name to a procedure and variable makes confusing.
You should avoid that.
## Recursive call
Procedures can be called recursively.
~~~
dp repeat (n) {
n = n - 1
if (n < 0) {
rt
}
fd 100
tr 90
repeat (n)
}
repeat (4)
~~~
Repeat is called in the body of repeat.
The call to itself is a recursive call.
Parameters are generated each time the procedure is called.
So, parameter `n` is 4 at the first call but it is 3 at the second call.
Each time the procedure is called, the parameter `n` decreases by one.
Finally, it becomes less than zero, then the procedures return.
The program above draws a square.
Turtle doesn't have any primary loop statements.
It should probably be added to the future version.
However, the program above shows that we can program loop with a recursive call.
## Fractal curves
Recursive call can be applied to draw fractal curves.
Fractal curves appear when a procedure is applied to it repeatedly.
The procedure replaces a part of the curve with the contracted curve.
![Tree](../src/turtle/image/turtle_tree.png)
This shape is called tree.
The basic pattern of this shape is a line segment.
It is the first stage.
The second stage adds two shorter line segments at the endpoint of the original segment.
The new segment has 70 percent length to the original segment and the orientation is +30 or -30 degrees different.
The third stage adds two shorter line segments to the second stage line segments.
And repeats this several times.
This repeating is programmed by recursive call.
Two more examples are shown here.
They are Koch curve and Square Koch curve.
![Koch curve](../src/turtle/image/turtle_koch.png)
![Square Koch curve](../src/turtle/image/turtle_square_koch.png)
## Tokens and punctuations
The following is the list of tokens.
Keywords:
- pu: pen up
- pd: pen down
- pw: pen width = line width
- fd: forward
- tr: turn right
- bc: background color
- fc: foreground color
- if: if statement
- rt: return
- rs: reset
- dp: define procedure
identifiers and numbers:
- identifier: This is used for the name of variables, parameters and procedures.
It is expressed ` [a-zA-Z][a-zA-Z0-9]*` by regular expression.
- number: This is expressed `(0|[1-9][0-9]*)(\.[0-9]+)?` by regular expression.
It doesn't have `+` or `-` sign because they bring some syntactic confusion.
However negative number such as `-10` can be recognized as unary minus and a number.
Symbols for expression
- `=`
- `>`
- `<`
- `+`
- `-`
- `*`
- `/`
- `(`
- `)`
Delimiters
- `(`
- `)`
- `{`
- `}`
- `,`
Comments and spaces:
- comment: This is characters between `#` and new line inclusive.
- white space:
- horizontal tab: tab is recognized as eight spaces.
- new line: This is the end of a line and denoted by '\\n'.
These characters are used to separate tokens explicitly.
They doesn't have any syntactic meaning and are ignored by the parser.
## Grammar
~~~
program:
statement
| program statement
;
statement:
primary_procedure
| procedure_definition
;
primary_procedure:
PU
| PD
| PW expression
| FD expression
| TR expression
| BC '(' expression ',' expression ',' expression ')'
| FC '(' expression ',' expression ',' expression ')'
| ID '=' expression
| IF '(' expression ')' '{' primary_procedure_list '}'
| RT
| RS
| ID '(' ')'
| ID '(' argument_list ')'
;
procedure_definition:
DP ID '(' ')' '{' primary_procedure_list '}'
| DP ID '(' parameter_list ')' '{' primary_procedure_list '}'
;
parameter_list:
ID
| parameter_list ',' ID
;
argument_list:
expression
| argument_list ',' expression
;
primary_procedure_list:
primary_procedure
| primary_procedure_list primary_procedure
;
expression:
expression '=' expression
| expression '>' expression
| expression '<' expression
| expression '+' expression
| expression '-' expression
| expression '*' expression
| expression '/' expression
| '-' expression %prec UMINUS
| '(' expression ')'
| ID
| NUM
;
~~~

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View file

@ -2,7 +2,7 @@
require 'pathname' require 'pathname'
# The method 'src2md' converts .src.md file into .md file. # The method 'src2md' converts .src.md file into .md file.
# The outputed .md file is fit for the final format, which is one of markdown, html and latex. # The .md file is the final format for GFM, or intermediate markdown file for html and/or latex.
# - Links to relative URL are removed for latex. Otherwise, it remains. # - Links to relative URL are removed for latex. Otherwise, it remains.
# See "Hyperref and relative link" below for further explanation. # See "Hyperref and relative link" below for further explanation.
# - Width and height for images are removed for markdown and html. it remains for latex. # - Width and height for images are removed for markdown and html. it remains for latex.
@ -19,7 +19,7 @@ require 'pathname'
# (sec13.tex) # (sec13.tex)
# \hypertarget{tfeapplication.c}{% # \hypertarget{tfeapplication.c}{%
# \section{tfeapplication.c}\label{tfeapplication.c}} # \section{tfeapplication.c}\label{tfeapplication.c}}
# If you click the text 'Section 13' in sec11.tex, then you can move to '13 tfeapplication.c' ("13 " is automatically added by latex), which is section 13 in sec13.tex. # If you click on the text 'Section 13' in sec11.tex, then you will move to 'tfeapplication.c' in sec13.tex.
# The following lines are the original one in sec11.md and the result in sec11.tex, which is generated by pandoc. # The following lines are the original one in sec11.md and the result in sec11.tex, which is generated by pandoc.
# (sec11.md) # (sec11.md)
@ -38,7 +38,7 @@ require 'pathname'
# The pdf file generated by lualatex recognizes that the link 'href{../src/tfe}' points a pdf file '../src/tfe.pdf'. # The pdf file generated by lualatex recognizes that the link 'href{../src/tfe}' points a pdf file '../src/tfe.pdf'.
# To avoid generating such incorrect links, it is good to remove the links from the original markdown file. # To avoid generating such incorrect links, it is good to remove the links from the original markdown file.
# If the target is full URL, which means absolute URL begins with "http", no problem happens. # If the target is full URL, which means absolute URL begins with "http(s)", no problem happens.
# This script just remove the links if its target is relative URL if the target is latex. # This script just remove the links if its target is relative URL if the target is latex.
# If you want to revive the link with relative URL, refer the description above. # If you want to revive the link with relative URL, refer the description above.
@ -71,7 +71,13 @@ require 'pathname'
# Listings package supports only C, ruby, xml and make. # Listings package supports only C, ruby, xml and make.
# Bison, lex, markdown and meson aren't supported. # Bison, lex, markdown and meson aren't supported.
def src2md srcmd, md, type="gfm" # file_table contains paths of source, GFM, html and latex.
# It is possible to get the relationship between source file and created GFM/html/latex file.
# type is "gfm", "html" or "latex".
# Caller can specify the target type.
def src2md srcmd, md, file_table=nil, type="gfm"
# parameters: # parameters:
# srcmd: .src.md file's path. source # srcmd: .src.md file's path. source
# md: .md file's path. destination # md: .md file's path. destination
@ -237,7 +243,7 @@ def src2md srcmd, md, type="gfm"
md_buf << "~~~\n" md_buf << "~~~\n"
shell_flag = true shell_flag = true
else else
line = change_rel_link(line, src_dir, md_dir) line = change_rel_link(line, src_dir, md_dir, file_table, type)
if type == "latex" # remove relative link if type == "latex" # remove relative link
if ! (line =~ /\[[^\]]*\]\(http[^)]*\)/) if ! (line =~ /\[[^\]]*\]\(http[^)]*\)/)
line.gsub!(/^([^!]*)\[([^\]]*)\]\([^\)]*\)/,"\\1\\2") line.gsub!(/^([^!]*)\[([^\]]*)\]\([^\)]*\)/,"\\1\\2")
@ -252,7 +258,9 @@ def src2md srcmd, md, type="gfm"
end end
# Change the base of relative links from org_dir to new_dir # Change the base of relative links from org_dir to new_dir
def change_rel_link line, org_dir, new_dir def change_rel_link line, org_dir, new_dir, file_table=nil, type="gfm"
i = [nil, "gfm", "html", "latex"].find_index(type)
raise "Illegal type (#{type}).\n" unless i == 1 || i == 2 || i == 3
p_new_dir = Pathname.new new_dir p_new_dir = Pathname.new new_dir
left = "" left = ""
right = line right = line
@ -261,9 +269,15 @@ def change_rel_link line, org_dir, new_dir
right = $' right = $'
name = $1 name = $1
link = $2 link = $2
if name =~ /\[(S|s)ection (\d+)\]/ if file_table
link = "sec#{$2}.md" file_table.each do |tbl|
elsif ! (link =~ /^(http|\/)/) if tbl[0] == link
link = tbl[i]
break
end
end
end
if ! (link =~ /^(http|\/)/)
p_link = Pathname.new "#{org_dir}/#{link}" p_link = Pathname.new "#{org_dir}/#{link}"
link = p_link.relative_path_from(p_new_dir).to_s link = p_link.relative_path_from(p_new_dir).to_s
end end

View file

@ -1,15 +1,15 @@
class Sec_file < String class Src_file <String
def initialize path def initialize path
unless path.instance_of?(String) unless path.instance_of?(String)
raise "Sec_file class initialization error: The argument is not String type." raise "Src_file class initialization error: The argument is not String type."
end end
unless File.exist?(path) unless File.exist?(path)
raise "Sec_file class initialization error: File #{path} is not exist." raise "Src_file class initialization error: File #{path} is not exist."
end end
unless path =~ /sec\d+(\.\d+)?\.src\.md$/ unless path =~ /\.src\.md$/
raise "Sec_file class initialization error: The argment \"#{path}\" doesn't have secXX.src.md form. XX are digits." raise "Src_file class initialization error: The argment \"#{path}\" doesn't have .src.md suffix."
end end
@name = File.basename path @name = File.basename path, ".src.md"
@dirname = File.dirname path @dirname = File.dirname path
super(path) super(path)
end end
@ -17,11 +17,29 @@ class Sec_file < String
self self
end end
def basename def basename
@name @name+".src.md"
end end
def dirname def dirname
@dirname @dirname
end end
def to_md
@name+".md"
end
def to_html
@name+".html"
end
def to_tex
@name+".tex"
end
end
class Sec_file < Src_file
def initialize path
unless path =~ /sec\d+(\.\d+)?\.src\.md$/
raise "Sec_file class initialization error: The argment \"#{path}\" doesn't have secXX.src.md form. XX is int or float."
end
super(path)
end
def c_files def c_files
buf = IO.readlines(self) buf = IO.readlines(self)
files = [] files = []
@ -41,15 +59,6 @@ class Sec_file < String
end end
files files
end end
def to_md
@name.gsub(/\.(src\.md|md|html|tex)$/, ".md")
end
def to_html
@name.gsub(/\.(src\.md|md|html|tex)$/, ".html")
end
def to_tex
@name.gsub(/\.(src\.md|md|html|tex)$/, ".tex")
end
def num # the return value is String def num # the return value is String
@name.match(/\d+(\.\d+)?/)[0] @name.match(/\d+(\.\d+)?/)[0]
end end
@ -80,7 +89,7 @@ class Sec_file < String
if old != new if old != new
File.rename old, new File.rename old, new
self.replace new self.replace new
@name = File.basename new @name = File.basename new, ".src.md"
@dirname = File.dirname new @dirname = File.dirname new
end end
end end

View file

@ -0,0 +1,476 @@
# How to build Gtk4 Tutorial
## Quick start guide
1. You need linux operationg system, ruby, rake, pandoc and latex system.
2. download this repository and uncompress the files.
3. change your current directory to the top directory of the source files.
4. type `rake html` to create html files. The files are generated under `html` directory.
5. type `rake pdf` to create pdf file. The file is generated under `latex` directory.
## Prerequisites
- Linux operationg system.
The programs in the repository has been tested on Ubuntu 20.04.
- Download the files in this repository.
There are two ways to download.
1. Use git.
Type `git clone https://github.com/ToshioCP/Gtk4-tutorial.git` on the command-line.
2. Download a zip file.
Click on the code button (green button) in the top page of this repository.
Then, click "Download ZIP".
- Ruby and rake.
- Pandoc. It is used to generate html and latex files.
- Latex system. Texlive2020 or later version is recommended.
It is used to generate pdf file.
## Github flavored markdown
When you see [gtk4_tutorial github page](https://github.com/ToshioCP/Gtk4-tutorial), you'll find `Readme.md` contents below the list of files.
This file is written in markdown language.
A markdown file has `.md` suffix.
There are several kinds of markdown language.
`Readme.md` uses 'github flavored markdown', which is often shortened as GFM.
Markdown files in the gfm directory also written in GFM.
If you are not familiar with it, refer to the page [github flavor markdown spec](https://github.github.com/gfm/).
## Pandoc's markdown
This tutorial also uses another markdown -- pandoc's markdown.
Pandoc is a converter between markdown, html, latex, word docx and so on.
This type of markdown is used to convert markdown to html and latex in this tutorial.
## Src.md file
Src.md file has ".src.md" suffix.
The syntax of src.md file is similar to markdown but it has a special command which isn't included in markdown syntax.
It is @@@ command.
The command starts with a line that begins with "@@@" and it ends with a line "@@@".
For example,
@@@include
tfeapplication.c
@@@
There are four types of @@@ command.
### @@@include
This type of @@@ command starts with a line "@@@include".
@@@include
tfeapplication.c
@@@
This command replaces itself with the text read from the C source files surrounded by `@@@include` and `@@@`.
If a function list follows the filename, only the functions are read.
If no function list is given, the command can read any text file other than C source file.
@@@include
tfeapplication.c main startup
@@@
The command above is replaced by the contents of `main` and `startup` functions in `tfeapplication.c`.
@@@include
lib_src2md.rb
@@@
This command is replaced by the contents of `lib_src2md.rb` which is a ruby script (not C file).
The inserted text is converted to fence code block.
Fence code block begins with `~~~` and ends with `~~~`.
The contents are displayed verbatim.
`~~~` is look like a fence so the block is called "fence code block".
If the target markdown is GFM, then an info string follows the beginning fence.
The following example shows that the @@@ command includes a C source file `sample.c`.
$ cat src/sample.c
int
main (int argc, char **argv) {
... ...
}
$cat src/sample.src.md
... ...
@@@include -N
sample.c
@@@
... ...
$ ruby src2md.rb src/sample.src.md gfm/sample.md
$ cat gfm/sample.md
... ...
~~~C
int
main (int argc, char **argv) {
... ...
}
~~~
... ...
Info strings are usually languages like C, ruby, xml and so on.
This string is decided with the filename extension.
- `.c` => C
- `.rb` => ruby
- `.xml` => xml
The supported language is written in line 274 and 275 in `lib/lib_src2md.rb`.
A line number is inserted at the top of each line in the code block.
If you don't want to insert it, give "-N" option to @@@include command.
Options:
- `-n`: Inserts a line number at the top of each line (default).
- `-N`: No line number is inserted.
The following shows that line numbers are inserted at the beginning of lines.
$cat src/sample.src.md
... ...
@@@include
sample.c
@@@
... ...
$ ruby src2md.rb src/sample.src.md gfm/sample.md
$ cat gfm/sample.md
... ...
~~~C
1 int
2 main (int argc, char **argv) {
... ...
14 }
~~~
... ...
If the target markdown is an intermediate file to html, then another type of info string follows the beginning fence.
If @@@include command doesn't have -N option, then the generated markdown is:
~~~{.C .numberLines}
int
main (int argc, char **argv) {
... ...
}
~~~
The info string `.C` specifies C language.
The info string `.numberLines` is a class of the pandoc markdown.
If the class is given, pandoc generates CSS to insert line numbers to the source code in the html file.
That's why the fence code block in the markdown doesn't have line numbers, which is different from gfm markdown.
If `-N` option is given, then the info string is `{.C}` only.
If the target markdown is an intermediate file to latex, then the same info string follows the beginning fence.
~~~{.C .numberLines}
int
main (int argc, char **argv) {
... ...
}
~~~
Rake uses pandoc with --listings option when it converts markdown to latex.
The generated latex file uses listings package to list source files instead of verbatim environment.
The markdwon above is converted to the following latex source file.
\begin{lstlisting}[language=C, numbers=left]
int
main (int argc, char **argv) {
... ...
}
\end{lstlisting}
Listing package can color or emphasize keywords, strings, comments and directives.
But it doesn't analyze the syntax or token of the language, so the kind of emphasis target is limited.
@@@include command have two advantages.
1. Less typing.
2. You don't need to modify your src.md file, even if the C source file is modified.
### @@@shell
This type of @@@ command starts with a line begins with "@@@shell".
@@@shell
shell command
... ...
@@@
This command replaces itself with:
- the shell command
- the standard output from the shell command
For example,
@@@shell
wc Rakefile
@@@
This is converted to:
~~~
$ wc Rakefile
164 475 4971 Rakefile
~~~
### @@@if series
This type of @@@ command starts with a line begins with "@@@if", "@@@elif", "@@@else" or "@@@end".
This command is similar to "#if", "#elif", #else" and "#end" directives in C preprocessor.
For example,
@@@if gfm
Refer to [tfetextview API reference](tfetextview/tfetextview_doc.md)
@@@elif html
Refer to [tfetextview API reference](tfetextview_doc.html)
@@@elif latex
Refer to tfetextview API reference in appendix.
@@@end
`@@@if` and `@@@elif` have conditions.
They are `gfm`, `html` or `latex` so far.
- gfm: builds a GFM file
- html: builds a html file
- latex: builds a latex file or pdf file.
Other type of conditions may be available in the future version.
## Conversion
The @@@ commands above (@@@include, @@@shell and @@@if series) are carried out by `src2md.rb`.
In addition, some other conversions are made by `src2md.rb`.
- Relative links are changed according to the change of the base directory.
- Size option in image link is removed when the destination is GFM or html.
- Relative link is removed when the destination is latex.
- Lines in fence code block are folded when the destination is latex.
There's a method `src2md` in the `lib/lib_src2md.rb`.
This method converts src.md file into md file.
The script `src2md.rb` just invokes this method.
In the same way, the method is called in the action in `Rakefile`.
The code analyzing @@@if series command is rather complicated.
It is based on the state diagram below.
![state diagram](../image/state_diagram.png)
## mktbl.rb script
The fourth @@@ command begins with "@@@table".
The contents of this command is a table of GFM or pandoc's markdown.
The script `mktbl.rb` in `src` directory makes a table easy to read.
For example, a text file `sample.md` has a table like this:
Price list
@@@table
|item|price|
|:---:|:---:|
|mouse|$10|
|PC|$500|
@@@
Run the script.
~~~
$ cd src
$ ruby mktbl.rb sample.md
~~~
Then, the file is changed to:
~~~
Price list
|item |price|
|:---:|:---:|
|mouse| $10 |
| PC |$500 |
~~~
The script makes a backup file `sample.md.bak`.
The task of the script seems easy, but the program is not so simple.
The script `mktbl.rb` uses a library `lib/lib_mktbl.rb`
This script is independent from `src2md.rb`.
## Directory structure
There are seven directories under `gtk4_tutorial` directory.
They are `gfm`, `src`, `image`, `html`, `latex`, `doc` and `lib`.
Three directories `gfm`, `html` and `latex` are the destination directories for GFM, html and latex files respectively.
It is possible that these three directories don't exist before the conversion.
- src: This directory contains src.md files and C-related source files.
- image: This directory contains image files like png or jpg.
- gfm: `rake` converts src.md files to GFM files and store them in this directory.
- html: This directory is empty at first. `rake html` will convert src.md files to html files and store them in this directory.
- latex: This directory is empty at first. `rake latex` will convert src.md files to latex files and store them in this directory.
`rake pdf` creates pdf file in `latex` directory.
- doc: This directory contains `Readme_for_developers.md` (this file).
- lib: This directory includes ruby library files.
## Src directory and the top directory
Src directory contains src.md files and C-related source files.
The top directory, which is gtk\_tutorial directory, contains `Rakefile`, `src2md.rb` and some other files.
When `Readme.md` is generated, it will be located at the top directory.
`Readme.md` has title, abstract, table of contents and links to GFM files under `gfm` directory.
Rakefile describes how to convert src.md files into GFM files.
Rake carries out the conversion according to the `Rakefile`.
## The name of files in src directory
Each file in `src` directory is an abstract or section of the whole document.
A `abstract.src.md` contains the abstract of this tutorial.
Each section filename is "sec", number of the section and ".src.md" suffix.
For example, "sec1.src.md", "sec5.src.md" or "sec12.src.md".
They are the files correspond to section 1, section 5 and section 12 respectively.
## C source file directory
Most of Src.md files have `@@@include` commands and they include C source files.
Such C source files are located in the subdirectories of `src` directory.
Those C files have been compiled and tested.
When you compile source files, some auxiliary files and a target file like `a.out` are created.
Or `_build` directory is made when `meson` and `ninja` is used when compiling.
Those files are not tracked by `git` because they are specified in `.gitignore`.
The name of the subdirectories should be independent of section names.
It is because of renumbering, which will be explained in the next subsection.
## Renumbering
Sometimes you might want to insert a section.
For example, you want to insert it between section 4 and section 5.
You can make a temporary section 4.5, that is a rational number between 4 and 5.
However, section numbers are usually integer so section 4.5 must be changed to section 5.
And the numbers of the following sections must be increased by one.
This renumbering is done by a method `renum` of the class `Sec_files`.
The method and class is written in `lib/lib_sec_file.rb`.
- It changes file names.
- If there are references to sections in src.md files, the section numbers will be automatically renumbered.
## Rakefile
Rakefile is a similar file to Makefile but controlled by rake, which is a make-like program written in ruby.
Rakefile in this tutorial has the following tasks.
- md: generate GFM markdown files. This is the default.
- html: generate html files.
- pdf: generate latex files and a pdf file, which is compiled by lualatex.
- latex: generate latex files.
- all: generate md, html, latex and pdf files.
Rake does renumbering before the tasks above.
## Generate GFM markdown files
Markdown files (GFM) are generated by rake.
$ rake
This command generates `Readme.md` with `src/abstract.src.md` and titles of src.md files.
At the same time, it converts each src.md file into GFM file under `gfm` directory.
Navigation lines are added at the top and bottom of each markdown section file.
You can describe width and height of images in src.md files.
For example,
![sample image](../image/sample_image.png){width=10cm height=6cm}
The size between left brace and right brace is used in latex file and it is not fit to GFM syntax.
So the size is removed in the conversion.
If a src.md file has relative URL link, it will be changed by conversion.
Because src.md files are located under `src` directory and GFM files are located under `gfm` directory, base URL of GFM files is different from base URL of src.md files.
For example, `[src/sample.c](sample.c)` is translated to `[src/sample.c](../src/sample.c)`.
If a link points another src.md file, then the target filename will be changed to .md file.
For example, `[Section 5](sec5.src.md)` is translated to `[Section 5](sec5.md)`.
If you want to clean the directory, that means remove all the generated markdown files, type `rake clean`.
$ rake clean
If you see the github repository (ToshioCP/Gtk4-tutorial), `Readme.md` is shown below the code.
And `Readme.md` includes links to each markdown files.
The repository not only stores source files but also shows the whole tutorial.
## Generate html files
Src.md files can be translated to html files.
You need pandoc to do this.
Most linux distribution has pandoc package.
Refer to your distribution document to install it.
Type `rake html` to generate html files.
$ rake html
First, it generates pandoc's markdown files under `html` directory.
Then, pandoc converts them to html files.
The width and height of image files are removed.
`index.html` is the top html file.
If you want to clean `html` directory, type `rake cleanhtml`
$ rake cleanhtml
Every html file has stylesheet in its header.
This is created by `lib/lib_add_head_tail_html.rb`.
This script has a sample markdown code and convert it with pandoc and `-s` option.
Pandoc generates a html file with header.
The script extracts the header and use it for html files.
You can customize the style by modifying `lib/lib_add_head_tail_html.rb`.
## Generate latex files and a pdf file
Src.md files can be translated to latex files.
You need pandoc to do this.
Type `rake latex` to generate latex files.
$ rake latex
First, it generates pandoc's markdown files under `latex` directory.
Then, pandoc converts them to latex files.
Links to files or directories are removed because latex doesn't support them.
However, links to full URL are kept.
Image size is set with the size between the left brace and right brace.
![sample image](../image/sample_image.png){width=10cm height=6cm}
You need to specify appropriate width and height.
It is almost `0.015 x pixels` cm.
For example, if the width of an image is 400 pixels, the width in a latex file will be almost 6cm.
`main.tex` is the top latex file.
If you want to clean `latex` directory, type `rake cleanlatex`
$ rake cleanlatex
`main.tex` is a root file and it includes each section file between `\begin{document}` and `\end{document}`.
`main.tex` also includes `helper.tex` in its preamble.
`main.tex` and `helper.tex` is created by `lib/lib_gen_main_tex.rb`.
It has a sample markdown code and convert it witn pandoc and `-s` option.
Pandoc generates preamble.
`lib/lib_gen_main_tx.rb` extracts the preamble and put a part of it into `helper.tex`.
You can customize `helper.tex` by modifying `lib/lib_gen_main_tex.rb`.
You can generate pdf file by typing `rake pdf`.
$ rake pdf
This does `rake latex` first.
After that the latex files are compiled by lualatex.

View file

@ -18,7 +18,13 @@ The latest version of the tutorial is located at [Gtk4-tutorial github repositor
You can read it without download. You can read it without download.
If you want to get a html or pdf version, you can make them with `rake`, which is a ruby version of make. If you want to get a html or pdf version, you can make them with `rake`, which is a ruby version of make.
There is a documentation \("[How to build Gtk4 Tutorial](../doc/Readme_for_developers.md)"\) that describes how to make them. @@@if gfm
There is a documentation \("[How to build Gtk4 Tutorial](Readme_for_developers.src.md)"\) that describes how to make them.
@@@elif html
There is a documentation \("[How to build Gtk4 Tutorial](Readme_for_developers.src.md)"\) that describes how to make them.
@@@elif latex
An appendix "How to build Gtk4 Tutorial" describes how to make them.
@@@end
If you have a question, feel free to post it to the issue. If you have a question, feel free to post it to the issue.
Any question is helpful to make this tutorial get better. Any question is helpful to make this tutorial get better.

View file

@ -232,5 +232,5 @@ Its original markdown file is under the directory `src/tfetextview`.
@@@end @@@end
All the source files are listed in [Section 15](sec15.src.md). All the source files are listed in [Section 15](sec15.src.md).
You can find them under [src/tfe5](tfe5) and [src/tfetextview](../tfetextview) directories. You can find them under [src/tfe5](tfe5) and [src/tfetextview](tfetextview) directories.

View file

@ -17,7 +17,7 @@ So, readers can skip that part of this sections.
## How to use turtle ## How to use turtle
@@@if gfm @@@if gfm
The documentation of turtle is [here](turtle/turtle_doc.md). The documentation of turtle is [here](turtle/turtle_doc.src.md).
@@@elif html @@@elif html
The documentation of turtle is [here](../html/turtle_doc.html). The documentation of turtle is [here](../html/turtle_doc.html).
@@@if latex @@@if latex
@ -407,7 +407,7 @@ FC '(' NUM ',' NUM ',' NUM ')';
You can find this is a primary_procedure easily. You can find this is a primary_procedure easily.
The parser of the turtle language analyzes the turtle source code in the same way. The parser of the turtle language analyzes the turtle source code in the same way.
The grammar of turtle is described in the [document](turtle/turtle_doc.md). The grammar of turtle is described in the [document](turtle/turtle_doc.src.md).
The following is an extract from the document. The following is an extract from the document.
~~~ ~~~

View file

@ -467,12 +467,13 @@ files.each do |f|
end end
# --- test change_rel_link # --- test change_rel_link
file_table = [["sec3.src.md", "../gfm/sec3.md", "../html/sec3.html", "../latex/sec3.html"]]
# general relative link # general relative link
s = "[sample.c](temp/sample.c)" s = "[sample.c](temp/sample.c)"
t = change_rel_link s, "test", "gfm" t = change_rel_link s, "test", "gfm"
if t != "[sample.c](../test/temp/sample.c)" if t != "[sample.c](../test/temp/sample.c)"
print "Relative link change according to base directory change didn't work.\n" print "Relative link change according to base directory change didn't work.\n"
print " Base directory test => gtm\n" print " Base directory test => gfm\n"
print " Original link => #{s}\n" print " Original link => #{s}\n"
print " Relative link temp/sample.c => #{t}\n" print " Relative link temp/sample.c => #{t}\n"
print " ** Correct new link must be [sample.c](../test/temp/sample.c) **\n" print " ** Correct new link must be [sample.c](../test/temp/sample.c) **\n"
@ -481,13 +482,13 @@ end
# srcdir/secXX.src.md is converted to dstdir/secXX.md. # srcdir/secXX.src.md is converted to dstdir/secXX.md.
# Therefore, secXX.src.md must be changed tp secXX.md. # Therefore, secXX.src.md must be changed tp secXX.md.
s = "[Section 3](sec3.src.md)" s = "[Section 3](sec3.src.md)"
t = change_rel_link s, "test", "gfm" t = change_rel_link s, "src", "gfm", file_table, "gfm"
if t != "[Section 3](sec3.md)" if t != "[Section 3](sec3.md)"
print "Relative link change according to base directory change didn't work.\n" print "Relative link change according to base directory change didn't work.\n"
print " Base directory test => gtm\n" print " Base directory test => gfm\n"
print " Original link => #{s}\n" print " Original link => #{s}\n"
print " Relative link temp/sample.c => #{t}\n" print " Relative link temp/sample.c => #{t}\n"
print " ** Correct new link must be [Section 2](sec3) **\n" print " ** Correct new link must be [Section 3](sec3) **\n"
end end
# --- test src2md # --- test src2md

View file

@ -1,7 +1,11 @@
# test_lib_sec_file.rb # test_lib_sec_file.rb
require_relative "../lib/lib_sec_file.rb" require_relative "../lib/lib_src_file.rb"
# Sample files for the test # Sample files for the test
src_text = <<'EOS'
This is a source file.
EOS
sample_c = <<'EOS' sample_c = <<'EOS'
#include <stdio.h> #include <stdio.h>
@ -52,6 +56,7 @@ Prerequisite
EOS EOS
files = [ files = [
["temp/srcfile.src.md", src_text],
["temp/sample.c", sample_c], ["temp/sample.c", sample_c],
["temp/sec1.src.md", sec1_text], ["temp/sec1.src.md", sec1_text],
["temp/sec2.src.md", sec2_text], ["temp/sec2.src.md", sec2_text],
@ -66,6 +71,24 @@ files.each do |f|
File.write f[0], f[1] File.write f[0], f[1]
end end
# Test Src_file
print "****** Src_file class test ******\n"
src = Src_file.new "temp/srcfile.src.md"
test_items = [
["path", "\"temp/srcfile.src.md\""],
["basename", "\"srcfile.src.md\""],
["dirname", "\"temp\""],
["to_md", "\"srcfile.md\""],
["to_html", "\"srcfile.html\""],
["to_tex", "\"srcfile.tex\""],
]
test_items.each do |item|
if eval("src.#{item[0]} != #{item[1]}")
print "src.#{item[0]} != #{item[1]}\n"
print " .... src.#{item[0]} is #{eval("src_sec1.#{item[0]}")}\n"
end
end
# Test Sec_file # Test Sec_file
print "****** Sec_file class test ******\n" print "****** Sec_file class test ******\n"
src_sec05 = Sec_file.new "temp/sec0.5.src.md" src_sec05 = Sec_file.new "temp/sec0.5.src.md"