mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-23 09:41:36 +00:00
Compare commits
5 Commits
398b0645a4
...
8a2ec348e1
Author | SHA1 | Date | |
---|---|---|---|
|
8a2ec348e1 | ||
|
770a4138b4 | ||
|
4d7ecfbbf7 | ||
|
bea8f291bc | ||
|
8083755456 |
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -3,4 +3,3 @@
|
|||||||
- [ ] Pull request touches only one file (or a set of logically related files with similar changes made)
|
- [ ] Pull request touches only one file (or a set of logically related files with similar changes made)
|
||||||
- [ ] Content changes are aimed at *intermediate to experienced programmers* (this is a poor format for explaining fundamental programming concepts)
|
- [ ] Content changes are aimed at *intermediate to experienced programmers* (this is a poor format for explaining fundamental programming concepts)
|
||||||
- [ ] If you've changed any part of the YAML Frontmatter, make sure it is formatted according to [CONTRIBUTING.md](https://github.com/adambard/learnxinyminutes-docs/blob/master/CONTRIBUTING.md)
|
- [ ] If you've changed any part of the YAML Frontmatter, make sure it is formatted according to [CONTRIBUTING.md](https://github.com/adambard/learnxinyminutes-docs/blob/master/CONTRIBUTING.md)
|
||||||
- [ ] Yes, I have double-checked quotes and field names!
|
|
||||||
|
12
.github/workflows/lint.yml
vendored
12
.github/workflows/lint.yml
vendored
@ -11,8 +11,18 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.13'
|
||||||
|
- run: pip install -r lint/requirements.txt
|
||||||
- uses: ruby/setup-ruby@v1
|
- uses: ruby/setup-ruby@v1
|
||||||
with:
|
with:
|
||||||
ruby-version: '3.2'
|
ruby-version: '3.2'
|
||||||
- run: gem install mdl
|
- run: gem install mdl
|
||||||
- run: mdl . --ignore-front-matter -r MD003,MD011,MD023,MD027,MD028,MD035,MD037,MD038,MD039,MD047
|
|
||||||
|
- name: Files are UTF-8
|
||||||
|
run: ./lint/encoding.sh .
|
||||||
|
- name: Lint Markdown
|
||||||
|
run: mdl . --ignore-front-matter -r MD003,MD011,MD023,MD027,MD028,MD035,MD037,MD038,MD039,MD047
|
||||||
|
- name: Lint frontmatter
|
||||||
|
run: ./lint/frontmatter.py .
|
||||||
|
@ -31,13 +31,6 @@ review them more effectively and/or individually.
|
|||||||
language in question.
|
language in question.
|
||||||
* Keep articles succinct and scannable. We all know how to use Google here.
|
* Keep articles succinct and scannable. We all know how to use Google here.
|
||||||
* **Use UTF-8**
|
* **Use UTF-8**
|
||||||
* For translations (or EN articles with non-ASCII characters) please ensure
|
|
||||||
your file is UTF-8 encoded.
|
|
||||||
* Leave out the byte-order-mark (BOM) at the start of the file (in Vim, use
|
|
||||||
`:set nobomb`).
|
|
||||||
* You can check if the file contains a BOM on Linux/Unix systems by running
|
|
||||||
`file language.html.markdown` You will see this if it uses a BOM:
|
|
||||||
`UTF-8 Unicode (with BOM) text`.
|
|
||||||
|
|
||||||
### Header configuration
|
### Header configuration
|
||||||
|
|
||||||
@ -48,29 +41,32 @@ called frontmatter.
|
|||||||
The following fields are necessary for English articles about programming
|
The following fields are necessary for English articles about programming
|
||||||
languages:
|
languages:
|
||||||
|
|
||||||
* **name** The human-readable name of the programming language
|
* `name`: The human-readable name of the programming language
|
||||||
* **contributors** A list of [author, URL] lists to credit
|
* `contributors`: A list of [*author*, *URL*] lists to credit, *URL* is optional
|
||||||
|
|
||||||
Other fields:
|
Other fields:
|
||||||
|
|
||||||
* **category**: The category of the article. So far, can be one of *language*,
|
* `category`: The category of the article. So far, can be one of *language*,
|
||||||
*tool* or *Algorithms & Data Structures*. Defaults to *language* if omitted.
|
*tool* or *Algorithms & Data Structures*. Defaults to *language* if omitted.
|
||||||
* **filename**: The filename for this article's code. It will be fetched, mashed
|
* `filename`: The filename for this article's code. It will be fetched, mashed
|
||||||
together, and made downloadable.
|
together, and made downloadable.
|
||||||
|
|
||||||
|
Translations should also include:
|
||||||
|
* `translators`: A list of [*translator*, *URL*] lists to credit, *URL* is optional
|
||||||
|
|
||||||
Non-English articles inherit frontmatter values from the English article (if it exists)
|
Non-English articles inherit frontmatter values from the English article (if it exists)
|
||||||
but you can overwrite them.
|
but you can overwrite them.
|
||||||
|
|
||||||
Here's an example header for Ruby:
|
Here's an example header for Ruby:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
*--
|
---
|
||||||
name: Ruby
|
name: Ruby
|
||||||
filename: learnruby.rb
|
filename: learnruby.rb
|
||||||
contributors:
|
contributors:
|
||||||
- ["Doktor Esperanto", "http://example.com/"]
|
- ["Doktor Esperanto", "http://example.com/"]
|
||||||
- ["Someone else", "http://someoneelseswebsite.com/"]
|
- ["Someone else", "http://someoneelseswebsite.com/"]
|
||||||
*--
|
---
|
||||||
```
|
```
|
||||||
|
|
||||||
### Syntax highlighter
|
### Syntax highlighter
|
||||||
|
2
bf.md
2
bf.md
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: BF
|
name: BF
|
||||||
learn_x_in_y_name: brainfuck
|
where_x_eq_name: brainfuck
|
||||||
filename: bf.bf
|
filename: bf.bf
|
||||||
contributors:
|
contributors:
|
||||||
- ["Prajit Ramachandran", "http://prajitr.github.io/"]
|
- ["Prajit Ramachandran", "http://prajitr.github.io/"]
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
filename: learngroovy-ca.groovy
|
filename: learngroovy-ca.groovy
|
||||||
contributors:
|
contributors:
|
||||||
- ["Roberto Pérez Alcolea", "http://github.com/rpalcolea"]
|
- ["Roberto Pérez Alcolea", "http://github.com/rpalcolea"]
|
||||||
translations:
|
translators:
|
||||||
- ["Xavier Sala Pujolar", "http://github.com/utrescu"]
|
- ["Xavier Sala Pujolar", "http://github.com/utrescu"]
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
contributors:
|
contributors:
|
||||||
- ["Dan Turkel", "http://danturkel.com/"]
|
- ["Dan Turkel", "http://danturkel.com/"]
|
||||||
translators :
|
translators:
|
||||||
- ["Frederik Ring", "https://github.com/m90"]
|
- ["Frederik Ring", "https://github.com/m90"]
|
||||||
- ["Philipp Fischbeck", "https://github.com/PFischbeck"]
|
- ["Philipp Fischbeck", "https://github.com/PFischbeck"]
|
||||||
filename: markdown-de.md
|
filename: markdown-de.md
|
||||||
|
@ -3,10 +3,9 @@ contributors:
|
|||||||
- ["Joao Marques", "http://github.com/mrshankly"]
|
- ["Joao Marques", "http://github.com/mrshankly"]
|
||||||
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
|
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
|
||||||
- ["Ryan Plant", "https://github.com/ryanplant-au"]
|
- ["Ryan Plant", "https://github.com/ryanplant-au"]
|
||||||
translator:
|
translators:
|
||||||
- ["Adrian Carrascal", "https://github.com/acarrascalgarcia"]
|
- ["Adrian Carrascal", "https://github.com/acarrascalgarcia"]
|
||||||
filename: learnelixir-es.ex
|
filename: learnelixir-es.ex
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Elixir es un lenguaje funcional moderno construido sobre la máquina virtual de Erlang.
|
Elixir es un lenguaje funcional moderno construido sobre la máquina virtual de Erlang.
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
filename: LearnGit-es.txt
|
filename: LearnGit-es.txt
|
||||||
contributors:
|
contributors:
|
||||||
- ["Jake Prather", "http://github.com/JakeHP"]
|
- ["Jake Prather", "http://github.com/JakeHP"]
|
||||||
translator:
|
translators:
|
||||||
- ["Raúl Ascencio", "http://rscnt.github.io"]
|
- ["Raúl Ascencio", "http://rscnt.github.io"]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Git es un sistema de control de versiones distribuido diseñado para manejar
|
Git es un sistema de control de versiones distribuido diseñado para manejar
|
||||||
|
@ -4,10 +4,11 @@ contributors:
|
|||||||
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
|
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
|
||||||
- ["Ryan Plant", "https://github.com/ryanplant-au"]
|
- ["Ryan Plant", "https://github.com/ryanplant-au"]
|
||||||
- ["Ev Bogdanov", "https://github.com/evbogdanov"]
|
- ["Ev Bogdanov", "https://github.com/evbogdanov"]
|
||||||
translator:
|
translators:
|
||||||
- ["Timothé Pardieu", "https://github.com/timprd"]
|
- ["Timothé Pardieu", "https://github.com/timprd"]
|
||||||
filename: learnelixir-fr.ex
|
filename: learnelixir-fr.ex
|
||||||
---
|
---
|
||||||
|
|
||||||
Elixir est un langage de programmation fonctionnel moderne reposant sur la machine virtuelle BEAM, qui héberge aussi Erlang.
|
Elixir est un langage de programmation fonctionnel moderne reposant sur la machine virtuelle BEAM, qui héberge aussi Erlang.
|
||||||
Il est totalement compatible avec Erlang mais dispose d'une syntaxe plus agréable et apporte de nouvelles fonctionnalités.
|
Il est totalement compatible avec Erlang mais dispose d'une syntaxe plus agréable et apporte de nouvelles fonctionnalités.
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
name: Groovy
|
name: Groovy
|
||||||
filename: learngroovy.groovy
|
|
||||||
contributors:
|
contributors:
|
||||||
- ["Roberto Pérez Alcolea", "http://github.com/rpalcolea"]
|
- ["Roberto Pérez Alcolea", "http://github.com/rpalcolea"]
|
||||||
filename: learngroovy.groovy
|
filename: learngroovy.groovy
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
contributors:
|
contributors:
|
||||||
- ["Brett Taylor", "https://github.com/glutnix"]
|
- ["Brett Taylor", "https://github.com/glutnix"]
|
||||||
translator:
|
translators:
|
||||||
- ["Agostino Fiscale", "https://github.com/agostinofiscale"]
|
- ["Agostino Fiscale", "https://github.com/agostinofiscale"]
|
||||||
filename: LearnComposer-it.sh
|
filename: LearnComposer-it.sh
|
||||||
---
|
---
|
||||||
|
30
lint/encoding.sh
Executable file
30
lint/encoding.sh
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
check_encoding() {
|
||||||
|
file="$1"
|
||||||
|
encoding=$(file -b --mime-encoding "$file")
|
||||||
|
|
||||||
|
# Check if the encoding is neither UTF-8 nor US-ASCII
|
||||||
|
if [[ "$encoding" != "utf-8" && "$encoding" != "us-ascii" ]]; then
|
||||||
|
# Print the file path and encoding
|
||||||
|
echo "Error: $file has encoding $encoding, which is not utf-8 or us-ascii"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for UTF-8 BOM
|
||||||
|
if [[ "$encoding" == "utf-8" ]]; then
|
||||||
|
if head -c 3 "$file" | cmp -s <(echo -ne '\xEF\xBB\xBF'); then
|
||||||
|
echo "Error: $file contains a UTF-8 BOM"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
export -f check_encoding
|
||||||
|
|
||||||
|
# Default to current directory if no argument is given
|
||||||
|
directory="${1:-.}"
|
||||||
|
|
||||||
|
find "$directory" -type f -name "*.md" -print0 | xargs -0 -P 8 -I {} bash -c 'check_encoding "$@"' _ {}
|
120
lint/frontmatter.py
Executable file
120
lint/frontmatter.py
Executable file
@ -0,0 +1,120 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
import yaml
|
||||||
|
import yamllint.config
|
||||||
|
import yamllint.linter
|
||||||
|
|
||||||
|
|
||||||
|
def extract_yaml_frontmatter(file_path):
|
||||||
|
"""Extracts YAML front matter from a Markdown file."""
|
||||||
|
with open(file_path, "r", encoding="utf-8") as file:
|
||||||
|
content = file.read()
|
||||||
|
matches = re.match(r"^(---\s*\n.*?\n)---\n", content, re.DOTALL)
|
||||||
|
if matches:
|
||||||
|
return matches.group(1)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
yaml_config = yamllint.config.YamlLintConfig(
|
||||||
|
"""{
|
||||||
|
extends: relaxed,
|
||||||
|
rules: {
|
||||||
|
commas: disable,
|
||||||
|
trailing-spaces: disable,
|
||||||
|
indentation: disable,
|
||||||
|
line-length: disable,
|
||||||
|
empty-lines: disable
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def lint_yaml(yaml_content):
|
||||||
|
"""Lints YAML content using yamllint by sending it to stdin."""
|
||||||
|
problems = []
|
||||||
|
for p in yamllint.linter.run(yaml_content, yaml_config):
|
||||||
|
problems.append(f"{p.line}:{p.column} {p.desc} ({p.rule})")
|
||||||
|
return "\n".join(problems)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_yaml_keys(yaml_content, allowed_keys):
|
||||||
|
"""Validates that the YAML content contains only the specified keys."""
|
||||||
|
try:
|
||||||
|
data = yaml.safe_load(yaml_content)
|
||||||
|
if not data:
|
||||||
|
return "Empty YAML front matter."
|
||||||
|
extra_keys = set(data.keys()) - set(allowed_keys)
|
||||||
|
if extra_keys:
|
||||||
|
return f"Invalid keys found: {', '.join(extra_keys)}"
|
||||||
|
for key, value_type in allowed_keys.items():
|
||||||
|
if key in data:
|
||||||
|
if not isinstance(data[key], value_type):
|
||||||
|
return f"Invalid type for key '{key}': expected {value_type.__name__}, got {type(data[key]).__name__}"
|
||||||
|
if isinstance(data[key], list):
|
||||||
|
for item in data[key]:
|
||||||
|
if not isinstance(item, list):
|
||||||
|
return f"Invalid type for item in key '{key}': expected list, got {type(item).__name__}"
|
||||||
|
elif not item:
|
||||||
|
return f"Invalid item in key '{key}': found empty list"
|
||||||
|
elif not isinstance(item[0], str):
|
||||||
|
return f"Invalid type for item[0] in key '{key}': expected str, got {type(item[0]).__name__}"
|
||||||
|
elif len(item) == 2 and not isinstance(item[1], str):
|
||||||
|
return f"Invalid type for item[1] in key '{key}': expected str, got {type(item[1]).__name__}"
|
||||||
|
elif len(item) > 2:
|
||||||
|
return f"Invalid length for item in key '{key}': expected 1 or 2, got {len(item)}"
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
return f"Error parsing YAML: {e}"
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def process_files(path):
|
||||||
|
"""Processes either a single file or all Markdown files in a directory."""
|
||||||
|
if path.is_dir():
|
||||||
|
pathlist = path.rglob("*.md")
|
||||||
|
else:
|
||||||
|
pathlist = [path]
|
||||||
|
|
||||||
|
has_error = False
|
||||||
|
allowed_keys = {
|
||||||
|
"name": str,
|
||||||
|
"where_x_eq_name": str,
|
||||||
|
"category": str,
|
||||||
|
"filename": str,
|
||||||
|
"contributors": list,
|
||||||
|
"translators": list,
|
||||||
|
}
|
||||||
|
for path in pathlist:
|
||||||
|
yaml_content = extract_yaml_frontmatter(path)
|
||||||
|
if yaml_content:
|
||||||
|
lint_result = lint_yaml(yaml_content)
|
||||||
|
key_validation = validate_yaml_keys(yaml_content, allowed_keys)
|
||||||
|
if lint_result or key_validation:
|
||||||
|
if has_error: # don't prepend newline to first error
|
||||||
|
print()
|
||||||
|
print(path)
|
||||||
|
if lint_result:
|
||||||
|
print(lint_result)
|
||||||
|
if key_validation:
|
||||||
|
print(key_validation)
|
||||||
|
has_error = True
|
||||||
|
return has_error
|
||||||
|
|
||||||
|
|
||||||
|
def main(path_input):
|
||||||
|
"""Determines if the input is a directory or a file and processes accordingly."""
|
||||||
|
path = Path(path_input)
|
||||||
|
if not path.exists():
|
||||||
|
print(f"Error: {path_input} does not exist.")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
return process_files(path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
|
||||||
|
path_input = sys.argv[1] if len(sys.argv) > 1 else "."
|
||||||
|
has_error = main(path_input)
|
||||||
|
sys.exit(1 if has_error else 0)
|
2
lint/requirements.txt
Normal file
2
lint/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
yamllint
|
||||||
|
pyyaml
|
@ -3,7 +3,7 @@ contributors:
|
|||||||
- ["Joao Marques", "http://github.com/mrshankly"]
|
- ["Joao Marques", "http://github.com/mrshankly"]
|
||||||
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
|
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
|
||||||
- ["Ryan Plant", "https://github.com/ryanplant-au"]
|
- ["Ryan Plant", "https://github.com/ryanplant-au"]
|
||||||
translator:
|
translators:
|
||||||
- ["Ev Bogdanov", "https://github.com/evbogdanov"]
|
- ["Ev Bogdanov", "https://github.com/evbogdanov"]
|
||||||
filename: learnelixir-ru.ex
|
filename: learnelixir-ru.ex
|
||||||
---
|
---
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
require 'charlock_holmes'
|
|
||||||
$file_count = 0;
|
|
||||||
markdown_files = Dir["./**/*.html.markdown"]
|
|
||||||
markdown_files.each do |file|
|
|
||||||
begin
|
|
||||||
contents = File.read(file)
|
|
||||||
detection = CharlockHolmes::EncodingDetector.detect(contents)
|
|
||||||
case detection[:encoding]
|
|
||||||
when 'UTF-8'
|
|
||||||
$file_count = $file_count + 1
|
|
||||||
when 'ISO-8859-1'
|
|
||||||
$file_count = $file_count + 1
|
|
||||||
when /ISO-8859/
|
|
||||||
puts "Notice: #{file} was detected as #{detection[:encoding]} encoding. Everything is probably fine."
|
|
||||||
$file_count = $file_count + 1
|
|
||||||
else
|
|
||||||
puts "WARNING #{file} was detected as #{detection[:encoding]} encoding. Please save the file in UTF-8!"
|
|
||||||
end
|
|
||||||
rescue Exception => msg
|
|
||||||
puts msg
|
|
||||||
end
|
|
||||||
end
|
|
||||||
files_failed = markdown_files.length - $file_count
|
|
||||||
if files_failed != 0
|
|
||||||
puts "FAILURE!!! #{files_failed} files were unable to be validated as UTF-8!"
|
|
||||||
puts "Please resave the file as UTF-8."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
puts "Success. All #{$file_count} files passed UTF-8 validity checks."
|
|
||||||
exit 0
|
|
||||||
end
|
|
@ -1,21 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
require 'yaml';
|
|
||||||
$file_count = 0;
|
|
||||||
markdown_files = Dir["./**/*.html.markdown"]
|
|
||||||
markdown_files.each do |file|
|
|
||||||
begin
|
|
||||||
YAML.load_file(file)
|
|
||||||
$file_count = $file_count + 1
|
|
||||||
rescue Exception => msg
|
|
||||||
puts msg
|
|
||||||
end
|
|
||||||
end
|
|
||||||
files_failed = markdown_files.length - $file_count
|
|
||||||
if files_failed != 0
|
|
||||||
puts "FAILURE!!! #{files_failed} files were unable to be parsed!"
|
|
||||||
puts "Please check the YAML headers for the documents that failed!"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
puts "All #{$file_count} files were verified valid YAML"
|
|
||||||
exit 0
|
|
||||||
end
|
|
@ -8,7 +8,6 @@ contributors:
|
|||||||
- ["Jason Stathopulos", "http://github.com/SpiritBreaker226"]
|
- ["Jason Stathopulos", "http://github.com/SpiritBreaker226"]
|
||||||
- ["Milo Gilad", "http://github.com/Myl0g"]
|
- ["Milo Gilad", "http://github.com/Myl0g"]
|
||||||
- ["Adem Budak", "https://github.com/p1v0t"]
|
- ["Adem Budak", "https://github.com/p1v0t"]
|
||||||
|
|
||||||
filename: LearnGit-tr.txt
|
filename: LearnGit-tr.txt
|
||||||
---
|
---
|
||||||
|
|
||||||
|
443
vim9script.md
Normal file
443
vim9script.md
Normal file
@ -0,0 +1,443 @@
|
|||||||
|
---
|
||||||
|
name: Vim9script
|
||||||
|
filename: learn9vimscript.vim
|
||||||
|
contributors:
|
||||||
|
- ["HiPhish", "http://hiphish.github.io/"]
|
||||||
|
---
|
||||||
|
|
||||||
|
```vim
|
||||||
|
# ##############
|
||||||
|
# Introduction
|
||||||
|
# ##############
|
||||||
|
|
||||||
|
# Vim9 script is a modernized version of Vim's scripting language, offering features like variables, functions, and loops.
|
||||||
|
# Accoding to `:help vim9-differences`, the principal differences from legacy Vim script are as follows:
|
||||||
|
#
|
||||||
|
# - Comments start with #, not ": >
|
||||||
|
# echo "hello" # comment
|
||||||
|
# - Using a backslash for line continuation is hardly ever needed: >
|
||||||
|
# echo "hello "
|
||||||
|
# .. yourName
|
||||||
|
# .. ", how are you?"
|
||||||
|
# - White space is required in many places to improve readability.
|
||||||
|
# - Assign values without `:let` *E1126* , declare variables with `:var`: >
|
||||||
|
# var count = 0
|
||||||
|
# count += 3
|
||||||
|
# - Constants can be declared with `:final` and `:const`: >
|
||||||
|
# final matches = [] # add to the list later
|
||||||
|
# const names = ['Betty', 'Peter'] # cannot be changed
|
||||||
|
# - `:final` cannot be used as an abbreviation of `:finally`.
|
||||||
|
# - Variables and functions are script-local by default.
|
||||||
|
# - Functions are declared with argument types and return type: >
|
||||||
|
# def CallMe(count: number, message: string): bool
|
||||||
|
# - Call functions without `:call`: >
|
||||||
|
# writefile(['done'], 'file.txt')
|
||||||
|
# - You cannot use old Ex commands:
|
||||||
|
# `:Print`
|
||||||
|
# `:append`
|
||||||
|
# `:change`
|
||||||
|
# `:d` directly followed by 'd' or 'p'.
|
||||||
|
# `:insert`
|
||||||
|
# `:k`
|
||||||
|
# `:mode`
|
||||||
|
# `:open`
|
||||||
|
# `:s` with only flags
|
||||||
|
# `:t`
|
||||||
|
# `:xit`
|
||||||
|
# - Some commands, especially those used for flow control, cannot be shortened.
|
||||||
|
# E.g., `:throw` cannot be written as `:th`. *vim9-no-shorten*
|
||||||
|
# - You cannot use curly-braces names.
|
||||||
|
# - A range before a command must be prefixed with a colon: >
|
||||||
|
# :%s/this/that
|
||||||
|
# - Executing a register with "@r" does not work, you can prepend a colon or use
|
||||||
|
# `:exe`: >
|
||||||
|
# :exe @a
|
||||||
|
# - Unless mentioned specifically, the highest |scriptversion| is used.
|
||||||
|
# - When defining an expression mapping, the expression will be evaluated in the
|
||||||
|
# context of the script where it was defined.
|
||||||
|
# - When indexing a string the index is counted in characters, not bytes:
|
||||||
|
# |vim9-string-index|
|
||||||
|
# - Some possibly unexpected differences: |vim9-gotchas|.
|
||||||
|
#
|
||||||
|
# You can run Vim9 script commands in command-line mode or write them to a file and source it in Vim.
|
||||||
|
# This guide assumes familiarity with ex-commands and focuses on scripting.
|
||||||
|
|
||||||
|
# Comments start with #
|
||||||
|
# The vertical line '|' separates commands
|
||||||
|
echo 'Hello' | echo 'world!'
|
||||||
|
|
||||||
|
# Putting a comment after a command usually works
|
||||||
|
pwd # Displays the current working directory
|
||||||
|
|
||||||
|
# Line continuation is rarely needed
|
||||||
|
echo "Hello "
|
||||||
|
.. "world"
|
||||||
|
|
||||||
|
echo [1, 2]
|
||||||
|
|
||||||
|
echo {
|
||||||
|
'a': 1,
|
||||||
|
'b': 2
|
||||||
|
}
|
||||||
|
|
||||||
|
# #######
|
||||||
|
# Types
|
||||||
|
# #######
|
||||||
|
|
||||||
|
# Numbers
|
||||||
|
echo 123 # Decimal
|
||||||
|
echo 0b1111011 # Binary
|
||||||
|
echo 0173 # Octal
|
||||||
|
echo 0x7B # Hexadecimal
|
||||||
|
echo 123.0 # Floating-point
|
||||||
|
echo 1.23e2 # Floating-point (scientific notation)
|
||||||
|
|
||||||
|
# Booleans
|
||||||
|
echo true # Evaluates to true
|
||||||
|
echo false # Evaluates to false
|
||||||
|
|
||||||
|
# Boolean values from comparison
|
||||||
|
echo x == y # Equality by value
|
||||||
|
echo x != y # Inequality
|
||||||
|
echo x > y # Greater than
|
||||||
|
echo x >= y # Greater than or equal
|
||||||
|
echo x < y # Smaller than
|
||||||
|
echo x <= y # Smaller than or equal
|
||||||
|
echo x is y # Instance identity
|
||||||
|
echo x isnot y # Instance non-identity
|
||||||
|
|
||||||
|
# Strings
|
||||||
|
echo 'a' < 'B' # True or false depending on 'ignorecase'
|
||||||
|
echo 'a' <? 'B' # True
|
||||||
|
echo 'a' <# 'B' # False
|
||||||
|
|
||||||
|
# Regular expression matching
|
||||||
|
echo "hi" =~ "hello" # Regular expression match
|
||||||
|
echo "hi" =~# "hello" # Case sensitive
|
||||||
|
echo "hi" =~? "hello" # Case insensitive
|
||||||
|
echo "hi" !~ "hello" # Regular expression unmatch
|
||||||
|
echo "hi" !~# "hello" # Case sensitive
|
||||||
|
echo "hi" !~? "hello" # Case insensitive
|
||||||
|
|
||||||
|
# Boolean operations
|
||||||
|
echo true && false # Logical AND
|
||||||
|
echo true || false # Logical OR
|
||||||
|
echo !true # Logical NOT
|
||||||
|
echo true ? 'yes' : 'no' # Ternary operator
|
||||||
|
|
||||||
|
# Strings
|
||||||
|
echo "Hello world\n" # Newline
|
||||||
|
echo 'Hello world\n' # Literal
|
||||||
|
echo 'Let''s go!' # Two single quotes become one
|
||||||
|
|
||||||
|
# String concatenation
|
||||||
|
echo 'Hello ' .. 'world' # String concatenation
|
||||||
|
|
||||||
|
# String indexing
|
||||||
|
echo 'Hello'[0] # First character
|
||||||
|
echo 'Hello'[1] # Second character
|
||||||
|
echo 'Hellö'[4] # Returns a character
|
||||||
|
|
||||||
|
# Substrings
|
||||||
|
echo 'Hello'[:] # Copy of entire string
|
||||||
|
echo 'Hello'[1:3] # Substring
|
||||||
|
echo 'Hello'[1:-2] # Substring until second to last character
|
||||||
|
echo 'Hello'[1:] # Substring with starting index
|
||||||
|
echo 'Hello'[:2] # Substring with ending index
|
||||||
|
echo 'Hello'[-2:] # Substring relative to end
|
||||||
|
|
||||||
|
# Lists
|
||||||
|
echo [] # Empty list
|
||||||
|
echo [1, 2, 'Hello'] # List with elements
|
||||||
|
echo [1, 2, 'Hello', ] # Trailing comma permitted
|
||||||
|
echo [[1, 2], 'Hello'] # Nested lists
|
||||||
|
|
||||||
|
# List concatenation
|
||||||
|
echo [1, 2] + [3, 4] # Creates a new list
|
||||||
|
|
||||||
|
# List indexing
|
||||||
|
echo [1, 2, 3, 4][2] # Third element
|
||||||
|
echo [1, 2, 3, 4][-1] # Last element
|
||||||
|
|
||||||
|
# List slicing
|
||||||
|
echo [1, 2, 3, 4][:] # Shallow copy
|
||||||
|
echo [1, 2, 3, 4][:2] # Sublist until third item
|
||||||
|
echo [1, 2, 3, 4][2:] # Sublist from third item
|
||||||
|
echo [1, 2, 3, 4][:-2] # Sublist until second-to-last item
|
||||||
|
|
||||||
|
# Dictionaries
|
||||||
|
echo {} # Empty dictionary
|
||||||
|
echo {'a': 1, 'b': 2} # Dictionary literal
|
||||||
|
echo {'a': 1, 'b': 2, } # Trailing comma permitted
|
||||||
|
echo {'x': {'a': 1, 'b': 2}} # Nested dictionary
|
||||||
|
|
||||||
|
# Indexing a dictionary
|
||||||
|
echo {'a': 1, 'b': 2}['a'] # Literal index
|
||||||
|
echo {'a': 1, 'b': 2}.a # Syntactic sugar
|
||||||
|
|
||||||
|
# Funcref
|
||||||
|
echo function('type') # Reference to function type()
|
||||||
|
echo {x -> x * x} # Anonymous function
|
||||||
|
|
||||||
|
# Regular expression
|
||||||
|
substitute/hello/Hello/
|
||||||
|
|
||||||
|
# ###########################
|
||||||
|
# Implicit type conversions
|
||||||
|
# ###########################
|
||||||
|
|
||||||
|
echo "1" + 1 # Number
|
||||||
|
echo "1" .. 1 # String
|
||||||
|
echo "0xA" + 1 # Number
|
||||||
|
|
||||||
|
# ###########
|
||||||
|
# Variables
|
||||||
|
# ###########
|
||||||
|
|
||||||
|
var b:my_var = 1 # Local to current buffer
|
||||||
|
var w:my_var = 1 # Local to current window
|
||||||
|
var t:my_var = 1 # Local to current tab page
|
||||||
|
var g:my_var = 1 # Global variable
|
||||||
|
|
||||||
|
# Access special Vim memory like variables
|
||||||
|
var @a = 'Hello' # Register
|
||||||
|
var $PATH='' # Environment variable
|
||||||
|
var &textwidth = 79 # Option
|
||||||
|
var &l:textwidth = 79 # Local option
|
||||||
|
var &g:textwidth = 79 # Global option
|
||||||
|
|
||||||
|
# Access scopes as dictionaries
|
||||||
|
echo b: # All buffer variables
|
||||||
|
echo w: # All window variables
|
||||||
|
echo t: # All tab page variables
|
||||||
|
echo g: # All global variables
|
||||||
|
echo v: # All Vim variables
|
||||||
|
|
||||||
|
# Constant variables
|
||||||
|
const x = 10 # Constant
|
||||||
|
|
||||||
|
# Function reference variables
|
||||||
|
var IsString = {x -> type(x) == type('')} # Global
|
||||||
|
var isNumber = {x -> type(x) == type(0)} # Local
|
||||||
|
|
||||||
|
# Multiple value binding
|
||||||
|
var [x, y] = [1, 2]
|
||||||
|
|
||||||
|
# Assign the remainder to a rest variable
|
||||||
|
var [mother, father; children] = ['Alice', 'Bob', 'Carol', 'Dennis', 'Emily']
|
||||||
|
|
||||||
|
# ##############
|
||||||
|
# Flow control
|
||||||
|
# ##############
|
||||||
|
|
||||||
|
# Conditional
|
||||||
|
var condition = true
|
||||||
|
|
||||||
|
if condition
|
||||||
|
echo 'First condition'
|
||||||
|
elseif another_condition
|
||||||
|
echo 'Second condition'
|
||||||
|
else
|
||||||
|
echo 'Fail'
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Loops
|
||||||
|
|
||||||
|
# For-loop
|
||||||
|
for person in ['Alice', 'Bob', 'Carol', 'Dennis', 'Emily']
|
||||||
|
echo 'Hello ' .. person
|
||||||
|
endfor
|
||||||
|
|
||||||
|
# Iterate over a nested list
|
||||||
|
for [x, y] in [[1, 0], [0, 1], [-1, 0], [0, -1]]
|
||||||
|
echo 'Position: x =' .. x .. ', y = ' .. y
|
||||||
|
endfor
|
||||||
|
|
||||||
|
# Iterate over a range of numbers
|
||||||
|
for i in range(10, 0, -1)
|
||||||
|
echo 'T minus' .. i
|
||||||
|
endfor
|
||||||
|
|
||||||
|
# Iterate over the keys of a dictionary
|
||||||
|
for symbol in keys({'π': 3.14, 'e': 2.71})
|
||||||
|
echo 'The constant ' .. symbol .. ' is a transcendent number'
|
||||||
|
endfor
|
||||||
|
|
||||||
|
# Iterate over the values of a dictionary
|
||||||
|
for value in values({'π': 3.14, 'e': 2.71})
|
||||||
|
echo 'The value ' .. value .. ' approximates a transcendent number'
|
||||||
|
endfor
|
||||||
|
|
||||||
|
# Iterate over the keys and values of a dictionary
|
||||||
|
for [symbol, value] in items({'π': 3.14, 'e': 2.71})
|
||||||
|
echo 'The number ' .. symbol .. ' is approximately ' .. value
|
||||||
|
endfor
|
||||||
|
|
||||||
|
# While-loops
|
||||||
|
var there_yet = true
|
||||||
|
while !there_yet
|
||||||
|
echo 'Are we there yet?'
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
# Exception handling
|
||||||
|
try
|
||||||
|
source path/to/file
|
||||||
|
catch /Cannot open/
|
||||||
|
echo 'Looks like that file does not exist'
|
||||||
|
catch /.*/
|
||||||
|
echo 'Something went wrong, but I do not know what'
|
||||||
|
finally
|
||||||
|
echo 'I am done trying'
|
||||||
|
endtry
|
||||||
|
|
||||||
|
# ##########
|
||||||
|
# Functions
|
||||||
|
# ##########
|
||||||
|
|
||||||
|
# Defining functions
|
||||||
|
def AddNumbersLoudly(x: number, y: number): number
|
||||||
|
echo 'Adding' .. x .. 'and' .. y
|
||||||
|
return x + y
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def s:addNumbersLoudly(x: number, y: number): number
|
||||||
|
echo 'Adding' .. x .. 'and' .. y
|
||||||
|
return x + y
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Range functions
|
||||||
|
def FirstAndLastLine() range
|
||||||
|
echo [a:firstline, a:lastline]
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Aborting functions
|
||||||
|
def SourceMyFile() abort
|
||||||
|
source my-file.vim
|
||||||
|
echo 'This will never be printed'
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Closures
|
||||||
|
def MakeAdder(x: number)
|
||||||
|
def Adder(n: number) closure
|
||||||
|
return n + x
|
||||||
|
enddef
|
||||||
|
return funcref('Adder')
|
||||||
|
enddef
|
||||||
|
var AddFive = MakeAdder(5)
|
||||||
|
echo AddFive(3) # Prints 8
|
||||||
|
|
||||||
|
# Dictionary functions
|
||||||
|
def Mylen() dict
|
||||||
|
return len(self.data)
|
||||||
|
enddef
|
||||||
|
var mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
|
||||||
|
echo mydict.len()
|
||||||
|
|
||||||
|
# Alternatively, more concise
|
||||||
|
var mydict = {'data': [0, 1, 2, 3]}
|
||||||
|
def mydict.len()
|
||||||
|
return len(self.data)
|
||||||
|
enddef
|
||||||
|
|
||||||
|
# Calling functions
|
||||||
|
var animals = keys({'cow': 'moo', 'dog': 'woof', 'cat': 'meow'})
|
||||||
|
|
||||||
|
# Call a function for its side effects only
|
||||||
|
call sign_undefine()
|
||||||
|
|
||||||
|
# The call() function
|
||||||
|
echo call(function('get'), [{'a': 1, 'b': 2}, 'c', 3]) # Prints 3
|
||||||
|
|
||||||
|
# Function namespaces
|
||||||
|
def foo#bar#log(value: string)
|
||||||
|
echomsg value
|
||||||
|
enddef
|
||||||
|
|
||||||
|
call foo#bar#log('Hello')
|
||||||
|
|
||||||
|
# #############################
|
||||||
|
# Frequently used ex-commands
|
||||||
|
# #############################
|
||||||
|
|
||||||
|
# Sourcing runtime files
|
||||||
|
runtime plugin/my-plugin.vim
|
||||||
|
|
||||||
|
# Defining new ex-commands
|
||||||
|
command! SwapAdjacentLines normal! ddp
|
||||||
|
|
||||||
|
command! -nargs=1 Error echoerr <args>
|
||||||
|
|
||||||
|
# Defining auto-commands
|
||||||
|
autocmd BufWritePost $MYVIMRC source $MYVIMRC
|
||||||
|
|
||||||
|
# Auto groups
|
||||||
|
augroup auto-source
|
||||||
|
autocmd!
|
||||||
|
autocmd BufWritePost $MYVIMRC source $MYVIMRC
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
# Executing
|
||||||
|
var line = 3
|
||||||
|
execute line .. 'delete'
|
||||||
|
|
||||||
|
# Executing normal-mode commands
|
||||||
|
normal! ggddGp
|
||||||
|
|
||||||
|
# Window commands
|
||||||
|
wincmd L
|
||||||
|
|
||||||
|
# ###########################
|
||||||
|
# Frequently used functions
|
||||||
|
# ###########################
|
||||||
|
|
||||||
|
# Feature check
|
||||||
|
echo has('nvim')
|
||||||
|
echo has('python3')
|
||||||
|
echo has('unix')
|
||||||
|
echo has('win32')
|
||||||
|
|
||||||
|
# Test if something exists
|
||||||
|
echo exists('&mouse')
|
||||||
|
echo exists('+mouse')
|
||||||
|
echo exists('$HOSTNAME')
|
||||||
|
echo exists('*strftime')
|
||||||
|
echo exists('**s:MyFunc')
|
||||||
|
echo exists('bufcount')
|
||||||
|
echo exists('my_dict["foo"]')
|
||||||
|
echo exists(':Make')
|
||||||
|
echo exists("#CursorHold")
|
||||||
|
echo exists("#BufReadPre#*.gz")
|
||||||
|
echo exists("#filetypeindent")
|
||||||
|
echo exists("##ColorScheme")
|
||||||
|
|
||||||
|
# Various dynamic values
|
||||||
|
echo expand('%')
|
||||||
|
echo expand('<cword>')
|
||||||
|
echo expand('%:p')
|
||||||
|
|
||||||
|
# Type tests
|
||||||
|
echo type(my_var) == v:t_number
|
||||||
|
echo type(my_var) == v:t_string
|
||||||
|
echo type(my_var) == v:t_func
|
||||||
|
echo type(my_var) == v:t_list
|
||||||
|
echo type(my_var) == v:t_dict
|
||||||
|
echo type(my_var) == v:t_float
|
||||||
|
echo type(my_var) == v:t_bool
|
||||||
|
echo my_var is v:null
|
||||||
|
|
||||||
|
# Format strings
|
||||||
|
echo printf('%d in hexadecimal is %X', 123, 123)
|
||||||
|
|
||||||
|
# #####################
|
||||||
|
# Tricks of the trade
|
||||||
|
# #####################
|
||||||
|
|
||||||
|
# Source guard
|
||||||
|
if exists('g:loaded_my_plugin')
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
var g_loaded_my_plugin = true
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
var greeting = get(g:, 'my_plugin_greeting', 'Hello')
|
||||||
|
```
|
@ -4,7 +4,6 @@ contributors:
|
|||||||
- ["Aleksey Kholovchuk", "https://github.com/vortexxx192"]
|
- ["Aleksey Kholovchuk", "https://github.com/vortexxx192"]
|
||||||
translators:
|
translators:
|
||||||
- ["GengchenXU", "https://github.com/GengchenXU"]
|
- ["GengchenXU", "https://github.com/GengchenXU"]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Qt** Qt是一个广为人知的框架,用于开发跨平台软件,该软件可以在各种软件和硬件平台上运行,代码几乎没有变化,同时具有本机应用程序的能力和速度。虽然**Qt**最初是用*C*++,但也有其他语言的端口: *[PyQt](../pyqt/)*, *QtRuby*, *PHP-Qt*, 等等.
|
**Qt** Qt是一个广为人知的框架,用于开发跨平台软件,该软件可以在各种软件和硬件平台上运行,代码几乎没有变化,同时具有本机应用程序的能力和速度。虽然**Qt**最初是用*C*++,但也有其他语言的端口: *[PyQt](../pyqt/)*, *QtRuby*, *PHP-Qt*, 等等.
|
||||||
|
Loading…
Reference in New Issue
Block a user