mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-04 02:44:44 +00:00
Markdown code blocks migration part 8 (#22478)
This commit is contained in:
@@ -110,16 +110,16 @@ proc respond*(req: Request, code: HttpCode, content: string,
|
||||
## This procedure will **not** close the client socket.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## import std/json
|
||||
## proc handler(req: Request) {.async.} =
|
||||
## if req.url.path == "/hello-world":
|
||||
## let msg = %* {"message": "Hello World"}
|
||||
## let headers = newHttpHeaders([("Content-Type","application/json")])
|
||||
## await req.respond(Http200, $msg, headers)
|
||||
## else:
|
||||
## await req.respond(Http404, "Not Found")
|
||||
## ```Nim
|
||||
## import std/json
|
||||
## proc handler(req: Request) {.async.} =
|
||||
## if req.url.path == "/hello-world":
|
||||
## let msg = %* {"message": "Hello World"}
|
||||
## let headers = newHttpHeaders([("Content-Type","application/json")])
|
||||
## await req.respond(Http200, $msg, headers)
|
||||
## else:
|
||||
## await req.respond(Http404, "Not Found")
|
||||
## ```
|
||||
var msg = "HTTP/1.1 " & $code & "\c\L"
|
||||
|
||||
if headers != nil:
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
## `difference <#difference,HashSet[A],HashSet[A]>`_, and
|
||||
## `symmetric difference <#symmetricDifference,HashSet[A],HashSet[A]>`_
|
||||
##
|
||||
## .. code-block::
|
||||
## **Examples:**
|
||||
##
|
||||
## ```Nim
|
||||
## echo toHashSet([9, 5, 1]) # {9, 1, 5}
|
||||
## echo toOrderedSet([9, 5, 1]) # {9, 5, 1}
|
||||
##
|
||||
@@ -37,7 +39,7 @@
|
||||
## echo s1 - s2 # {1, 9}
|
||||
## echo s1 * s2 # {5}
|
||||
## echo s1 -+- s2 # {9, 1, 3, 7}
|
||||
##
|
||||
## ```
|
||||
##
|
||||
## Note: The data types declared here have *value semantics*: This means
|
||||
## that `=` performs a copy of the set.
|
||||
@@ -249,7 +251,7 @@ iterator items*[A](s: HashSet[A]): A =
|
||||
## If you need a sequence with the elements you can use `sequtils.toSeq
|
||||
## template <sequtils.html#toSeq.t,untyped>`_.
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## type
|
||||
## pair = tuple[a, b: int]
|
||||
## var
|
||||
@@ -262,6 +264,7 @@ iterator items*[A](s: HashSet[A]): A =
|
||||
## assert a.len == 2
|
||||
## echo b
|
||||
## # --> {(a: 1, b: 3), (a: 0, b: 4)}
|
||||
## ```
|
||||
let length = s.len
|
||||
for h in 0 .. high(s.data):
|
||||
if isFilled(s.data[h].hcode):
|
||||
@@ -586,12 +589,12 @@ proc `$`*[A](s: HashSet[A]): string =
|
||||
## any moment and values are not escaped.
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## echo toHashSet([2, 4, 5])
|
||||
## # --> {2, 4, 5}
|
||||
## echo toHashSet(["no", "esc'aping", "is \" provided"])
|
||||
## # --> {no, esc'aping, is " provided}
|
||||
## ```
|
||||
dollarImpl()
|
||||
|
||||
|
||||
@@ -874,12 +877,12 @@ proc `$`*[A](s: OrderedSet[A]): string =
|
||||
## any moment and values are not escaped.
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## echo toOrderedSet([2, 4, 5])
|
||||
## # --> {2, 4, 5}
|
||||
## echo toOrderedSet(["no", "esc'aping", "is \" provided"])
|
||||
## # --> {no, esc'aping, is " provided}
|
||||
## ```
|
||||
dollarImpl()
|
||||
|
||||
|
||||
@@ -890,7 +893,7 @@ iterator items*[A](s: OrderedSet[A]): A =
|
||||
## If you need a sequence with the elements you can use `sequtils.toSeq
|
||||
## template <sequtils.html#toSeq.t,untyped>`_.
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var a = initOrderedSet[int]()
|
||||
## for value in [9, 2, 1, 5, 1, 8, 4, 2]:
|
||||
## a.incl(value)
|
||||
@@ -902,6 +905,7 @@ iterator items*[A](s: OrderedSet[A]): A =
|
||||
## # --> Got 5
|
||||
## # --> Got 8
|
||||
## # --> Got 4
|
||||
## ```
|
||||
let length = s.len
|
||||
forAllOrderedPairs:
|
||||
yield s.data[h].key
|
||||
|
||||
@@ -191,8 +191,7 @@ proc withKey*[A, B](t: var SharedTable[A, B], key: A,
|
||||
##
|
||||
## Example usage:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## # If value exists, decrement it.
|
||||
## # If it becomes zero or less, delete the key
|
||||
## t.withKey(1'i64) do (k: int64, v: var int, pairExists: var bool):
|
||||
@@ -200,6 +199,7 @@ proc withKey*[A, B](t: var SharedTable[A, B], key: A,
|
||||
## dec v
|
||||
## if v <= 0:
|
||||
## pairExists = false
|
||||
## ```
|
||||
withLock t:
|
||||
var hc: Hash
|
||||
var index = rawGet(t, key, hc)
|
||||
|
||||
@@ -136,14 +136,11 @@ runnableExamples:
|
||||
## a more complex object as a key you will be greeted by a strange compiler
|
||||
## error:
|
||||
##
|
||||
## .. code::
|
||||
##
|
||||
## Error: type mismatch: got (Person)
|
||||
## but expected one of:
|
||||
## hashes.hash(x: openArray[A]): Hash
|
||||
## hashes.hash(x: int): Hash
|
||||
## hashes.hash(x: float): Hash
|
||||
## …
|
||||
## Error: type mismatch: got (Person)
|
||||
## but expected one of:
|
||||
## hashes.hash(x: openArray[A]): Hash
|
||||
## hashes.hash(x: int): Hash
|
||||
## hashes.hash(x: float): Hash
|
||||
##
|
||||
## What is happening here is that the types used for table keys require to have
|
||||
## a `hash()` proc which will convert them to a `Hash <hashes.html#Hash>`_
|
||||
@@ -678,7 +675,7 @@ iterator pairs*[A, B](t: Table[A, B]): (A, B) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## let a = {
|
||||
## 'o': [1, 5, 7, 9],
|
||||
## 'e': [2, 4, 6, 8]
|
||||
@@ -692,6 +689,7 @@ iterator pairs*[A, B](t: Table[A, B]): (A, B) =
|
||||
## # value: [2, 4, 6, 8]
|
||||
## # key: o
|
||||
## # value: [1, 5, 7, 9]
|
||||
## ```
|
||||
let L = len(t)
|
||||
for h in 0 .. high(t.data):
|
||||
if isFilled(t.data[h].hcode):
|
||||
@@ -1127,7 +1125,7 @@ iterator pairs*[A, B](t: TableRef[A, B]): (A, B) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## let a = {
|
||||
## 'o': [1, 5, 7, 9],
|
||||
## 'e': [2, 4, 6, 8]
|
||||
@@ -1141,6 +1139,7 @@ iterator pairs*[A, B](t: TableRef[A, B]): (A, B) =
|
||||
## # value: [2, 4, 6, 8]
|
||||
## # key: o
|
||||
## # value: [1, 5, 7, 9]
|
||||
## ```
|
||||
let L = len(t)
|
||||
for h in 0 .. high(t.data):
|
||||
if isFilled(t.data[h].hcode):
|
||||
@@ -1703,7 +1702,7 @@ iterator pairs*[A, B](t: OrderedTable[A, B]): (A, B) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## let a = {
|
||||
## 'o': [1, 5, 7, 9],
|
||||
## 'e': [2, 4, 6, 8]
|
||||
@@ -1717,6 +1716,7 @@ iterator pairs*[A, B](t: OrderedTable[A, B]): (A, B) =
|
||||
## # value: [1, 5, 7, 9]
|
||||
## # key: e
|
||||
## # value: [2, 4, 6, 8]
|
||||
## ```
|
||||
|
||||
let L = len(t)
|
||||
forAllOrderedPairs:
|
||||
@@ -2113,7 +2113,7 @@ iterator pairs*[A, B](t: OrderedTableRef[A, B]): (A, B) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## let a = {
|
||||
## 'o': [1, 5, 7, 9],
|
||||
## 'e': [2, 4, 6, 8]
|
||||
@@ -2127,6 +2127,7 @@ iterator pairs*[A, B](t: OrderedTableRef[A, B]): (A, B) =
|
||||
## # value: [1, 5, 7, 9]
|
||||
## # key: e
|
||||
## # value: [2, 4, 6, 8]
|
||||
## ```
|
||||
|
||||
let L = len(t)
|
||||
forAllOrderedPairs:
|
||||
@@ -2526,7 +2527,7 @@ iterator pairs*[A](t: CountTable[A]): (A, int) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## let a = toCountTable("abracadabra")
|
||||
##
|
||||
## for k, v in pairs(a):
|
||||
@@ -2543,6 +2544,7 @@ iterator pairs*[A](t: CountTable[A]): (A, int) =
|
||||
## # value: 1
|
||||
## # key: r
|
||||
## # value: 2
|
||||
## ```
|
||||
let L = len(t)
|
||||
for h in 0 .. high(t.data):
|
||||
if t.data[h].val != 0:
|
||||
@@ -2806,7 +2808,7 @@ iterator pairs*[A](t: CountTableRef[A]): (A, int) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## let a = newCountTable("abracadabra")
|
||||
##
|
||||
## for k, v in pairs(a):
|
||||
@@ -2823,6 +2825,7 @@ iterator pairs*[A](t: CountTableRef[A]): (A, int) =
|
||||
## # value: 1
|
||||
## # key: r
|
||||
## # value: 2
|
||||
## ```
|
||||
let L = len(t)
|
||||
for h in 0 .. high(t.data):
|
||||
if t.data[h].val != 0:
|
||||
@@ -2915,4 +2918,4 @@ proc hash*[K,V](s: OrderedTable[K,V]): Hash =
|
||||
proc hash*[V](s: CountTable[V]): Hash =
|
||||
for p in pairs(s):
|
||||
result = result xor hash(p)
|
||||
result = !$result
|
||||
result = !$result
|
||||
|
||||
@@ -18,13 +18,14 @@ type
|
||||
proc `==`*(a, b: Color): bool {.borrow.}
|
||||
## Compares two colors.
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var
|
||||
## a = Color(0xff_00_ff)
|
||||
## b = colFuchsia
|
||||
## c = Color(0x00_ff_cc)
|
||||
## assert a == b
|
||||
## assert not (a == c)
|
||||
## ```
|
||||
|
||||
template extract(a: Color, r, g, b: untyped) =
|
||||
var r = a.int shr 16 and 0xff
|
||||
|
||||
@@ -18,12 +18,11 @@
|
||||
##
|
||||
## The above output could be the result of a code snippet like:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## if detectOs(Ubuntu):
|
||||
## foreignDep "lbiblas-dev"
|
||||
## foreignDep "libvoodoo"
|
||||
##
|
||||
## ```
|
||||
##
|
||||
## See `packaging <packaging.html>`_ for hints on distributing Nim using OS packages.
|
||||
|
||||
|
||||
@@ -30,9 +30,10 @@
|
||||
## Examples
|
||||
## ========
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## var nim = "Nim"
|
||||
## echo h1(a(href="https://nim-lang.org", nim))
|
||||
## ```
|
||||
##
|
||||
## Writes the string:
|
||||
##
|
||||
|
||||
@@ -12,10 +12,9 @@
|
||||
##
|
||||
## It can be used to parse a wild HTML document and output it as valid XHTML
|
||||
## document (well, if you are lucky):
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
##
|
||||
## ```Nim
|
||||
## echo loadHtml("mydirty.html")
|
||||
## ```
|
||||
##
|
||||
## Every tag in the resulting tree is in lower case.
|
||||
##
|
||||
@@ -29,9 +28,7 @@
|
||||
## and write back the modified version. In this case we look for hyperlinks
|
||||
## ending with the extension `.rst` and convert them to `.html`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## :test:
|
||||
##
|
||||
## ```Nim test
|
||||
## import std/htmlparser
|
||||
## import std/xmltree # To use '$' for XmlNode
|
||||
## import std/strtabs # To access XmlAttributes
|
||||
@@ -48,6 +45,7 @@
|
||||
## a.attrs["href"] = dir / filename & ".html"
|
||||
##
|
||||
## writeFile("output.html", $html)
|
||||
## ```
|
||||
|
||||
import strutils, streams, parsexml, xmltree, unicode, strtabs
|
||||
|
||||
|
||||
@@ -18,18 +18,19 @@
|
||||
## This example uses HTTP GET to retrieve
|
||||
## `http://google.com`:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/httpclient
|
||||
## var client = newHttpClient()
|
||||
## try:
|
||||
## echo client.getContent("http://google.com")
|
||||
## finally:
|
||||
## client.close()
|
||||
## ```
|
||||
##
|
||||
## The same action can also be performed asynchronously, simply use the
|
||||
## `AsyncHttpClient`:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/[asyncdispatch, httpclient]
|
||||
##
|
||||
## proc asyncProc(): Future[string] {.async.} =
|
||||
@@ -40,6 +41,7 @@
|
||||
## client.close()
|
||||
##
|
||||
## echo waitFor asyncProc()
|
||||
## ```
|
||||
##
|
||||
## The functionality implemented by `HttpClient` and `AsyncHttpClient`
|
||||
## is the same, so you can use whichever one suits you best in the examples
|
||||
@@ -59,7 +61,7 @@
|
||||
## uses `multipart/form-data` as the `Content-Type` to send the HTML to be
|
||||
## validated to the server.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## var client = newHttpClient()
|
||||
## var data = newMultipartData()
|
||||
## data["output"] = "soap12"
|
||||
@@ -69,13 +71,14 @@
|
||||
## echo client.postContent("http://validator.w3.org/check", multipart=data)
|
||||
## finally:
|
||||
## client.close()
|
||||
## ```
|
||||
##
|
||||
## To stream files from disk when performing the request, use `addFiles`.
|
||||
##
|
||||
## **Note:** This will allocate a new `Mimetypes` database every time you call
|
||||
## it, you can pass your own via the `mimeDb` parameter to avoid this.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## let mimes = newMimetypes()
|
||||
## var client = newHttpClient()
|
||||
## var data = newMultipartData()
|
||||
@@ -84,12 +87,13 @@
|
||||
## echo client.postContent("http://validator.w3.org/check", multipart=data)
|
||||
## finally:
|
||||
## client.close()
|
||||
## ```
|
||||
##
|
||||
## You can also make post requests with custom headers.
|
||||
## This example sets `Content-Type` to `application/json`
|
||||
## and uses a json object for the body
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/[httpclient, json]
|
||||
##
|
||||
## let client = newHttpClient()
|
||||
@@ -102,6 +106,7 @@
|
||||
## echo response.status
|
||||
## finally:
|
||||
## client.close()
|
||||
## ```
|
||||
##
|
||||
## Progress reporting
|
||||
## ==================
|
||||
@@ -110,27 +115,29 @@
|
||||
## This callback will be executed every second with information about the
|
||||
## progress of the HTTP request.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## import std/[asyncdispatch, httpclient]
|
||||
## ```Nim
|
||||
## import std/[asyncdispatch, httpclient]
|
||||
##
|
||||
## proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
|
||||
## echo("Downloaded ", progress, " of ", total)
|
||||
## echo("Current rate: ", speed div 1000, "kb/s")
|
||||
## proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
|
||||
## echo("Downloaded ", progress, " of ", total)
|
||||
## echo("Current rate: ", speed div 1000, "kb/s")
|
||||
##
|
||||
## proc asyncProc() {.async.} =
|
||||
## var client = newAsyncHttpClient()
|
||||
## client.onProgressChanged = onProgressChanged
|
||||
## try:
|
||||
## discard await client.getContent("http://speedtest-ams2.digitalocean.com/100mb.test")
|
||||
## finally:
|
||||
## client.close()
|
||||
## proc asyncProc() {.async.} =
|
||||
## var client = newAsyncHttpClient()
|
||||
## client.onProgressChanged = onProgressChanged
|
||||
## try:
|
||||
## discard await client.getContent("http://speedtest-ams2.digitalocean.com/100mb.test")
|
||||
## finally:
|
||||
## client.close()
|
||||
##
|
||||
## waitFor asyncProc()
|
||||
## waitFor asyncProc()
|
||||
## ```
|
||||
##
|
||||
## If you would like to remove the callback simply set it to `nil`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## client.onProgressChanged = nil
|
||||
## ```
|
||||
##
|
||||
## .. warning:: The `total` reported by httpclient may be 0 in some cases.
|
||||
##
|
||||
@@ -152,9 +159,10 @@
|
||||
##
|
||||
## Example of setting SSL verification parameters in a new client:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## import httpclient
|
||||
## var client = newHttpClient(sslContext=newContext(verifyMode=CVerifyPeer))
|
||||
## ```Nim
|
||||
## import httpclient
|
||||
## var client = newHttpClient(sslContext=newContext(verifyMode=CVerifyPeer))
|
||||
## ```
|
||||
##
|
||||
## There are three options for verify mode:
|
||||
##
|
||||
@@ -183,10 +191,11 @@
|
||||
##
|
||||
## Here is how to set a timeout when creating an `HttpClient` instance:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## import std/httpclient
|
||||
## ```Nim
|
||||
## import std/httpclient
|
||||
##
|
||||
## let client = newHttpClient(timeout = 42)
|
||||
## let client = newHttpClient(timeout = 42)
|
||||
## ```
|
||||
##
|
||||
## Proxy
|
||||
## =====
|
||||
@@ -197,36 +206,39 @@
|
||||
##
|
||||
## Some examples on how to configure a Proxy for `HttpClient`:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## import std/httpclient
|
||||
## ```Nim
|
||||
## import std/httpclient
|
||||
##
|
||||
## let myProxy = newProxy("http://myproxy.network")
|
||||
## let client = newHttpClient(proxy = myProxy)
|
||||
## let myProxy = newProxy("http://myproxy.network")
|
||||
## let client = newHttpClient(proxy = myProxy)
|
||||
## ```
|
||||
##
|
||||
## Use proxies with basic authentication:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## import std/httpclient
|
||||
##
|
||||
## let myProxy = newProxy("http://myproxy.network", auth="user:password")
|
||||
## let client = newHttpClient(proxy = myProxy)
|
||||
## ```Nim
|
||||
## import std/httpclient
|
||||
##
|
||||
## let myProxy = newProxy("http://myproxy.network", auth="user:password")
|
||||
## let client = newHttpClient(proxy = myProxy)
|
||||
## ```
|
||||
##
|
||||
## Get Proxy URL from environment variables:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## import std/httpclient
|
||||
## ```Nim
|
||||
## import std/httpclient
|
||||
##
|
||||
## var url = ""
|
||||
## try:
|
||||
## if existsEnv("http_proxy"):
|
||||
## url = getEnv("http_proxy")
|
||||
## elif existsEnv("https_proxy"):
|
||||
## url = getEnv("https_proxy")
|
||||
## except ValueError:
|
||||
## echo "Unable to parse proxy from environment variables."
|
||||
## var url = ""
|
||||
## try:
|
||||
## if existsEnv("http_proxy"):
|
||||
## url = getEnv("http_proxy")
|
||||
## elif existsEnv("https_proxy"):
|
||||
## url = getEnv("https_proxy")
|
||||
## except ValueError:
|
||||
## echo "Unable to parse proxy from environment variables."
|
||||
##
|
||||
## let myProxy = newProxy(url = url)
|
||||
## let client = newHttpClient(proxy = myProxy)
|
||||
## let myProxy = newProxy(url = url)
|
||||
## let client = newHttpClient(proxy = myProxy)
|
||||
## ```
|
||||
##
|
||||
## Redirects
|
||||
## =========
|
||||
@@ -237,10 +249,11 @@
|
||||
##
|
||||
## Here you can see an example about how to set the `maxRedirects` of `HttpClient`:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## import std/httpclient
|
||||
## ```Nim
|
||||
## import std/httpclient
|
||||
##
|
||||
## let client = newHttpClient(maxRedirects = 0)
|
||||
## let client = newHttpClient(maxRedirects = 0)
|
||||
## ```
|
||||
##
|
||||
|
||||
import std/private/since
|
||||
@@ -429,8 +442,9 @@ proc add*(p: MultipartData, xs: MultipartEntries): MultipartData
|
||||
## Add a list of multipart entries to the multipart data `p`. All values are
|
||||
## added without a filename and without a content type.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## data.add({"action": "login", "format": "json"})
|
||||
## ```
|
||||
for name, content in xs.items:
|
||||
p.add(name, content)
|
||||
result = p
|
||||
@@ -439,8 +453,9 @@ proc newMultipartData*(xs: MultipartEntries): MultipartData =
|
||||
## Create a new multipart data object and fill it with the entries `xs`
|
||||
## directly.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## var data = newMultipartData({"action": "login", "format": "json"})
|
||||
## ```
|
||||
result = MultipartData()
|
||||
for entry in xs:
|
||||
result.add(entry.name, entry.content)
|
||||
@@ -455,8 +470,9 @@ proc addFiles*(p: MultipartData, xs: openArray[tuple[name, file: string]],
|
||||
## Raises an `IOError` if the file cannot be opened or reading fails. To
|
||||
## manually specify file content, filename and MIME type, use `[]=` instead.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## data.addFiles({"uploaded_file": "public/test.html"})
|
||||
## ```
|
||||
for name, file in xs.items:
|
||||
var contentType: string
|
||||
let (_, fName, ext) = splitFile(file)
|
||||
@@ -470,8 +486,9 @@ proc `[]=`*(p: MultipartData, name, content: string) {.inline.} =
|
||||
## Add a multipart entry to the multipart data `p`. The value is added
|
||||
## without a filename and without a content type.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## data["username"] = "NimUser"
|
||||
## ```
|
||||
p.add(name, content)
|
||||
|
||||
proc `[]=`*(p: MultipartData, name: string,
|
||||
@@ -479,9 +496,10 @@ proc `[]=`*(p: MultipartData, name: string,
|
||||
## Add a file to the multipart data `p`, specifying filename, contentType
|
||||
## and content manually.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## data["uploaded_file"] = ("test.html", "text/html",
|
||||
## "<html><head></head><body><p>test</p></body></html>")
|
||||
## ```
|
||||
p.add(name, file.content, file.name, file.contentType, useStream = false)
|
||||
|
||||
proc getBoundary(p: MultipartData): string =
|
||||
@@ -688,15 +706,15 @@ proc close*(client: HttpClient | AsyncHttpClient) =
|
||||
client.connected = false
|
||||
|
||||
proc getSocket*(client: HttpClient): Socket {.inline.} =
|
||||
## Get network socket, useful if you want to find out more details about the connection
|
||||
## Get network socket, useful if you want to find out more details about the connection.
|
||||
##
|
||||
## this example shows info about local and remote endpoints
|
||||
## This example shows info about local and remote endpoints:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## if client.connected:
|
||||
## echo client.getSocket.getLocalAddr
|
||||
## echo client.getSocket.getPeerAddr
|
||||
##
|
||||
## ```
|
||||
return client.socket
|
||||
|
||||
proc getSocket*(client: AsyncHttpClient): AsyncSocket {.inline.} =
|
||||
|
||||
@@ -41,13 +41,14 @@
|
||||
## For a `JsonNode` who's kind is `JObject`, you can access its fields using
|
||||
## the `[]` operator. The following example shows how to do this:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/json
|
||||
##
|
||||
## let jsonNode = parseJson("""{"key": 3.14}""")
|
||||
##
|
||||
## doAssert jsonNode.kind == JObject
|
||||
## doAssert jsonNode["key"].kind == JFloat
|
||||
## ```
|
||||
##
|
||||
## Reading values
|
||||
## --------------
|
||||
@@ -62,12 +63,13 @@
|
||||
##
|
||||
## To retrieve the value of `"key"` you can do the following:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/json
|
||||
##
|
||||
## let jsonNode = parseJson("""{"key": 3.14}""")
|
||||
##
|
||||
## doAssert jsonNode["key"].getFloat() == 3.14
|
||||
## ```
|
||||
##
|
||||
## **Important:** The `[]` operator will raise an exception when the
|
||||
## specified field does not exist.
|
||||
@@ -79,7 +81,7 @@
|
||||
## when the field is not found. The `get`-family of procedures will return a
|
||||
## type's default value when called on `nil`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/json
|
||||
##
|
||||
## let jsonNode = parseJson("{}")
|
||||
@@ -88,6 +90,7 @@
|
||||
## doAssert jsonNode{"nope"}.getFloat() == 0
|
||||
## doAssert jsonNode{"nope"}.getStr() == ""
|
||||
## doAssert jsonNode{"nope"}.getBool() == false
|
||||
## ```
|
||||
##
|
||||
## Using default values
|
||||
## --------------------
|
||||
@@ -95,7 +98,7 @@
|
||||
## The `get`-family helpers also accept an additional parameter which allow
|
||||
## you to fallback to a default value should the key's values be `null`:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/json
|
||||
##
|
||||
## let jsonNode = parseJson("""{"key": 3.14, "key2": null}""")
|
||||
@@ -103,6 +106,7 @@
|
||||
## doAssert jsonNode["key"].getFloat(6.28) == 3.14
|
||||
## doAssert jsonNode["key2"].getFloat(3.14) == 3.14
|
||||
## doAssert jsonNode{"nope"}.getFloat(3.14) == 3.14 # note the {}
|
||||
## ```
|
||||
##
|
||||
## Unmarshalling
|
||||
## -------------
|
||||
@@ -113,7 +117,7 @@
|
||||
## Note: Use `Option <options.html#Option>`_ for keys sometimes missing in json
|
||||
## responses, and backticks around keys with a reserved keyword as name.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/json
|
||||
## import std/options
|
||||
##
|
||||
@@ -127,6 +131,7 @@
|
||||
## let user = to(userJson, User)
|
||||
## if user.`type`.isSome():
|
||||
## assert user.`type`.get() != "robot"
|
||||
## ```
|
||||
##
|
||||
## Creating JSON
|
||||
## =============
|
||||
@@ -134,7 +139,7 @@
|
||||
## This module can also be used to comfortably create JSON using the `%*`
|
||||
## operator:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## import std/json
|
||||
##
|
||||
## var hisName = "John"
|
||||
@@ -148,6 +153,7 @@
|
||||
## var j2 = %* {"name": "Isaac", "books": ["Robot Dreams"]}
|
||||
## j2["details"] = %* {"age":35, "pi":3.1415}
|
||||
## echo j2
|
||||
## ```
|
||||
##
|
||||
## See also: std/jsonutils for hookable json serialization/deserialization
|
||||
## of arbitrary types.
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
##
|
||||
## To get started, first create a logger:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## import std/logging
|
||||
##
|
||||
## var logger = newConsoleLogger()
|
||||
## ```
|
||||
##
|
||||
## The logger that was created above logs to the console, but this module
|
||||
## also provides loggers that log to files, such as the
|
||||
@@ -30,9 +31,10 @@
|
||||
## Once a logger has been created, call its `log proc
|
||||
## <#log.e,ConsoleLogger,Level,varargs[string,]>`_ to log a message:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## logger.log(lvlInfo, "a log message")
|
||||
## # Output: INFO a log message
|
||||
## ```
|
||||
##
|
||||
## The ``INFO`` within the output is the result of a format string being
|
||||
## prepended to the message, and it will differ depending on the message's
|
||||
@@ -58,7 +60,7 @@
|
||||
## used with the `addHandler proc<#addHandler,Logger>`_, which is demonstrated
|
||||
## in the following example:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## import std/logging
|
||||
##
|
||||
## var consoleLog = newConsoleLogger()
|
||||
@@ -68,17 +70,19 @@
|
||||
## addHandler(consoleLog)
|
||||
## addHandler(fileLog)
|
||||
## addHandler(rollingLog)
|
||||
## ```
|
||||
##
|
||||
## After doing this, use either the `log template
|
||||
## <#log.t,Level,varargs[string,]>`_ or one of the level-specific templates,
|
||||
## such as the `error template<#error.t,varargs[string,]>`_, to log messages
|
||||
## to all registered handlers at once.
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## # This example uses the loggers created above
|
||||
## log(lvlError, "an error occurred")
|
||||
## error("an error occurred") # Equivalent to the above line
|
||||
## info("something normal happened") # Will not be written to errors.log
|
||||
## ```
|
||||
##
|
||||
## Note that a message's level is still checked against each handler's
|
||||
## ``levelThreshold`` and the global log filter.
|
||||
@@ -116,12 +120,13 @@
|
||||
##
|
||||
## The following example illustrates how to use format strings:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## import std/logging
|
||||
##
|
||||
## var logger = newConsoleLogger(fmtStr="[$time] - $levelname: ")
|
||||
## logger.log(lvlInfo, "this is a message")
|
||||
## # Output: [19:50:13] - INFO: this is a message
|
||||
## ```
|
||||
##
|
||||
## Notes when using multiple threads
|
||||
## ---------------------------------
|
||||
@@ -372,10 +377,11 @@ method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var consoleLog = newConsoleLogger()
|
||||
## consoleLog.log(lvlInfo, "this is a message")
|
||||
## consoleLog.log(lvlError, "error code is: ", 404)
|
||||
## ```
|
||||
if level >= logging.level and level >= logger.levelThreshold:
|
||||
let ln = substituteLog(logger.fmtStr, level, args)
|
||||
when defined(js):
|
||||
@@ -414,10 +420,11 @@ proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr,
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var normalLog = newConsoleLogger()
|
||||
## var formatLog = newConsoleLogger(fmtStr=verboseFmtStr)
|
||||
## var errorLog = newConsoleLogger(levelThreshold=lvlError, useStderr=true)
|
||||
## ```
|
||||
new result
|
||||
result.fmtStr = fmtStr
|
||||
result.levelThreshold = levelThreshold
|
||||
@@ -450,10 +457,11 @@ when not defined(js):
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var fileLog = newFileLogger("messages.log")
|
||||
## fileLog.log(lvlInfo, "this is a message")
|
||||
## fileLog.log(lvlError, "error code is: ", 404)
|
||||
## ```
|
||||
if level >= logging.level and level >= logger.levelThreshold:
|
||||
writeLine(logger.file, substituteLog(logger.fmtStr, level, args))
|
||||
if level >= logger.flushThreshold: flushFile(logger.file)
|
||||
@@ -481,7 +489,7 @@ when not defined(js):
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var messages = open("messages.log", fmWrite)
|
||||
## var formatted = open("formatted.log", fmWrite)
|
||||
## var errors = open("errors.log", fmWrite)
|
||||
@@ -489,6 +497,7 @@ when not defined(js):
|
||||
## var normalLog = newFileLogger(messages)
|
||||
## var formatLog = newFileLogger(formatted, fmtStr=verboseFmtStr)
|
||||
## var errorLog = newFileLogger(errors, levelThreshold=lvlError)
|
||||
## ```
|
||||
new(result)
|
||||
result.file = file
|
||||
result.levelThreshold = levelThreshold
|
||||
@@ -519,10 +528,11 @@ when not defined(js):
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var normalLog = newFileLogger("messages.log")
|
||||
## var formatLog = newFileLogger("formatted.log", fmtStr=verboseFmtStr)
|
||||
## var errorLog = newFileLogger("errors.log", levelThreshold=lvlError)
|
||||
## ```
|
||||
let file = open(filename, mode, bufSize = bufSize)
|
||||
newFileLogger(file, levelThreshold, fmtStr, flushThreshold)
|
||||
|
||||
@@ -579,11 +589,12 @@ when not defined(js):
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var normalLog = newRollingFileLogger("messages.log")
|
||||
## var formatLog = newRollingFileLogger("formatted.log", fmtStr=verboseFmtStr)
|
||||
## var shortLog = newRollingFileLogger("short.log", maxLines=200)
|
||||
## var errorLog = newRollingFileLogger("errors.log", levelThreshold=lvlError)
|
||||
## ```
|
||||
new(result)
|
||||
result.levelThreshold = levelThreshold
|
||||
result.fmtStr = fmtStr
|
||||
@@ -633,10 +644,11 @@ when not defined(js):
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var rollingLog = newRollingFileLogger("messages.log")
|
||||
## rollingLog.log(lvlInfo, "this is a message")
|
||||
## rollingLog.log(lvlError, "error code is: ", 404)
|
||||
## ```
|
||||
if level >= logging.level and level >= logger.levelThreshold:
|
||||
if logger.curLine >= logger.maxLines:
|
||||
logger.file.close()
|
||||
@@ -666,11 +678,12 @@ template log*(level: Level, args: varargs[string, `$`]) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var logger = newConsoleLogger()
|
||||
## addHandler(logger)
|
||||
##
|
||||
## log(lvlInfo, "This is an example.")
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `debug template<#debug.t,varargs[string,]>`_
|
||||
@@ -695,11 +708,12 @@ template debug*(args: varargs[string, `$`]) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var logger = newConsoleLogger()
|
||||
## addHandler(logger)
|
||||
##
|
||||
## debug("myProc called with arguments: foo, 5")
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `log template<#log.t,Level,varargs[string,]>`_
|
||||
@@ -716,11 +730,12 @@ template info*(args: varargs[string, `$`]) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var logger = newConsoleLogger()
|
||||
## addHandler(logger)
|
||||
##
|
||||
## info("Application started successfully.")
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `log template<#log.t,Level,varargs[string,]>`_
|
||||
@@ -737,11 +752,12 @@ template notice*(args: varargs[string, `$`]) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var logger = newConsoleLogger()
|
||||
## addHandler(logger)
|
||||
##
|
||||
## notice("An important operation has completed.")
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `log template<#log.t,Level,varargs[string,]>`_
|
||||
@@ -757,11 +773,12 @@ template warn*(args: varargs[string, `$`]) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var logger = newConsoleLogger()
|
||||
## addHandler(logger)
|
||||
##
|
||||
## warn("The previous operation took too long to process.")
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `log template<#log.t,Level,varargs[string,]>`_
|
||||
@@ -779,11 +796,12 @@ template error*(args: varargs[string, `$`]) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var logger = newConsoleLogger()
|
||||
## addHandler(logger)
|
||||
##
|
||||
## error("An exception occurred while processing the form.")
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `log template<#log.t,Level,varargs[string,]>`_
|
||||
@@ -800,11 +818,12 @@ template fatal*(args: varargs[string, `$`]) =
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var logger = newConsoleLogger()
|
||||
## addHandler(logger)
|
||||
##
|
||||
## fatal("Can't open database -- exiting.")
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `log template<#log.t,Level,varargs[string,]>`_
|
||||
|
||||
@@ -150,7 +150,7 @@ proc open*(filename: string, mode: FileMode = fmRead,
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## var
|
||||
## mm, mm_full, mm_half: MemFile
|
||||
##
|
||||
@@ -162,6 +162,7 @@ proc open*(filename: string, mode: FileMode = fmRead,
|
||||
##
|
||||
## # Read the first 512 bytes
|
||||
## mm_half = memfiles.open("/tmp/test.mmap", mode = fmReadWrite, mappedSize = 512)
|
||||
## ```
|
||||
|
||||
# The file can be resized only when write mode is used:
|
||||
if mode == fmAppend:
|
||||
@@ -443,13 +444,13 @@ iterator memSlices*(mfile: MemFile, delim = '\l', eat = '\r'): MemSlice {.inline
|
||||
## functions, not str* functions).
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## var count = 0
|
||||
## for slice in memSlices(memfiles.open("foo")):
|
||||
## if slice.size > 0 and cast[cstring](slice.data)[0] != '#':
|
||||
## inc(count)
|
||||
## echo count
|
||||
## ```
|
||||
|
||||
proc c_memchr(cstr: pointer, c: char, n: csize_t): pointer {.
|
||||
importc: "memchr", header: "<string.h>".}
|
||||
@@ -479,11 +480,11 @@ iterator lines*(mfile: MemFile, buf: var string, delim = '\l',
|
||||
## <#memSlices.i,MemFile,char,char>`_, but Nim strings are returned.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## var buffer: string = ""
|
||||
## for line in lines(memfiles.open("foo"), buffer):
|
||||
## echo line
|
||||
## ```
|
||||
|
||||
for ms in memSlices(mfile, delim, eat):
|
||||
setLen(buf, ms.size)
|
||||
@@ -498,10 +499,10 @@ iterator lines*(mfile: MemFile, delim = '\l', eat = '\r'): string {.inline.} =
|
||||
## <#memSlices.i,MemFile,char,char>`_, but Nim strings are returned.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for line in lines(memfiles.open("foo")):
|
||||
## echo line
|
||||
## ```
|
||||
|
||||
var buf = newStringOfCap(80)
|
||||
for line in lines(mfile, buf, delim, eat):
|
||||
|
||||
@@ -53,7 +53,7 @@ Pattern matching
|
||||
supports pattern matching on `Option`s, with the `Some(<pattern>)` and
|
||||
`None()` patterns.
|
||||
|
||||
.. code-block:: nim
|
||||
```nim
|
||||
{.experimental: "caseStmtMacros".}
|
||||
|
||||
import fusion/matching
|
||||
@@ -65,6 +65,7 @@ supports pattern matching on `Option`s, with the `Some(<pattern>)` and
|
||||
assert false
|
||||
|
||||
assertMatch(some(some(none(int))), Some(Some(None())))
|
||||
```
|
||||
]##
|
||||
# xxx pending https://github.com/timotheecour/Nim/issues/376 use `runnableExamples` and `whichModule`
|
||||
|
||||
|
||||
@@ -411,9 +411,9 @@ proc execShellCmd*(command: string): int {.rtl, extern: "nos$1",
|
||||
## <osproc.html#execProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_.
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## discard execShellCmd("ls -la")
|
||||
## ```
|
||||
result = exitStatusLikeShell(c_system(command))
|
||||
|
||||
proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
|
||||
@@ -482,18 +482,18 @@ proc inclFilePermissions*(filename: string,
|
||||
permissions: set[FilePermission]) {.
|
||||
rtl, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect], noWeirdTarget.} =
|
||||
## A convenience proc for:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## setFilePermissions(filename, getFilePermissions(filename)+permissions)
|
||||
## ```
|
||||
setFilePermissions(filename, getFilePermissions(filename)+permissions)
|
||||
|
||||
proc exclFilePermissions*(filename: string,
|
||||
permissions: set[FilePermission]) {.
|
||||
rtl, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect], noWeirdTarget.} =
|
||||
## A convenience proc for:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## setFilePermissions(filename, getFilePermissions(filename)-permissions)
|
||||
## ```
|
||||
setFilePermissions(filename, getFilePermissions(filename)-permissions)
|
||||
|
||||
when not weirdTarget and (defined(freebsd) or defined(dragonfly) or defined(netbsd)):
|
||||
|
||||
@@ -91,12 +91,12 @@ proc execProcess*(command: string, workingDir: string = "",
|
||||
## * `execCmd proc <#execCmd,string>`_
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let outp = execProcess("nim", args=["c", "-r", "mytestfile.nim"], options={poUsePath})
|
||||
## let outp_shell = execProcess("nim c -r mytestfile.nim")
|
||||
## # Note: outp may have an interleave of text from the nim compile
|
||||
## # and any output from mytestfile when it runs
|
||||
## ```Nim
|
||||
## let outp = execProcess("nim", args=["c", "-r", "mytestfile.nim"], options={poUsePath})
|
||||
## let outp_shell = execProcess("nim c -r mytestfile.nim")
|
||||
## # Note: outp may have an interleave of text from the nim compile
|
||||
## # and any output from mytestfile when it runs
|
||||
## ```
|
||||
|
||||
proc execCmd*(command: string): int {.rtl, extern: "nosp$1",
|
||||
tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
|
||||
@@ -113,9 +113,9 @@ proc execCmd*(command: string): int {.rtl, extern: "nosp$1",
|
||||
## <#execProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let errC = execCmd("nim c -r mytestfile.nim")
|
||||
## ```Nim
|
||||
## let errC = execCmd("nim c -r mytestfile.nim")
|
||||
## ```
|
||||
|
||||
proc startProcess*(command: string, workingDir: string = "",
|
||||
args: openArray[string] = [], env: StringTableRef = nil,
|
||||
@@ -465,8 +465,7 @@ iterator lines*(p: Process, keepNewLines = false): string {.since: (1, 3), raise
|
||||
## * `readLines proc <#readLines,Process>`_
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## const opts = {poUsePath, poDaemon, poStdErrToStdOut}
|
||||
## var ps: seq[Process]
|
||||
## for prog in ["a", "b"]: # run 2 progs in parallel
|
||||
@@ -478,6 +477,7 @@ iterator lines*(p: Process, keepNewLines = false): string {.since: (1, 3), raise
|
||||
## i.inc
|
||||
## if i > 100: break
|
||||
## p.close
|
||||
## ```
|
||||
var outp = p.outputStream
|
||||
var line = newStringOfCap(120)
|
||||
while outp.readLine(line):
|
||||
@@ -495,8 +495,7 @@ proc readLines*(p: Process): (seq[string], int) {.since: (1, 3),
|
||||
## * `lines iterator <#lines.i,Process>`_
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## const opts = {poUsePath, poDaemon, poStdErrToStdOut}
|
||||
## var ps: seq[Process]
|
||||
## for prog in ["a", "b"]: # run 2 progs in parallel
|
||||
@@ -506,6 +505,7 @@ proc readLines*(p: Process): (seq[string], int) {.since: (1, 3),
|
||||
## if exCode != 0:
|
||||
## for line in lines: echo line
|
||||
## p.close
|
||||
## ```
|
||||
for line in p.lines: result[0].add(line)
|
||||
result[1] = p.peekExitCode
|
||||
|
||||
@@ -1587,8 +1587,7 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
|
||||
## <#execProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## var result = execCmdEx("nim r --hints:off -", options = {}, input = "echo 3*4")
|
||||
## import std/[strutils, strtabs]
|
||||
## stripLineEnd(result[0]) ## portable way to remove trailing newline, if any
|
||||
@@ -1597,6 +1596,7 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
|
||||
## when defined(posix):
|
||||
## assert execCmdEx("echo $FO", env = newStringTable({"FO": "B"})) == ("B\n", 0)
|
||||
## assert execCmdEx("echo $PWD", workingDir = "/") == ("/\n", 0)
|
||||
## ```
|
||||
|
||||
when (NimMajor, NimMinor, NimPatch) < (1, 3, 5):
|
||||
doAssert input.len == 0
|
||||
|
||||
@@ -45,9 +45,7 @@ runnableExamples("-r:off"):
|
||||
## Configuration file example
|
||||
]##
|
||||
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```none
|
||||
## charset = "utf-8"
|
||||
## [Package]
|
||||
## name = "hello"
|
||||
@@ -55,6 +53,7 @@ runnableExamples("-r:off"):
|
||||
## [Author]
|
||||
## name = "nim-lang"
|
||||
## website = "nim-lang.org"
|
||||
## ```
|
||||
|
||||
##[
|
||||
## Creating a configuration file
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
## Basic usage
|
||||
## ===========
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## import std/parsecsv
|
||||
## from std/os import paramStr
|
||||
## from std/streams import newFileStream
|
||||
@@ -29,11 +29,12 @@
|
||||
## for val in items(x.row):
|
||||
## echo "##", val, "##"
|
||||
## close(x)
|
||||
## ```
|
||||
##
|
||||
## For CSV files with a header row, the header can be read and then used as a
|
||||
## reference for item access with `rowEntry <#rowEntry,CsvParser,string>`_:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## import std/parsecsv
|
||||
##
|
||||
## # Prepare a file
|
||||
@@ -52,6 +53,7 @@
|
||||
## for col in items(p.headers):
|
||||
## echo "##", col, ":", p.rowEntry(col), "##"
|
||||
## p.close()
|
||||
## ```
|
||||
##
|
||||
## See also
|
||||
## ========
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
##
|
||||
## Here is an example:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## import std/parseopt
|
||||
##
|
||||
## var p = initOptParser("-ab -e:5 --foo --bar=20 file.txt")
|
||||
@@ -71,6 +71,7 @@
|
||||
## # Option: foo
|
||||
## # Option and value: bar, 20
|
||||
## # Argument: file.txt
|
||||
## ```
|
||||
##
|
||||
## The `getopt iterator<#getopt.i,OptParser>`_, which is provided for
|
||||
## convenience, can be used to iterate through all command line options as well.
|
||||
@@ -80,7 +81,8 @@
|
||||
## Then set the variable to the new value while parsing.
|
||||
##
|
||||
## Here is an example:
|
||||
## .. code-block::
|
||||
##
|
||||
## ```Nim
|
||||
## import std/parseopt
|
||||
##
|
||||
## var varName: string = "defaultValue"
|
||||
@@ -95,6 +97,7 @@
|
||||
## varName = val # do input sanitization in production systems
|
||||
## of cmdEnd:
|
||||
## discard
|
||||
## ```
|
||||
##
|
||||
## `shortNoVal` and `longNoVal`
|
||||
## ============================
|
||||
@@ -119,7 +122,7 @@
|
||||
## `shortNoVal` and `longNoVal`, which is the default, and providing
|
||||
## arguments for those two parameters:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## import std/parseopt
|
||||
##
|
||||
## proc printToken(kind: CmdLineKind, key: string, val: string) =
|
||||
@@ -153,6 +156,7 @@
|
||||
## # Output:
|
||||
## # Option and value: j, 4
|
||||
## # Option and value: first, bar
|
||||
## ```
|
||||
##
|
||||
## See also
|
||||
## ========
|
||||
@@ -387,14 +391,14 @@ when declared(quoteShellCommand):
|
||||
## * `remainingArgs proc<#remainingArgs,OptParser>`_
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
|
||||
## while true:
|
||||
## p.next()
|
||||
## if p.kind == cmdLongOption and p.key == "": # Look for "--"
|
||||
## break
|
||||
## doAssert p.cmdLineRest == "foo.txt bar.txt"
|
||||
## ```
|
||||
result = p.cmds[p.idx .. ^1].quoteShellCommand
|
||||
|
||||
proc remainingArgs*(p: OptParser): seq[string] {.rtl, extern: "npo$1".} =
|
||||
@@ -404,14 +408,14 @@ proc remainingArgs*(p: OptParser): seq[string] {.rtl, extern: "npo$1".} =
|
||||
## * `cmdLineRest proc<#cmdLineRest,OptParser>`_
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
|
||||
## while true:
|
||||
## p.next()
|
||||
## if p.kind == cmdLongOption and p.key == "": # Look for "--"
|
||||
## break
|
||||
## doAssert p.remainingArgs == @["foo.txt", "bar.txt"]
|
||||
## ```
|
||||
result = @[]
|
||||
for i in p.idx..<p.cmds.len: result.add p.cmds[i]
|
||||
|
||||
@@ -428,7 +432,7 @@ iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key,
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
## ```Nim
|
||||
## # these are placeholders, of course
|
||||
## proc writeHelp() = discard
|
||||
## proc writeVersion() = discard
|
||||
@@ -448,6 +452,7 @@ iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key,
|
||||
## if filename == "":
|
||||
## # no filename has been given, so we show the help
|
||||
## writeHelp()
|
||||
## ```
|
||||
p.pos = 0
|
||||
p.idx = 0
|
||||
while true:
|
||||
@@ -477,8 +482,7 @@ iterator getopt*(cmdline: seq[string] = @[],
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block::
|
||||
##
|
||||
## ```Nim
|
||||
## # these are placeholders, of course
|
||||
## proc writeHelp() = discard
|
||||
## proc writeVersion() = discard
|
||||
@@ -498,6 +502,7 @@ iterator getopt*(cmdline: seq[string] = @[],
|
||||
## if filename == "":
|
||||
## # no filename has been written, so we show the help
|
||||
## writeHelp()
|
||||
## ```
|
||||
var p = initOptParser(cmdline, shortNoVal = shortNoVal,
|
||||
longNoVal = longNoVal)
|
||||
while true:
|
||||
|
||||
@@ -12,29 +12,28 @@
|
||||
##
|
||||
## To unpack raw bytes look at the `streams <streams.html>`_ module.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## :test:
|
||||
## ```nim test
|
||||
## let logs = @["2019-01-10: OK_", "2019-01-11: FAIL_", "2019-01: aaaa"]
|
||||
## var outp: seq[string]
|
||||
##
|
||||
## let logs = @["2019-01-10: OK_", "2019-01-11: FAIL_", "2019-01: aaaa"]
|
||||
## var outp: seq[string]
|
||||
## for log in logs:
|
||||
## var res: string
|
||||
## if parseUntil(log, res, ':') == 10: # YYYY-MM-DD == 10
|
||||
## outp.add(res & " - " & captureBetween(log, ' ', '_'))
|
||||
## doAssert outp == @["2019-01-10 - OK", "2019-01-11 - FAIL"]
|
||||
## ```
|
||||
##
|
||||
## for log in logs:
|
||||
## var res: string
|
||||
## if parseUntil(log, res, ':') == 10: # YYYY-MM-DD == 10
|
||||
## outp.add(res & " - " & captureBetween(log, ' ', '_'))
|
||||
## doAssert outp == @["2019-01-10 - OK", "2019-01-11 - FAIL"]
|
||||
## ```nim test
|
||||
## from std/strutils import Digits, parseInt
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## :test:
|
||||
## from std/strutils import Digits, parseInt
|
||||
##
|
||||
## let
|
||||
## input1 = "2019 school start"
|
||||
## input2 = "3 years back"
|
||||
## startYear = input1[0 .. skipWhile(input1, Digits)-1] # 2019
|
||||
## yearsBack = input2[0 .. skipWhile(input2, Digits)-1] # 3
|
||||
## examYear = parseInt(startYear) + parseInt(yearsBack)
|
||||
## doAssert "Examination is in " & $examYear == "Examination is in 2022"
|
||||
## let
|
||||
## input1 = "2019 school start"
|
||||
## input2 = "3 years back"
|
||||
## startYear = input1[0 .. skipWhile(input1, Digits)-1] # 2019
|
||||
## yearsBack = input2[0 .. skipWhile(input2, Digits)-1] # 3
|
||||
## examYear = parseInt(startYear) + parseInt(yearsBack)
|
||||
## doAssert "Examination is in " & $examYear == "Examination is in 2022"
|
||||
## ```
|
||||
##
|
||||
## **See also:**
|
||||
## * `strutils module<strutils.html>`_ for combined and identical parsing proc's
|
||||
|
||||
@@ -36,43 +36,43 @@ The file ``examples/htmltitle.nim`` demonstrates how to use the
|
||||
XML parser to accomplish a simple task: To determine the title of an HTML
|
||||
document.
|
||||
|
||||
.. code-block:: nim
|
||||
```nim
|
||||
# Example program to show the parsexml module
|
||||
# This program reads an HTML file and writes its title to stdout.
|
||||
# Errors and whitespace are ignored.
|
||||
|
||||
# Example program to show the parsexml module
|
||||
# This program reads an HTML file and writes its title to stdout.
|
||||
# Errors and whitespace are ignored.
|
||||
import os, streams, parsexml, strutils
|
||||
|
||||
import os, streams, parsexml, strutils
|
||||
if paramCount() < 1:
|
||||
quit("Usage: htmltitle filename[.html]")
|
||||
|
||||
if paramCount() < 1:
|
||||
quit("Usage: htmltitle filename[.html]")
|
||||
var filename = addFileExt(paramStr(1), "html")
|
||||
var s = newFileStream(filename, fmRead)
|
||||
if s == nil: quit("cannot open the file " & filename)
|
||||
var x: XmlParser
|
||||
open(x, s, filename)
|
||||
while true:
|
||||
x.next()
|
||||
case x.kind
|
||||
of xmlElementStart:
|
||||
if cmpIgnoreCase(x.elementName, "title") == 0:
|
||||
var title = ""
|
||||
x.next() # skip "<title>"
|
||||
while x.kind == xmlCharData:
|
||||
title.add(x.charData)
|
||||
x.next()
|
||||
if x.kind == xmlElementEnd and cmpIgnoreCase(x.elementName, "title") == 0:
|
||||
echo("Title: " & title)
|
||||
quit(0) # Success!
|
||||
else:
|
||||
echo(x.errorMsgExpected("/title"))
|
||||
|
||||
var filename = addFileExt(paramStr(1), "html")
|
||||
var s = newFileStream(filename, fmRead)
|
||||
if s == nil: quit("cannot open the file " & filename)
|
||||
var x: XmlParser
|
||||
open(x, s, filename)
|
||||
while true:
|
||||
x.next()
|
||||
case x.kind
|
||||
of xmlElementStart:
|
||||
if cmpIgnoreCase(x.elementName, "title") == 0:
|
||||
var title = ""
|
||||
x.next() # skip "<title>"
|
||||
while x.kind == xmlCharData:
|
||||
title.add(x.charData)
|
||||
x.next()
|
||||
if x.kind == xmlElementEnd and cmpIgnoreCase(x.elementName, "title") == 0:
|
||||
echo("Title: " & title)
|
||||
quit(0) # Success!
|
||||
else:
|
||||
echo(x.errorMsgExpected("/title"))
|
||||
of xmlEof: break # end of file reached
|
||||
else: discard # ignore other events
|
||||
|
||||
of xmlEof: break # end of file reached
|
||||
else: discard # ignore other events
|
||||
|
||||
x.close()
|
||||
quit("Could not determine title!")
|
||||
x.close()
|
||||
quit("Could not determine title!")
|
||||
```
|
||||
|
||||
]##
|
||||
|
||||
@@ -85,64 +85,64 @@ The file ``examples/htmlrefs.nim`` demonstrates how to use the
|
||||
XML parser to accomplish another simple task: To determine all the links
|
||||
an HTML document contains.
|
||||
|
||||
.. code-block:: nim
|
||||
```nim
|
||||
# Example program to show the new parsexml module
|
||||
# This program reads an HTML file and writes all its used links to stdout.
|
||||
# Errors and whitespace are ignored.
|
||||
|
||||
# Example program to show the new parsexml module
|
||||
# This program reads an HTML file and writes all its used links to stdout.
|
||||
# Errors and whitespace are ignored.
|
||||
import os, streams, parsexml, strutils
|
||||
|
||||
import os, streams, parsexml, strutils
|
||||
proc `=?=` (a, b: string): bool =
|
||||
# little trick: define our own comparator that ignores case
|
||||
return cmpIgnoreCase(a, b) == 0
|
||||
|
||||
proc `=?=` (a, b: string): bool =
|
||||
# little trick: define our own comparator that ignores case
|
||||
return cmpIgnoreCase(a, b) == 0
|
||||
if paramCount() < 1:
|
||||
quit("Usage: htmlrefs filename[.html]")
|
||||
|
||||
if paramCount() < 1:
|
||||
quit("Usage: htmlrefs filename[.html]")
|
||||
|
||||
var links = 0 # count the number of links
|
||||
var filename = addFileExt(paramStr(1), "html")
|
||||
var s = newFileStream(filename, fmRead)
|
||||
if s == nil: quit("cannot open the file " & filename)
|
||||
var x: XmlParser
|
||||
open(x, s, filename)
|
||||
next(x) # get first event
|
||||
block mainLoop:
|
||||
while true:
|
||||
case x.kind
|
||||
of xmlElementOpen:
|
||||
# the <a href = "xyz"> tag we are interested in always has an attribute,
|
||||
# thus we search for ``xmlElementOpen`` and not for ``xmlElementStart``
|
||||
if x.elementName =?= "a":
|
||||
x.next()
|
||||
if x.kind == xmlAttribute:
|
||||
if x.attrKey =?= "href":
|
||||
var link = x.attrValue
|
||||
inc(links)
|
||||
# skip until we have an ``xmlElementClose`` event
|
||||
while true:
|
||||
x.next()
|
||||
case x.kind
|
||||
of xmlEof: break mainLoop
|
||||
of xmlElementClose: break
|
||||
else: discard
|
||||
x.next() # skip ``xmlElementClose``
|
||||
# now we have the description for the ``a`` element
|
||||
var desc = ""
|
||||
while x.kind == xmlCharData:
|
||||
desc.add(x.charData)
|
||||
x.next()
|
||||
echo(desc & ": " & link)
|
||||
else:
|
||||
x.next()
|
||||
of xmlEof: break # end of file reached
|
||||
of xmlError:
|
||||
echo(errorMsg(x))
|
||||
var links = 0 # count the number of links
|
||||
var filename = addFileExt(paramStr(1), "html")
|
||||
var s = newFileStream(filename, fmRead)
|
||||
if s == nil: quit("cannot open the file " & filename)
|
||||
var x: XmlParser
|
||||
open(x, s, filename)
|
||||
next(x) # get first event
|
||||
block mainLoop:
|
||||
while true:
|
||||
case x.kind
|
||||
of xmlElementOpen:
|
||||
# the <a href = "xyz"> tag we are interested in always has an attribute,
|
||||
# thus we search for ``xmlElementOpen`` and not for ``xmlElementStart``
|
||||
if x.elementName =?= "a":
|
||||
x.next()
|
||||
else: x.next() # skip other events
|
||||
if x.kind == xmlAttribute:
|
||||
if x.attrKey =?= "href":
|
||||
var link = x.attrValue
|
||||
inc(links)
|
||||
# skip until we have an ``xmlElementClose`` event
|
||||
while true:
|
||||
x.next()
|
||||
case x.kind
|
||||
of xmlEof: break mainLoop
|
||||
of xmlElementClose: break
|
||||
else: discard
|
||||
x.next() # skip ``xmlElementClose``
|
||||
# now we have the description for the ``a`` element
|
||||
var desc = ""
|
||||
while x.kind == xmlCharData:
|
||||
desc.add(x.charData)
|
||||
x.next()
|
||||
echo(desc & ": " & link)
|
||||
else:
|
||||
x.next()
|
||||
of xmlEof: break # end of file reached
|
||||
of xmlError:
|
||||
echo(errorMsg(x))
|
||||
x.next()
|
||||
else: x.next() # skip other events
|
||||
|
||||
echo($links & " link(s) found!")
|
||||
x.close()
|
||||
echo($links & " link(s) found!")
|
||||
x.close()
|
||||
```
|
||||
|
||||
]##
|
||||
|
||||
|
||||
@@ -889,7 +889,7 @@ macro mkHandlerTplts(handlers: untyped): untyped =
|
||||
# Transforms the handler spec in *handlers* into handler templates.
|
||||
# The AST structure of *handlers[0]*:
|
||||
#
|
||||
# .. code-block::
|
||||
# ```
|
||||
# StmtList
|
||||
# Call
|
||||
# Ident "pkNonTerminal"
|
||||
@@ -910,6 +910,7 @@ macro mkHandlerTplts(handlers: untyped): untyped =
|
||||
# StmtList
|
||||
# <handler code block>
|
||||
# ...
|
||||
# ```
|
||||
func mkEnter(hdName, body: NimNode): NimNode =
|
||||
template helper(hdName, body) {.dirty.} =
|
||||
template hdName(s, p, start) =
|
||||
@@ -959,60 +960,61 @@ template eventParser*(pegAst, handlers: untyped): (proc(s: string): int) =
|
||||
## match, else the length of the total match. The following example code
|
||||
## evaluates an arithmetic expression defined by a simple PEG:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## import std/[strutils, pegs]
|
||||
## ```nim
|
||||
## import std/[strutils, pegs]
|
||||
##
|
||||
## let
|
||||
## pegAst = """
|
||||
## Expr <- Sum
|
||||
## Sum <- Product (('+' / '-')Product)*
|
||||
## Product <- Value (('*' / '/')Value)*
|
||||
## Value <- [0-9]+ / '(' Expr ')'
|
||||
## """.peg
|
||||
## txt = "(5+3)/2-7*22"
|
||||
## let
|
||||
## pegAst = """
|
||||
## Expr <- Sum
|
||||
## Sum <- Product (('+' / '-')Product)*
|
||||
## Product <- Value (('*' / '/')Value)*
|
||||
## Value <- [0-9]+ / '(' Expr ')'
|
||||
## """.peg
|
||||
## txt = "(5+3)/2-7*22"
|
||||
##
|
||||
## var
|
||||
## pStack: seq[string] = @[]
|
||||
## valStack: seq[float] = @[]
|
||||
## opStack = ""
|
||||
## let
|
||||
## parseArithExpr = pegAst.eventParser:
|
||||
## pkNonTerminal:
|
||||
## enter:
|
||||
## pStack.add p.nt.name
|
||||
## leave:
|
||||
## pStack.setLen pStack.high
|
||||
## if length > 0:
|
||||
## let matchStr = s.substr(start, start+length-1)
|
||||
## case p.nt.name
|
||||
## of "Value":
|
||||
## try:
|
||||
## valStack.add matchStr.parseFloat
|
||||
## echo valStack
|
||||
## except ValueError:
|
||||
## discard
|
||||
## of "Sum", "Product":
|
||||
## try:
|
||||
## let val = matchStr.parseFloat
|
||||
## except ValueError:
|
||||
## if valStack.len > 1 and opStack.len > 0:
|
||||
## valStack[^2] = case opStack[^1]
|
||||
## of '+': valStack[^2] + valStack[^1]
|
||||
## of '-': valStack[^2] - valStack[^1]
|
||||
## of '*': valStack[^2] * valStack[^1]
|
||||
## else: valStack[^2] / valStack[^1]
|
||||
## valStack.setLen valStack.high
|
||||
## echo valStack
|
||||
## opStack.setLen opStack.high
|
||||
## echo opStack
|
||||
## pkChar:
|
||||
## leave:
|
||||
## if length == 1 and "Value" != pStack[^1]:
|
||||
## let matchChar = s[start]
|
||||
## opStack.add matchChar
|
||||
## echo opStack
|
||||
## var
|
||||
## pStack: seq[string] = @[]
|
||||
## valStack: seq[float] = @[]
|
||||
## opStack = ""
|
||||
## let
|
||||
## parseArithExpr = pegAst.eventParser:
|
||||
## pkNonTerminal:
|
||||
## enter:
|
||||
## pStack.add p.nt.name
|
||||
## leave:
|
||||
## pStack.setLen pStack.high
|
||||
## if length > 0:
|
||||
## let matchStr = s.substr(start, start+length-1)
|
||||
## case p.nt.name
|
||||
## of "Value":
|
||||
## try:
|
||||
## valStack.add matchStr.parseFloat
|
||||
## echo valStack
|
||||
## except ValueError:
|
||||
## discard
|
||||
## of "Sum", "Product":
|
||||
## try:
|
||||
## let val = matchStr.parseFloat
|
||||
## except ValueError:
|
||||
## if valStack.len > 1 and opStack.len > 0:
|
||||
## valStack[^2] = case opStack[^1]
|
||||
## of '+': valStack[^2] + valStack[^1]
|
||||
## of '-': valStack[^2] - valStack[^1]
|
||||
## of '*': valStack[^2] * valStack[^1]
|
||||
## else: valStack[^2] / valStack[^1]
|
||||
## valStack.setLen valStack.high
|
||||
## echo valStack
|
||||
## opStack.setLen opStack.high
|
||||
## echo opStack
|
||||
## pkChar:
|
||||
## leave:
|
||||
## if length == 1 and "Value" != pStack[^1]:
|
||||
## let matchChar = s[start]
|
||||
## opStack.add matchChar
|
||||
## echo opStack
|
||||
##
|
||||
## let pLen = parseArithExpr(txt)
|
||||
## let pLen = parseArithExpr(txt)
|
||||
## ```
|
||||
##
|
||||
## The *handlers* parameter consists of code blocks for *PegKinds*,
|
||||
## which define the grammar elements of interest. Each block can contain
|
||||
@@ -1181,8 +1183,7 @@ template `=~`*(s: string, pattern: Peg): bool =
|
||||
## This calls ``match`` with an implicit declared ``matches`` array that
|
||||
## can be used in the scope of the ``=~`` call:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}":
|
||||
## # matches a key=value pair:
|
||||
## echo("Key: ", matches[0])
|
||||
@@ -1194,7 +1195,7 @@ template `=~`*(s: string, pattern: Peg): bool =
|
||||
## echo("comment: ", matches[0])
|
||||
## else:
|
||||
## echo("syntax error")
|
||||
##
|
||||
## ```
|
||||
bind MaxSubpatterns
|
||||
when not declaredInScope(matches):
|
||||
var matches {.inject.}: array[0..MaxSubpatterns-1, string]
|
||||
@@ -1230,14 +1231,15 @@ func replacef*(s: string, sub: Peg, by: string): string {.
|
||||
## Replaces `sub` in `s` by the string `by`. Captures can be accessed in `by`
|
||||
## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## "var1=key; var2=key2".replacef(peg"{\ident}'='{\ident}", "$1<-$2$2")
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## "var1<-keykey; val2<-key2key2"
|
||||
## ```
|
||||
result = ""
|
||||
var i = 0
|
||||
var caps: array[0..MaxSubpatterns-1, string]
|
||||
@@ -1305,8 +1307,7 @@ func replace*(s: string, sub: Peg, cb: proc(
|
||||
## The callback proc receives the index of the current match (starting with 0),
|
||||
## the count of captures and an open array with the captures of each match. Examples:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## func handleMatches*(m: int, n: int, c: openArray[string]): string =
|
||||
## result = ""
|
||||
## if m > 0:
|
||||
@@ -1318,12 +1319,13 @@ func replace*(s: string, sub: Peg, cb: proc(
|
||||
##
|
||||
## let s = "Var1=key1;var2=Key2; VAR3"
|
||||
## echo s.replace(peg"{\ident}('='{\ident})* ';'* \s*", handleMatches)
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## "var1: 'key1', var2: 'Key2', var3: ''"
|
||||
## ```
|
||||
result = ""
|
||||
var i = 0
|
||||
var caps: array[0..MaxSubpatterns-1, string]
|
||||
@@ -1361,18 +1363,19 @@ iterator split*(s: string, sep: Peg): string =
|
||||
## Substrings are separated by the PEG `sep`.
|
||||
## Examples:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for word in split("00232this02939is39an22example111", peg"\d+"):
|
||||
## writeLine(stdout, word)
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## "this"
|
||||
## "is"
|
||||
## "an"
|
||||
## "example"
|
||||
##
|
||||
## ```
|
||||
var c: Captures
|
||||
var
|
||||
first = 0
|
||||
|
||||
@@ -205,12 +205,11 @@ when defined(nimdoc):
|
||||
## to `value`. This `value` can be modified in the scope of
|
||||
## the `withData` call.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## s.withData(fd, value) do:
|
||||
## # block is executed only if `fd` registered in selector `s`
|
||||
## value.uid = 1000
|
||||
##
|
||||
## ```
|
||||
|
||||
template withData*[T](s: Selector[T], fd: SocketHandle|int, value,
|
||||
body1, body2: untyped) =
|
||||
@@ -218,15 +217,14 @@ when defined(nimdoc):
|
||||
## to `value`. This `value` can be modified in the scope of
|
||||
## the `withData` call.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## s.withData(fd, value) do:
|
||||
## # block is executed only if `fd` registered in selector `s`.
|
||||
## value.uid = 1000
|
||||
## do:
|
||||
## # block is executed if `fd` not registered in selector `s`.
|
||||
## raise
|
||||
##
|
||||
## ```
|
||||
|
||||
proc contains*[T](s: Selector[T], fd: SocketHandle|int): bool {.inline.} =
|
||||
## Determines whether selector contains a file descriptor.
|
||||
|
||||
@@ -27,67 +27,67 @@
|
||||
## StringStream example
|
||||
## --------------------
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/streams
|
||||
##
|
||||
## import std/streams
|
||||
## var strm = newStringStream("""The first line
|
||||
## the second line
|
||||
## the third line""")
|
||||
##
|
||||
## var strm = newStringStream("""The first line
|
||||
## the second line
|
||||
## the third line""")
|
||||
## var line = ""
|
||||
##
|
||||
## var line = ""
|
||||
## while strm.readLine(line):
|
||||
## echo line
|
||||
##
|
||||
## while strm.readLine(line):
|
||||
## echo line
|
||||
## # Output:
|
||||
## # The first line
|
||||
## # the second line
|
||||
## # the third line
|
||||
##
|
||||
## # Output:
|
||||
## # The first line
|
||||
## # the second line
|
||||
## # the third line
|
||||
##
|
||||
## strm.close()
|
||||
## strm.close()
|
||||
## ```
|
||||
##
|
||||
## FileStream example
|
||||
## ------------------
|
||||
##
|
||||
## Write file stream example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/streams
|
||||
##
|
||||
## import std/streams
|
||||
## var strm = newFileStream("somefile.txt", fmWrite)
|
||||
## var line = ""
|
||||
##
|
||||
## var strm = newFileStream("somefile.txt", fmWrite)
|
||||
## var line = ""
|
||||
## if not isNil(strm):
|
||||
## strm.writeLine("The first line")
|
||||
## strm.writeLine("the second line")
|
||||
## strm.writeLine("the third line")
|
||||
## strm.close()
|
||||
##
|
||||
## if not isNil(strm):
|
||||
## strm.writeLine("The first line")
|
||||
## strm.writeLine("the second line")
|
||||
## strm.writeLine("the third line")
|
||||
## strm.close()
|
||||
##
|
||||
## # Output (somefile.txt):
|
||||
## # The first line
|
||||
## # the second line
|
||||
## # the third line
|
||||
## # Output (somefile.txt):
|
||||
## # The first line
|
||||
## # the second line
|
||||
## # the third line
|
||||
## ```
|
||||
##
|
||||
## Read file stream example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/streams
|
||||
##
|
||||
## import std/streams
|
||||
## var strm = newFileStream("somefile.txt", fmRead)
|
||||
## var line = ""
|
||||
##
|
||||
## var strm = newFileStream("somefile.txt", fmRead)
|
||||
## var line = ""
|
||||
## if not isNil(strm):
|
||||
## while strm.readLine(line):
|
||||
## echo line
|
||||
## strm.close()
|
||||
##
|
||||
## if not isNil(strm):
|
||||
## while strm.readLine(line):
|
||||
## echo line
|
||||
## strm.close()
|
||||
##
|
||||
## # Output:
|
||||
## # The first line
|
||||
## # the second line
|
||||
## # the third line
|
||||
## # Output:
|
||||
## # The first line
|
||||
## # the second line
|
||||
## # the third line
|
||||
## ```
|
||||
##
|
||||
## See also
|
||||
## ========
|
||||
@@ -348,9 +348,9 @@ proc write*[T](s: Stream, x: T) =
|
||||
## **Note:** Not available for JS backend. Use `write(Stream, string)
|
||||
## <#write,Stream,string>`_ for now.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
##
|
||||
## s.writeData(s, unsafeAddr(x), sizeof(x))
|
||||
## ```Nim
|
||||
## s.writeData(s, unsafeAddr(x), sizeof(x))
|
||||
## ```
|
||||
runnableExamples:
|
||||
var strm = newStringStream("")
|
||||
strm.write("abcde")
|
||||
|
||||
@@ -91,14 +91,14 @@ proc newPipeOutStream*[T](s: sink (ref T)): owned PipeOutStream[T] =
|
||||
## when setPosition/getPosition is called or write operation is performed.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/[osproc, streamwrapper]
|
||||
## var
|
||||
## p = startProcess(exePath)
|
||||
## outStream = p.outputStream().newPipeOutStream()
|
||||
## echo outStream.peekChar
|
||||
## p.close()
|
||||
## ```
|
||||
|
||||
assert s.readDataImpl != nil
|
||||
|
||||
|
||||
@@ -133,13 +133,14 @@ runnableExamples:
|
||||
|
||||
An expression like `&"{key} is {value:arg} {{z}}"` is transformed into:
|
||||
|
||||
.. code-block:: nim
|
||||
```nim
|
||||
var temp = newStringOfCap(educatedCapGuess)
|
||||
temp.formatValue(key, "")
|
||||
temp.add(" is ")
|
||||
temp.formatValue(value, arg)
|
||||
temp.add(" {z}")
|
||||
temp
|
||||
```
|
||||
|
||||
Parts of the string that are enclosed in the curly braces are interpreted
|
||||
as Nim code. To escape a `{` or `}`, double it.
|
||||
@@ -272,13 +273,14 @@ The available floating point presentation types are:
|
||||
Because of the well defined order how templates and macros are
|
||||
expanded, strformat cannot expand template arguments:
|
||||
|
||||
.. code-block:: nim
|
||||
```nim
|
||||
template myTemplate(arg: untyped): untyped =
|
||||
echo "arg is: ", arg
|
||||
echo &"--- {arg} ---"
|
||||
|
||||
let x = "abc"
|
||||
myTemplate(x)
|
||||
```
|
||||
|
||||
First the template `myTemplate` is expanded, where every identifier
|
||||
`arg` is substituted with its argument. The `arg` inside the
|
||||
@@ -289,12 +291,13 @@ identifier that cannot be resolved anymore.
|
||||
|
||||
The workaround for this is to bind the template argument to a new local variable.
|
||||
|
||||
.. code-block:: nim
|
||||
```nim
|
||||
template myTemplate(arg: untyped): untyped =
|
||||
block:
|
||||
let arg1 {.inject.} = arg
|
||||
echo "arg is: ", arg1
|
||||
echo &"--- {arg1} ---"
|
||||
```
|
||||
|
||||
The use of `{.inject.}` here is necessary again because of template
|
||||
expansion order and hygienic templates. But since we generally want to
|
||||
|
||||
@@ -12,7 +12,7 @@ This module contains a `scanf`:idx: macro that can be used for extracting
|
||||
substrings from an input string. This is often easier than regular expressions.
|
||||
Some examples as an appetizer:
|
||||
|
||||
.. code-block:: nim
|
||||
```nim
|
||||
# check if input string matches a triple of integers:
|
||||
const input = "(1,2,4)"
|
||||
var x, y, z: int
|
||||
@@ -26,6 +26,7 @@ Some examples as an appetizer:
|
||||
var myfloat: float
|
||||
if scanf(input, "$i-$i-$i $w$s$f", year, month, day, identifier, myfloat):
|
||||
echo "yes, we have a match!"
|
||||
```
|
||||
|
||||
As can be seen from the examples, strings are matched verbatim except for
|
||||
substrings starting with ``$``. These constructions are available:
|
||||
@@ -83,8 +84,7 @@ matches optional tokens without any result binding.
|
||||
In this example, we define a helper proc ``someSep`` that skips some separators
|
||||
which we then use in our scanf pattern to help us in the matching process:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
```nim
|
||||
proc someSep(input: string; start: int; seps: set[char] = {':','-','.'}): int =
|
||||
# Note: The parameters and return value must match to what ``scanf`` requires
|
||||
result = 0
|
||||
@@ -92,11 +92,11 @@ which we then use in our scanf pattern to help us in the matching process:
|
||||
|
||||
if scanf(input, "$w$[someSep]$w", key, value):
|
||||
...
|
||||
```
|
||||
|
||||
It also possible to pass arguments to a user definable matcher:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
```nim
|
||||
proc ndigits(input: string; intVal: var int; start: int; n: int): int =
|
||||
# matches exactly ``n`` digits. Matchers need to return 0 if nothing
|
||||
# matched or otherwise the number of processed chars.
|
||||
@@ -115,6 +115,7 @@ It also possible to pass arguments to a user definable matcher:
|
||||
var year, month, day: int
|
||||
if scanf("2013-01-03", "${ndigits(4)}-${ndigits(2)}-${ndigits(2)}$.", year, month, day):
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
The scanp macro
|
||||
@@ -145,8 +146,7 @@ not implemented.
|
||||
|
||||
Simple example that parses the ``/etc/passwd`` file line by line:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
```nim
|
||||
const
|
||||
etc_passwd = """root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
|
||||
@@ -165,6 +165,7 @@ Simple example that parses the ``/etc/passwd`` file line by line:
|
||||
result.add entry
|
||||
else:
|
||||
break
|
||||
```
|
||||
|
||||
The ``scanp`` maps the grammar code into Nim code that performs the parsing.
|
||||
The parsing is performed with the help of 3 helper templates that that can be
|
||||
@@ -173,8 +174,7 @@ implemented for a custom type.
|
||||
These templates need to be named ``atom`` and ``nxt``. ``atom`` should be
|
||||
overloaded to handle both single characters and sets of character.
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
```nim
|
||||
import std/streams
|
||||
|
||||
template atom(input: Stream; idx: int; c: char): bool =
|
||||
@@ -190,11 +190,11 @@ overloaded to handle both single characters and sets of character.
|
||||
|
||||
if scanp(content, idx, +( ~{'\L', '\0'} -> entry.add(peekChar($input))), '\L'):
|
||||
result.add entry
|
||||
```
|
||||
|
||||
Calling ordinary Nim procs inside the macro is possible:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
```nim
|
||||
proc digits(s: string; intVal: var int; start: int): int =
|
||||
var x = 0
|
||||
while result+start < s.len and s[result+start] in {'0'..'9'} and s[result+start] != ':':
|
||||
@@ -220,12 +220,12 @@ Calling ordinary Nim procs inside the macro is possible:
|
||||
result.add login & " " & homedir
|
||||
else:
|
||||
break
|
||||
```
|
||||
|
||||
When used for matching, keep in mind that likewise scanf, no backtracking
|
||||
is performed.
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
```nim
|
||||
proc skipUntil(s: string; until: string; unless = '\0'; start: int): int =
|
||||
# Skips all characters until the string `until` is found. Returns 0
|
||||
# if the char `unless` is found first or the end is reached.
|
||||
@@ -256,12 +256,12 @@ is performed.
|
||||
|
||||
for r in collectLinks(body):
|
||||
echo r
|
||||
```
|
||||
|
||||
In this example both macros are combined seamlessly in order to maximise
|
||||
efficiency and perform different checks.
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
```nim
|
||||
iterator parseIps*(soup: string): string =
|
||||
## ipv4 only!
|
||||
const digits = {'0'..'9'}
|
||||
@@ -279,7 +279,7 @@ efficiency and perform different checks.
|
||||
yield buf
|
||||
buf.setLen(0) # need to clear `buf` each time, cause it might contain garbage
|
||||
idx.inc
|
||||
|
||||
```
|
||||
]##
|
||||
|
||||
|
||||
|
||||
@@ -129,11 +129,11 @@ const
|
||||
## Not very useful by its own, you can use it to create *inverted* sets to
|
||||
## make the `find func<#find,string,set[char],Natural,int>`_
|
||||
## find **invalid** characters in strings. Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## let invalid = AllChars - Digits
|
||||
## doAssert "01234".find(invalid) == -1
|
||||
## doAssert "01A34".find(invalid) == 2
|
||||
## ```
|
||||
|
||||
func isAlphaAscii*(c: char): bool {.rtl, extern: "nsuIsAlphaAsciiChar".} =
|
||||
## Checks whether or not character `c` is alphabetical.
|
||||
@@ -423,14 +423,12 @@ iterator split*(s: string, sep: char, maxsplit: int = -1): string =
|
||||
##
|
||||
## Substrings are separated by the character `sep`.
|
||||
## The code:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for word in split(";;this;is;an;;example;;;", ';'):
|
||||
## writeLine(stdout, word)
|
||||
##
|
||||
## ```
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```
|
||||
## ""
|
||||
## ""
|
||||
## "this"
|
||||
@@ -441,6 +439,7 @@ iterator split*(s: string, sep: char, maxsplit: int = -1): string =
|
||||
## ""
|
||||
## ""
|
||||
## ""
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `rsplit iterator<#rsplit.i,string,char,int>`_
|
||||
@@ -455,41 +454,46 @@ iterator split*(s: string, seps: set[char] = Whitespace,
|
||||
##
|
||||
## Substrings are separated by a substring containing only `seps`.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for word in split("this\lis an\texample"):
|
||||
## writeLine(stdout, word)
|
||||
## ```
|
||||
##
|
||||
## ...generates this output:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```
|
||||
## "this"
|
||||
## "is"
|
||||
## "an"
|
||||
## "example"
|
||||
## ```
|
||||
##
|
||||
## And the following code:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for word in split("this:is;an$example", {';', ':', '$'}):
|
||||
## writeLine(stdout, word)
|
||||
## ```
|
||||
##
|
||||
## ...produces the same output as the first example. The code:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## let date = "2012-11-20T22:08:08.398990"
|
||||
## let separators = {' ', '-', ':', 'T'}
|
||||
## for number in split(date, separators):
|
||||
## writeLine(stdout, number)
|
||||
## ```
|
||||
##
|
||||
## ...results in:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```
|
||||
## "2012"
|
||||
## "11"
|
||||
## "20"
|
||||
## "22"
|
||||
## "08"
|
||||
## "08.398990"
|
||||
## ```
|
||||
##
|
||||
## .. note:: Empty separator set results in returning an original string,
|
||||
## following the interpretation "split by no element".
|
||||
@@ -507,16 +511,18 @@ iterator split*(s: string, sep: string, maxsplit: int = -1): string =
|
||||
## Substrings are separated by the string `sep`.
|
||||
## The code:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for word in split("thisDATAisDATAcorrupted", "DATA"):
|
||||
## writeLine(stdout, word)
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```
|
||||
## "this"
|
||||
## "is"
|
||||
## "corrupted"
|
||||
## ```
|
||||
##
|
||||
## .. note:: Empty separator string results in returning an original string,
|
||||
## following the interpretation "split by no element".
|
||||
@@ -561,15 +567,17 @@ iterator rsplit*(s: string, sep: char,
|
||||
## string separator. Works exactly the same as `split iterator
|
||||
## <#split.i,string,char,int>`_ except in reverse order.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for piece in "foo:bar".rsplit(':'):
|
||||
## echo piece
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```
|
||||
## "bar"
|
||||
## "foo"
|
||||
## ```
|
||||
##
|
||||
## Substrings are separated from the right by the char `sep`.
|
||||
##
|
||||
@@ -586,15 +594,17 @@ iterator rsplit*(s: string, seps: set[char] = Whitespace,
|
||||
## string separator. Works exactly the same as `split iterator
|
||||
## <#split.i,string,char,int>`_ except in reverse order.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for piece in "foo bar".rsplit(WhiteSpace):
|
||||
## echo piece
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```
|
||||
## "bar"
|
||||
## "foo"
|
||||
## ```
|
||||
##
|
||||
## Substrings are separated from the right by the set of chars `seps`
|
||||
##
|
||||
@@ -614,15 +624,17 @@ iterator rsplit*(s: string, sep: string, maxsplit: int = -1,
|
||||
## string separator. Works exactly the same as `split iterator
|
||||
## <#split.i,string,string,int>`_ except in reverse order.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for piece in "foothebar".rsplit("the"):
|
||||
## echo piece
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```
|
||||
## "bar"
|
||||
## "foo"
|
||||
## ```
|
||||
##
|
||||
## Substrings are separated from the right by the string `sep`
|
||||
##
|
||||
@@ -648,13 +660,14 @@ iterator splitLines*(s: string, keepEol = false): string =
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for line in splitLines("\nthis\nis\nan\n\nexample\n"):
|
||||
## writeLine(stdout, line)
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## ""
|
||||
## "this"
|
||||
## "is"
|
||||
@@ -662,6 +675,7 @@ iterator splitLines*(s: string, keepEol = false): string =
|
||||
## ""
|
||||
## "example"
|
||||
## ""
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `splitWhitespace iterator<#splitWhitespace.i,string,int>`_
|
||||
@@ -694,16 +708,17 @@ iterator splitWhitespace*(s: string, maxsplit: int = -1): string =
|
||||
##
|
||||
## The following code:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## let s = " foo \t bar baz "
|
||||
## for ms in [-1, 1, 2, 3]:
|
||||
## echo "------ maxsplit = ", ms, ":"
|
||||
## for item in s.splitWhitespace(maxsplit=ms):
|
||||
## echo '"', item, '"'
|
||||
## ```
|
||||
##
|
||||
## ...results in:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```
|
||||
## ------ maxsplit = -1:
|
||||
## "foo"
|
||||
## "bar"
|
||||
@@ -719,6 +734,7 @@ iterator splitWhitespace*(s: string, maxsplit: int = -1): string =
|
||||
## "foo"
|
||||
## "bar"
|
||||
## "baz"
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `splitLines iterator<#splitLines.i,string>`_
|
||||
@@ -797,13 +813,15 @@ func rsplit*(s: string, sep: char, maxsplit: int = -1): seq[string] {.rtl,
|
||||
## For example, if a system had `#` as a delimiter, you could
|
||||
## do the following to get the tail of the path:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## var tailSplit = rsplit("Root#Object#Method#Index", '#', maxsplit=1)
|
||||
## ```
|
||||
##
|
||||
## Results in `tailSplit` containing:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## @["Root#Object#Method", "Index"]
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `rsplit iterator <#rsplit.i,string,char,int>`_
|
||||
@@ -825,13 +843,15 @@ func rsplit*(s: string, seps: set[char] = Whitespace,
|
||||
## For example, if a system had `#` as a delimiter, you could
|
||||
## do the following to get the tail of the path:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## var tailSplit = rsplit("Root#Object#Method#Index", {'#'}, maxsplit=1)
|
||||
## ```
|
||||
##
|
||||
## Results in `tailSplit` containing:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## @["Root#Object#Method", "Index"]
|
||||
## ```
|
||||
##
|
||||
## .. note:: Empty separator set results in returning an original string,
|
||||
## following the interpretation "split by no element".
|
||||
@@ -855,13 +875,15 @@ func rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
|
||||
## For example, if a system had `#` as a delimiter, you could
|
||||
## do the following to get the tail of the path:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## var tailSplit = rsplit("Root#Object#Method#Index", "#", maxsplit=1)
|
||||
## ```
|
||||
##
|
||||
## Results in `tailSplit` containing:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## @["Root#Object#Method", "Index"]
|
||||
## ```
|
||||
##
|
||||
## .. note:: Empty separator string results in returning an original string,
|
||||
## following the interpretation "split by no element".
|
||||
@@ -1786,8 +1808,9 @@ func addSep*(dest: var string, sep = ", ", startLen: Natural = 0) {.inline.} =
|
||||
##
|
||||
## A shorthand for:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## if dest.len > startLen: add(dest, sep)
|
||||
## ```
|
||||
##
|
||||
## This is often useful for generating some code where the items need to
|
||||
## be *separated* by `sep`. `sep` is only added if `dest` is longer than
|
||||
@@ -2634,13 +2657,13 @@ func formatEng*(f: BiggestFloat,
|
||||
## decimal point or (if `trim` is true) the maximum number of digits to be
|
||||
## shown.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## formatEng(0, 2, trim=false) == "0.00"
|
||||
## formatEng(0, 2) == "0"
|
||||
## formatEng(0.053, 0) == "53e-3"
|
||||
## formatEng(52731234, 2) == "52.73e6"
|
||||
## formatEng(-52731234, 2) == "-52.73e6"
|
||||
## ```
|
||||
##
|
||||
## If `siPrefix` is set to true, the number will be displayed with the SI
|
||||
## prefix corresponding to the exponent. For example 4100 will be displayed
|
||||
@@ -2655,8 +2678,7 @@ func formatEng*(f: BiggestFloat,
|
||||
## different to appending the unit to the result as the location of the space
|
||||
## is altered depending on whether there is an exponent.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## formatEng(4100, siPrefix=true, unit="V") == "4.1 kV"
|
||||
## formatEng(4.1, siPrefix=true, unit="V") == "4.1 V"
|
||||
## formatEng(4.1, siPrefix=true) == "4.1" # Note lack of space
|
||||
@@ -2666,6 +2688,7 @@ func formatEng*(f: BiggestFloat,
|
||||
## formatEng(4100) == "4.1e3"
|
||||
## formatEng(4100, unit="V") == "4.1e3 V"
|
||||
## formatEng(4100, unit="", useUnitSpace=true) == "4.1e3 " # Space with useUnitSpace=true
|
||||
## ```
|
||||
##
|
||||
## `decimalSep` is used as the decimal separator.
|
||||
##
|
||||
@@ -2829,13 +2852,15 @@ func `%`*(formatstr: string, a: openArray[string]): string {.rtl,
|
||||
##
|
||||
## This is best explained by an example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## "$1 eats $2." % ["The cat", "fish"]
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## "The cat eats fish."
|
||||
## ```
|
||||
##
|
||||
## The substitution variables (the thing after the `$`) are enumerated
|
||||
## from 1 to `a.len`.
|
||||
@@ -2843,21 +2868,24 @@ func `%`*(formatstr: string, a: openArray[string]): string {.rtl,
|
||||
## The notation `$#` can be used to refer to the next substitution
|
||||
## variable:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## "$# eats $#." % ["The cat", "fish"]
|
||||
## ```
|
||||
##
|
||||
## Substitution variables can also be words (that is
|
||||
## `[A-Za-z_]+[A-Za-z0-9_]*`) in which case the arguments in `a` with even
|
||||
## indices are keys and with odd indices are the corresponding values.
|
||||
## An example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## "$animal eats $food." % ["animal", "The cat", "food", "fish"]
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## "The cat eats fish."
|
||||
## ```
|
||||
##
|
||||
## The variables are compared with `cmpIgnoreStyle`. `ValueError` is
|
||||
## raised if an ill-formed format string has been passed to the `%` operator.
|
||||
@@ -2955,13 +2983,14 @@ iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[
|
||||
## Substrings are separated by a substring containing only `seps`.
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## for word in tokenize(" this is an example "):
|
||||
## writeLine(stdout, word)
|
||||
## ```
|
||||
##
|
||||
## Results in:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## (" ", true)
|
||||
## ("this", false)
|
||||
## (" ", true)
|
||||
@@ -2971,6 +3000,7 @@ iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[
|
||||
## (" ", true)
|
||||
## ("example", false)
|
||||
## (" ", true)
|
||||
## ```
|
||||
var i = 0
|
||||
while true:
|
||||
var j = i
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
Examples
|
||||
========
|
||||
|
||||
.. code-block:: nim
|
||||
```nim
|
||||
import std/[times, os]
|
||||
# Simple benchmarking
|
||||
let time = cpuTime()
|
||||
@@ -37,6 +37,7 @@
|
||||
# Arithmetic using TimeInterval
|
||||
echo "One year from now : ", now() + 1.years
|
||||
echo "One month from now : ", now() + 1.months
|
||||
```
|
||||
|
||||
Parsing and Formatting Dates
|
||||
============================
|
||||
@@ -44,10 +45,10 @@
|
||||
The `DateTime` type can be parsed and formatted using the different
|
||||
`parse` and `format` procedures.
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
```nim
|
||||
let dt = parse("2000-01-01", "yyyy-MM-dd")
|
||||
echo dt.format("yyyy-MM-dd")
|
||||
```
|
||||
|
||||
The different format patterns that are supported are documented below.
|
||||
|
||||
@@ -652,11 +653,10 @@ template eqImpl(a: Duration|Time, b: Duration|Time): bool =
|
||||
|
||||
const DurationZero* = Duration() ## \
|
||||
## Zero value for durations. Useful for comparisons.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## doAssert initDuration(seconds = 1) > DurationZero
|
||||
## doAssert initDuration(seconds = 0) == DurationZero
|
||||
## ```
|
||||
|
||||
proc initDuration*(nanoseconds, microseconds, milliseconds,
|
||||
seconds, minutes, hours, days, weeks: int64 = 0): Duration =
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
##
|
||||
## Specify the test name as a command line argument.
|
||||
##
|
||||
## .. code::
|
||||
##
|
||||
## ```cmd
|
||||
## nim c -r test "my test name" "another test"
|
||||
## ```
|
||||
##
|
||||
## Multiple arguments can be used.
|
||||
##
|
||||
@@ -45,9 +45,9 @@
|
||||
##
|
||||
## Specify the suite name delimited by `"::"`.
|
||||
##
|
||||
## .. code::
|
||||
##
|
||||
## ```cmd
|
||||
## nim c -r test "my test name::"
|
||||
## ```
|
||||
##
|
||||
## Selecting tests by pattern
|
||||
## ==========================
|
||||
@@ -58,19 +58,18 @@
|
||||
##
|
||||
## Tests matching **any** of the arguments are executed.
|
||||
##
|
||||
## .. code::
|
||||
##
|
||||
## ```cmd
|
||||
## nim c -r test fast_suite::mytest1 fast_suite::mytest2
|
||||
## nim c -r test "fast_suite::mytest*"
|
||||
## nim c -r test "auth*::" "crypto::hashing*"
|
||||
## # Run suites starting with 'bug #' and standalone tests starting with '#'
|
||||
## nim c -r test 'bug #*::' '::#*'
|
||||
## ```
|
||||
##
|
||||
## Examples
|
||||
## ========
|
||||
##
|
||||
## .. code:: nim
|
||||
##
|
||||
## ```nim
|
||||
## suite "description for this stuff":
|
||||
## echo "suite setup: run once before the tests"
|
||||
##
|
||||
@@ -96,6 +95,7 @@
|
||||
## discard v[4]
|
||||
##
|
||||
## echo "suite teardown: run once after the tests"
|
||||
## ```
|
||||
##
|
||||
## Limitations/Bugs
|
||||
## ================
|
||||
@@ -473,27 +473,26 @@ template suite*(name, body) {.dirty.} =
|
||||
## common fixture (``setup``, ``teardown``). The fixture is executed
|
||||
## for EACH test.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## suite "test suite for addition":
|
||||
## setup:
|
||||
## let result = 4
|
||||
## ```nim
|
||||
## suite "test suite for addition":
|
||||
## setup:
|
||||
## let result = 4
|
||||
##
|
||||
## test "2 + 2 = 4":
|
||||
## check(2+2 == result)
|
||||
## test "2 + 2 = 4":
|
||||
## check(2+2 == result)
|
||||
##
|
||||
## test "(2 + -2) != 4":
|
||||
## check(2 + -2 != result)
|
||||
## test "(2 + -2) != 4":
|
||||
## check(2 + -2 != result)
|
||||
##
|
||||
## # No teardown needed
|
||||
## # No teardown needed
|
||||
## ```
|
||||
##
|
||||
## The suite will run the individual test cases in the order in which
|
||||
## they were listed. With default global settings the above code prints:
|
||||
##
|
||||
## .. code-block::
|
||||
##
|
||||
## [Suite] test suite for addition
|
||||
## [OK] 2 + 2 = 4
|
||||
## [OK] (2 + -2) != 4
|
||||
## [Suite] test suite for addition
|
||||
## [OK] 2 + 2 = 4
|
||||
## [OK] (2 + -2) != 4
|
||||
bind formatters, ensureInitialized, suiteEnded
|
||||
|
||||
block:
|
||||
@@ -528,17 +527,15 @@ when not declared(setProgramResult):
|
||||
template test*(name, body) {.dirty.} =
|
||||
## Define a single test case identified by `name`.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## test "roses are red":
|
||||
## let roses = "red"
|
||||
## check(roses == "red")
|
||||
## ```nim
|
||||
## test "roses are red":
|
||||
## let roses = "red"
|
||||
## check(roses == "red")
|
||||
## ```
|
||||
##
|
||||
## The above code outputs:
|
||||
##
|
||||
## .. code-block::
|
||||
##
|
||||
## [OK] roses are red
|
||||
## [OK] roses are red
|
||||
bind shouldRun, checkpoints, formatters, ensureInitialized, testEnded, exceptionTypeName, setProgramResult
|
||||
|
||||
ensureInitialized()
|
||||
@@ -585,11 +582,11 @@ proc checkpoint*(msg: string) =
|
||||
## Set a checkpoint identified by `msg`. Upon test failure all
|
||||
## checkpoints encountered so far are printed out. Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## checkpoint("Checkpoint A")
|
||||
## check((42, "the Answer to life and everything") == (1, "a"))
|
||||
## checkpoint("Checkpoint B")
|
||||
## ```nim
|
||||
## checkpoint("Checkpoint A")
|
||||
## check((42, "the Answer to life and everything") == (1, "a"))
|
||||
## checkpoint("Checkpoint B")
|
||||
## ```
|
||||
##
|
||||
## outputs "Checkpoint A" once it fails.
|
||||
checkpoints.add(msg)
|
||||
@@ -601,11 +598,11 @@ template fail* =
|
||||
## failed (change exit code and test status). This template is useful
|
||||
## for debugging, but is otherwise mostly used internally. Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## checkpoint("Checkpoint A")
|
||||
## complicatedProcInThread()
|
||||
## fail()
|
||||
## ```nim
|
||||
## checkpoint("Checkpoint A")
|
||||
## complicatedProcInThread()
|
||||
## fail()
|
||||
## ```
|
||||
##
|
||||
## outputs "Checkpoint A" before quitting.
|
||||
bind ensureInitialized, setProgramResult
|
||||
@@ -633,11 +630,10 @@ template skip* =
|
||||
## for reasons depending on outer environment,
|
||||
## or certain application logic conditions or configurations.
|
||||
## The test code is still executed.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## if not isGLContextCreated():
|
||||
## skip()
|
||||
## ```nim
|
||||
## if not isGLContextCreated():
|
||||
## skip()
|
||||
## ```
|
||||
bind checkpoints
|
||||
|
||||
testStatusIMPL = TestStatus.SKIPPED
|
||||
|
||||
@@ -935,8 +935,9 @@ proc xmlConstructor(a: NimNode): NimNode =
|
||||
macro `<>`*(x: untyped): untyped =
|
||||
## Constructor macro for XML. Example usage:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## <>a(href="http://nim-lang.org", newText("Nim rules."))
|
||||
## ```
|
||||
##
|
||||
## Produces an XML tree for:
|
||||
##
|
||||
|
||||
@@ -163,11 +163,12 @@ when defined(nimdoc):
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## when declared(paramCount):
|
||||
## # Use paramCount() here
|
||||
## else:
|
||||
## # Do something else!
|
||||
## ```
|
||||
|
||||
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
||||
## Returns the `i`-th `command line argument`:idx: given to the application.
|
||||
@@ -195,11 +196,12 @@ when defined(nimdoc):
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## when declared(paramStr):
|
||||
## # Use paramStr() here
|
||||
## else:
|
||||
## # Do something else!
|
||||
## ```
|
||||
|
||||
elif defined(nimscript): discard
|
||||
elif defined(nodejs):
|
||||
@@ -296,11 +298,12 @@ when declared(paramCount) or defined(nimdoc):
|
||||
##
|
||||
## **Examples:**
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## when declared(commandLineParams):
|
||||
## # Use commandLineParams() here
|
||||
## else:
|
||||
## # Do something else!
|
||||
## ```
|
||||
result = @[]
|
||||
for i in 1..paramCount():
|
||||
result.add(paramStr(i))
|
||||
|
||||
@@ -19,7 +19,7 @@ const
|
||||
|
||||
# Inspired by https://engineering.fb.com/2013/03/15/developer-tools/three-optimization-tips-for-c
|
||||
# Generates:
|
||||
# .. code-block:: nim
|
||||
# ```nim
|
||||
# var res = ""
|
||||
# for i in 0 .. 99:
|
||||
# if i < 10:
|
||||
@@ -27,6 +27,7 @@ const
|
||||
# else:
|
||||
# res.add $i
|
||||
# doAssert res == digits100
|
||||
# ```
|
||||
|
||||
proc utoa2Digits*(buf: var openArray[char]; pos: int; digits: uint32) {.inline.} =
|
||||
buf[pos] = digits100[2 * digits]
|
||||
|
||||
@@ -15,19 +15,19 @@ The emulation cannot be 100% faithful and to avoid adding too much complexity,
|
||||
template since*(version: (int, int), body: untyped) {.dirty.} =
|
||||
## Evaluates `body` if the ``(NimMajor, NimMinor)`` is greater than
|
||||
## or equal to `version`. Usage:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## proc fun*() {.since: (1, 3).}
|
||||
## since (1, 3): fun()
|
||||
## ```
|
||||
when (NimMajor, NimMinor) >= version:
|
||||
body
|
||||
|
||||
template since*(version: (int, int, int), body: untyped) {.dirty.} =
|
||||
## Evaluates `body` if ``(NimMajor, NimMinor, NimPatch)`` is greater than
|
||||
## or equal to `version`. Usage:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## proc fun*() {.since: (1, 3, 1).}
|
||||
## since (1, 3, 1): fun()
|
||||
## ```
|
||||
when (NimMajor, NimMinor, NimPatch) >= version:
|
||||
body
|
||||
|
||||
@@ -31,37 +31,38 @@
|
||||
## Examples
|
||||
## ========
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## import std/socketstreams
|
||||
## ```Nim
|
||||
## import std/socketstreams
|
||||
##
|
||||
## var
|
||||
## socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
|
||||
## stream = newReadSocketStream(socket)
|
||||
## socket.sendTo("127.0.0.1", Port(12345), "SOME REQUEST")
|
||||
## echo stream.readLine() # Will call `recv`
|
||||
## stream.setPosition(0)
|
||||
## echo stream.readLine() # Will return the read line from the buffer
|
||||
## stream.resetStream() # Buffer is now empty, position is 0
|
||||
## echo stream.readLine() # Will call `recv` again
|
||||
## stream.close() # Closes the socket
|
||||
## var
|
||||
## socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
|
||||
## stream = newReadSocketStream(socket)
|
||||
## socket.sendTo("127.0.0.1", Port(12345), "SOME REQUEST")
|
||||
## echo stream.readLine() # Will call `recv`
|
||||
## stream.setPosition(0)
|
||||
## echo stream.readLine() # Will return the read line from the buffer
|
||||
## stream.resetStream() # Buffer is now empty, position is 0
|
||||
## echo stream.readLine() # Will call `recv` again
|
||||
## stream.close() # Closes the socket
|
||||
## ```
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/socketstreams
|
||||
##
|
||||
## import std/socketstreams
|
||||
##
|
||||
## var socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
|
||||
## socket.connect("127.0.0.1", Port(12345))
|
||||
## var sendStream = newWriteSocketStream(socket)
|
||||
## sendStream.write "NOM"
|
||||
## sendStream.setPosition(1)
|
||||
## echo sendStream.peekStr(2) # OM
|
||||
## sendStream.write "I"
|
||||
## sendStream.setPosition(0)
|
||||
## echo sendStream.readStr(3) # NIM
|
||||
## echo sendStream.getPosition() # 3
|
||||
## sendStream.flush() # This actually performs the writing to the socket
|
||||
## sendStream.setPosition(1)
|
||||
## sendStream.write "I" # Throws an error as we can't write into an already sent buffer
|
||||
## var socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
|
||||
## socket.connect("127.0.0.1", Port(12345))
|
||||
## var sendStream = newWriteSocketStream(socket)
|
||||
## sendStream.write "NOM"
|
||||
## sendStream.setPosition(1)
|
||||
## echo sendStream.peekStr(2) # OM
|
||||
## sendStream.write "I"
|
||||
## sendStream.setPosition(0)
|
||||
## echo sendStream.readStr(3) # NIM
|
||||
## echo sendStream.getPosition() # 3
|
||||
## sendStream.flush() # This actually performs the writing to the socket
|
||||
## sendStream.setPosition(1)
|
||||
## sendStream.write "I" # Throws an error as we can't write into an already sent buffer
|
||||
## ```
|
||||
|
||||
import net, streams
|
||||
|
||||
|
||||
@@ -12,27 +12,27 @@
|
||||
## Examples
|
||||
## ========
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## import std/locks
|
||||
##
|
||||
## import std/locks
|
||||
## var
|
||||
## thr: array[0..4, Thread[tuple[a,b: int]]]
|
||||
## L: Lock
|
||||
##
|
||||
## var
|
||||
## thr: array[0..4, Thread[tuple[a,b: int]]]
|
||||
## L: Lock
|
||||
## proc threadFunc(interval: tuple[a,b: int]) {.thread.} =
|
||||
## for i in interval.a..interval.b:
|
||||
## acquire(L) # lock stdout
|
||||
## echo i
|
||||
## release(L)
|
||||
##
|
||||
## proc threadFunc(interval: tuple[a,b: int]) {.thread.} =
|
||||
## for i in interval.a..interval.b:
|
||||
## acquire(L) # lock stdout
|
||||
## echo i
|
||||
## release(L)
|
||||
## initLock(L)
|
||||
##
|
||||
## initLock(L)
|
||||
## for i in 0..high(thr):
|
||||
## createThread(thr[i], threadFunc, (i*10, i*10+5))
|
||||
## joinThreads(thr)
|
||||
##
|
||||
## for i in 0..high(thr):
|
||||
## createThread(thr[i], threadFunc, (i*10, i*10+5))
|
||||
## joinThreads(thr)
|
||||
##
|
||||
## deinitLock(L)
|
||||
## deinitLock(L)
|
||||
## ```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2408,9 +2408,9 @@ when defined(nimV2):
|
||||
proc repr*[T, U](x: HSlice[T, U]): string =
|
||||
## Generic `repr` operator for slices that is lifted from the components
|
||||
## of `x`. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## $(1 .. 5) == "1 .. 5"
|
||||
## ```Nim
|
||||
## $(1 .. 5) == "1 .. 5"
|
||||
## ```
|
||||
result = repr(x.a)
|
||||
result.add(" .. ")
|
||||
result.add(repr(x.b))
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
## The following is a simple example of two different ways to use channels:
|
||||
## blocking and non-blocking.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## # Be sure to compile with --threads:on.
|
||||
## # The channels and threads modules are part of system and should not be
|
||||
## # imported.
|
||||
@@ -87,6 +87,7 @@
|
||||
##
|
||||
## # Clean up the channel.
|
||||
## chan.close()
|
||||
## ```
|
||||
##
|
||||
## Sample output
|
||||
## -------------
|
||||
@@ -113,7 +114,7 @@
|
||||
## using e.g. `system.allocShared0` and pass these pointers through thread
|
||||
## arguments:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## proc worker(channel: ptr Channel[string]) =
|
||||
## let greeting = channel[].recv()
|
||||
## echo greeting
|
||||
@@ -135,6 +136,7 @@
|
||||
## deallocShared(channel)
|
||||
##
|
||||
## localChannelExample() # "Hello from the main thread!"
|
||||
## ```
|
||||
|
||||
when not declared(ThisIsSystem):
|
||||
{.error: "You must not import this module explicitly".}
|
||||
|
||||
@@ -41,9 +41,9 @@ proc `$`*(x: bool): string {.magic: "BoolToStr", noSideEffect.}
|
||||
proc `$`*(x: char): string {.magic: "CharToStr", noSideEffect.}
|
||||
## The stringify operator for a character argument. Returns `x`
|
||||
## converted to a string.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## assert $'c' == "c"
|
||||
## ```
|
||||
|
||||
proc `$`*(x: cstring): string {.magic: "CStrToStr", noSideEffect.}
|
||||
## The stringify operator for a CString argument. Returns `x`
|
||||
@@ -67,19 +67,20 @@ proc `$`*(t: typedesc): string {.magic: "TypeTrait".}
|
||||
## For more procedures dealing with `typedesc`, see
|
||||
## `typetraits module <typetraits.html>`_.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## doAssert $(typeof(42)) == "int"
|
||||
## doAssert $(typeof("Foo")) == "string"
|
||||
## static: doAssert $(typeof(@['A', 'B'])) == "seq[char]"
|
||||
## ```
|
||||
|
||||
proc `$`*[T: tuple](x: T): string =
|
||||
## Generic `$` operator for tuples that is lifted from the components
|
||||
## of `x`. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## $(23, 45) == "(23, 45)"
|
||||
## $(a: 23, b: 45) == "(a: 23, b: 45)"
|
||||
## $() == "()"
|
||||
## ```
|
||||
tupleObjectDollar(result, x)
|
||||
|
||||
when not defined(nimPreviewSlimSystem):
|
||||
@@ -108,25 +109,25 @@ proc collectionToString[T](x: T, prefix, separator, suffix: string): string =
|
||||
proc `$`*[T](x: set[T]): string =
|
||||
## Generic `$` operator for sets that is lifted from the components
|
||||
## of `x`. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## ${23, 45} == "{23, 45}"
|
||||
## ```
|
||||
collectionToString(x, "{", ", ", "}")
|
||||
|
||||
proc `$`*[T](x: seq[T]): string =
|
||||
## Generic `$` operator for seqs that is lifted from the components
|
||||
## of `x`. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## $(@[23, 45]) == "@[23, 45]"
|
||||
## ```
|
||||
collectionToString(x, "@[", ", ", "]")
|
||||
|
||||
proc `$`*[T, U](x: HSlice[T, U]): string =
|
||||
## Generic `$` operator for slices that is lifted from the components
|
||||
## of `x`. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## $(1 .. 5) == "1 .. 5"
|
||||
## ```
|
||||
result = $x.a
|
||||
result.add(" .. ")
|
||||
result.add($x.b)
|
||||
@@ -140,7 +141,7 @@ when not defined(nimNoArrayToString):
|
||||
proc `$`*[T](x: openArray[T]): string =
|
||||
## Generic `$` operator for openarrays that is lifted from the components
|
||||
## of `x`. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## $(@[23, 45].toOpenArray(0, 1)) == "[23, 45]"
|
||||
## ```
|
||||
collectionToString(x, "[", ", ", "]")
|
||||
|
||||
@@ -31,7 +31,7 @@ In Nim the compiler cannot always know if a reference
|
||||
is stored on the stack or not. This is caused by var parameters.
|
||||
Consider this example:
|
||||
|
||||
.. code-block:: Nim
|
||||
```Nim
|
||||
proc setRef(r: var ref TNode) =
|
||||
new(r)
|
||||
|
||||
@@ -41,11 +41,12 @@ Consider this example:
|
||||
setRef(r) # here we should not update the reference counts, because
|
||||
# r is on the stack
|
||||
setRef(r.left) # here we should update the refcounts!
|
||||
```
|
||||
|
||||
We have to decide at runtime whether the reference is on the stack or not.
|
||||
The generated code looks roughly like this:
|
||||
|
||||
.. code-block:: C
|
||||
```C
|
||||
void setref(TNode** ref) {
|
||||
unsureAsgnRef(ref, newObj(TNode_TI, sizeof(TNode)))
|
||||
}
|
||||
@@ -53,6 +54,7 @@ The generated code looks roughly like this:
|
||||
setRef(&r)
|
||||
setRef(&r->left)
|
||||
}
|
||||
```
|
||||
|
||||
Note that for systems with a continuous stack (which most systems have)
|
||||
the check whether the ref is on the stack is very cheap (only two
|
||||
|
||||
@@ -89,10 +89,9 @@ proc patchFile*(package, filename, replacement: string) =
|
||||
## The compiler also performs `path substitution <nimc.html#compiler-usage-commandminusline-switches>`_ on `replacement`.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## patchFile("stdlib", "asyncdispatch", "patches/replacement")
|
||||
## ```
|
||||
discard
|
||||
|
||||
proc getCommand*(): string =
|
||||
@@ -159,20 +158,18 @@ proc strip(s: string): string =
|
||||
template `--`*(key, val: untyped) =
|
||||
## A shortcut for `switch <#switch,string,string>`_
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## --path:somePath # same as switch("path", "somePath")
|
||||
## --path:"someOtherPath" # same as switch("path", "someOtherPath")
|
||||
## ```
|
||||
switch(strip(astToStr(key)), strip(astToStr(val)))
|
||||
|
||||
template `--`*(key: untyped) =
|
||||
## A shortcut for `switch <#switch,string,string>`_
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## --listCmd # same as switch("listCmd")
|
||||
## ```
|
||||
switch(strip(astToStr(key)))
|
||||
|
||||
type
|
||||
@@ -341,12 +338,12 @@ template withDir*(dir: string; body: untyped): untyped =
|
||||
##
|
||||
## If you need a permanent change, use the `cd() <#cd,string>`_ proc.
|
||||
## Usage example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## # inside /some/path/
|
||||
## withDir "foo":
|
||||
## # move to /some/path/foo/
|
||||
## # back in /some/path/
|
||||
## ```
|
||||
let curDir = getCurrentDir()
|
||||
try:
|
||||
cd(dir)
|
||||
@@ -391,10 +388,10 @@ when not defined(nimble):
|
||||
## Defines a task. Hidden tasks are supported via an empty description.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## task build, "default build is via the C backend":
|
||||
## setCommand "c"
|
||||
## ```nim
|
||||
## task build, "default build is via the C backend":
|
||||
## setCommand "c"
|
||||
## ```
|
||||
##
|
||||
## For a task named `foo`, this template generates a `proc` named
|
||||
## `fooTask`. This is useful if you need to call one task in
|
||||
@@ -402,13 +399,14 @@ when not defined(nimble):
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## task foo, "foo": # > nim foo
|
||||
## echo "Running foo" # Running foo
|
||||
## ```nim
|
||||
## task foo, "foo": # > nim foo
|
||||
## echo "Running foo" # Running foo
|
||||
##
|
||||
## task bar, "bar": # > nim bar
|
||||
## echo "Running bar" # Running bar
|
||||
## fooTask() # Running foo
|
||||
## task bar, "bar": # > nim bar
|
||||
## echo "Running bar" # Running bar
|
||||
## fooTask() # Running foo
|
||||
## ```
|
||||
proc `name Task`*() =
|
||||
setCommand "nop"
|
||||
body
|
||||
|
||||
@@ -38,8 +38,9 @@ proc repr*(x: char): string {.noSideEffect, raises: [].} =
|
||||
## repr for a character argument. Returns `x`
|
||||
## converted to an escaped string.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## assert repr('c') == "'c'"
|
||||
## ```
|
||||
result.add '\''
|
||||
# Elides string creations if not needed
|
||||
if x in {'\\', '\0'..'\31', '\127'..'\255'}:
|
||||
@@ -132,11 +133,11 @@ proc reprObject[T: tuple|object](res: var string, x: T) {.noSideEffect, raises:
|
||||
proc repr*[T: tuple|object](x: T): string {.noSideEffect, raises: [].} =
|
||||
## Generic `repr` operator for tuples that is lifted from the components
|
||||
## of `x`. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## $(23, 45) == "(23, 45)"
|
||||
## $(a: 23, b: 45) == "(a: 23, b: 45)"
|
||||
## $() == "()"
|
||||
## ```
|
||||
when T is object:
|
||||
result = $typeof(x)
|
||||
reprObject(result, x)
|
||||
@@ -164,17 +165,17 @@ proc collectionToRepr[T](x: T, prefix, separator, suffix: string): string {.noSi
|
||||
proc repr*[T](x: set[T]): string =
|
||||
## Generic `repr` operator for sets that is lifted from the components
|
||||
## of `x`. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## ${23, 45} == "{23, 45}"
|
||||
## ```
|
||||
collectionToRepr(x, "{", ", ", "}")
|
||||
|
||||
proc repr*[T](x: seq[T]): string =
|
||||
## Generic `repr` operator for seqs that is lifted from the components
|
||||
## of `x`. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## $(@[23, 45]) == "@[23, 45]"
|
||||
## ```
|
||||
collectionToRepr(x, "@[", ", ", "]")
|
||||
|
||||
proc repr*[T, IDX](x: array[IDX, T]): string =
|
||||
@@ -184,9 +185,9 @@ proc repr*[T, IDX](x: array[IDX, T]): string =
|
||||
proc repr*[T](x: openArray[T]): string =
|
||||
## Generic `repr` operator for openarrays that is lifted from the components
|
||||
## of `x`. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ```Nim
|
||||
## $(@[23, 45].toOpenArray(0, 1)) == "[23, 45]"
|
||||
## ```
|
||||
collectionToRepr(x, "[", ", ", "]")
|
||||
|
||||
proc repr*[T](x: UncheckedArray[T]): string =
|
||||
|
||||
@@ -18,12 +18,13 @@
|
||||
##
|
||||
## Build and test examples:
|
||||
##
|
||||
## .. code-block::
|
||||
## ```cmd
|
||||
## ./bin/nim c -d:ssl -p:. -r tests/stdlib/tssl.nim
|
||||
## ./bin/nim c -d:ssl --threads:on -p:. -r tests/stdlib/thttpclient_ssl.nim
|
||||
## ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim
|
||||
## ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passl:-lcrypto --passl:-lssl -r tests/untestable/tssl.nim
|
||||
## ./bin/nim r --putenv:NIM_TESTAMENT_REMOTE_NETWORKING:1 -d:ssl -p:testament/lib --threads:on tests/untestable/thttpclient_ssl_remotenetwork.nim
|
||||
## ```
|
||||
|
||||
# https://www.feistyduck.com/library/openssl-cookbook/online/ch-testing-with-openssl.html
|
||||
#
|
||||
|
||||
@@ -693,11 +693,11 @@ proc newRecordGen(ctx: Context; typ: TypRef): PNode =
|
||||
String `interpolation`:idx: / `format`:idx: inspired by
|
||||
Python's ``f``-strings.
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
import strformat
|
||||
let msg = "hello"
|
||||
doAssert fmt"{msg}\n" == "hello\\n"
|
||||
```nim
|
||||
import strformat
|
||||
let msg = "hello"
|
||||
doAssert fmt"{msg}\n" == "hello\\n"
|
||||
```
|
||||
|
||||
Because the literal is a raw string literal, the ``\n`` is not interpreted as
|
||||
an escape sequence.
|
||||
|
||||
@@ -699,11 +699,11 @@ proc newRecordGen(ctx: Context; typ: TypRef): PNode =
|
||||
String `interpolation`:idx: / `format`:idx: inspired by
|
||||
Python's ``f``-strings.
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
import strformat
|
||||
let msg = "hello"
|
||||
doAssert fmt"{msg}\n" == "hello\\n"
|
||||
```nim
|
||||
import strformat
|
||||
let msg = "hello"
|
||||
doAssert fmt"{msg}\n" == "hello\\n"
|
||||
```
|
||||
|
||||
Because the literal is a raw string literal, the ``\n`` is not interpreted as
|
||||
an escape sequence.
|
||||
|
||||
@@ -143,27 +143,26 @@ proc extractErrorMsg(s: string; i: int; line: var int; col: var int; spec: var T
|
||||
##
|
||||
## Can parse a single message for a line:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## proc generic_proc*[T] {.no_destroy, userPragma.} = #[tt.Error
|
||||
## ^ 'generic_proc' should be: 'genericProc' [Name] ]#
|
||||
## ```
|
||||
##
|
||||
## Can parse multiple messages for a line when they are separated by ';':
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## proc generic_proc*[T] {.no_destroy, userPragma.} = #[tt.Error
|
||||
## ^ 'generic_proc' should be: 'genericProc' [Name]; tt.Error
|
||||
## ^ 'no_destroy' should be: 'nodestroy' [Name]; tt.Error
|
||||
## ^ 'userPragma' should be: 'user_pragma' [template declared in mstyleCheck.nim(10, 9)] [Name] ]#
|
||||
## ```
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## ```nim
|
||||
## proc generic_proc*[T] {.no_destroy, userPragma.} = #[tt.Error
|
||||
## ^ 'generic_proc' should be: 'genericProc' [Name];
|
||||
## tt.Error ^ 'no_destroy' should be: 'nodestroy' [Name];
|
||||
## tt.Error ^ 'userPragma' should be: 'user_pragma' [template declared in mstyleCheck.nim(10, 9)] [Name] ]#
|
||||
##
|
||||
## ```
|
||||
result = i + len(inlineErrorMarker)
|
||||
inc col, len(inlineErrorMarker)
|
||||
let msgLine = line
|
||||
|
||||
@@ -168,14 +168,14 @@ template new_parsed_parameter*(tkind: Tparam_kind, expr): Tparsed_parameter =
|
||||
## initialised with. The template figures out at compile time what field to
|
||||
## assign the variable to, and thus you reduce code clutter and may use this
|
||||
## to initialise single assignments variables in `let` blocks. Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## ```nim
|
||||
## let
|
||||
## parsed_param1 = new_parsed_parameter(PK_FLOAT, 3.41)
|
||||
## parsed_param2 = new_parsed_parameter(PK_BIGGEST_INT, 2358123 * 23123)
|
||||
## # The following line doesn't compile due to
|
||||
## # type mismatch: got <string> but expected 'int'
|
||||
## #parsed_param3 = new_parsed_parameter(PK_INT, "231")
|
||||
## ```
|
||||
var result {.gensym.}: Tparsed_parameter
|
||||
result.kind = tkind
|
||||
when tkind == PK_EMPTY: discard
|
||||
|
||||
Reference in New Issue
Block a user