summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-11-28 21:56:48 +0100
committerGitHub <noreply@github.com>2017-11-28 21:56:48 +0100
commit5196cc3a5410749934858d7356ef4605bb52f544 (patch)
treef31e3d07b448c1d64fed6215e3fd7fb8164e8c5e
parentb74a5148a9e7bf646ee6a13cad0ce046d7b9d8b4 (diff)
parent45821ea2ab081a77b057b6837dae5be52b975cee (diff)
downloadNim-5196cc3a5410749934858d7356ef4605bb52f544.tar.gz
Merge branch 'devel' into fixes-6223
-rw-r--r--changelog.md5
-rw-r--r--compiler/pragmas.nim6
-rw-r--r--compiler/semdestruct.nim15
-rw-r--r--lib/pure/htmlgen.nim4
-rw-r--r--lib/pure/mimetypes.nim9
-rw-r--r--lib/pure/strutils.nim74
6 files changed, 67 insertions, 46 deletions
diff --git a/changelog.md b/changelog.md
index bd40d7e99..f0deceb15 100644
--- a/changelog.md
+++ b/changelog.md
@@ -107,4 +107,7 @@ This now needs to be written as:
       if true: echo "yes"
 - The ``[]`` proc for strings now raises an ``IndexError`` exception when
   the specified slice is out of bounds. See issue
-  [#6223](https://github.com/nim-lang/Nim/issues/6223) for more details.
\ No newline at end of file
+  [#6223](https://github.com/nim-lang/Nim/issues/6223) for more details.
+- ``strutils.split`` and ``strutils.rsplit`` with an empty string and a
+  separator now returns that empty string.
+  See issue [#4377](https://github.com/nim-lang/Nim/issues/4377).
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index f1d81f798..b598cadb2 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -23,7 +23,7 @@ const
     wMagic, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
     wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
     wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
-    wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
+    wAsmNoStackFrame, wError, wDiscardable, wNoInit, wCodegenDecl,
     wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
     wOverride, wConstructor, wExportNims, wUsed, wLiftLocals}
   converterPragmas* = procPragmas
@@ -759,10 +759,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         incl(sym.loc.flags, lfNoDecl)
         # implies nodecl, because otherwise header would not make sense
         if sym.loc.r == nil: sym.loc.r = rope(sym.name.s)
-      of wDestructor:
-        sym.flags.incl sfOverriden
-        if sym.name.s.normalize != "destroy":
-          localError(n.info, errGenerated, "destructor has to be named 'destroy'")
       of wOverride:
         sym.flags.incl sfOverriden
       of wNosideeffect:
diff --git a/compiler/semdestruct.nim b/compiler/semdestruct.nim
index 4b61c6316..b16bf004f 100644
--- a/compiler/semdestruct.nim
+++ b/compiler/semdestruct.nim
@@ -23,7 +23,6 @@ new(destructorIsTrivial)
 var
   destructorName = getIdent"destroy_"
   destructorParam = getIdent"this_"
-  destructorPragma = newIdentNode(getIdent"destructor", unknownLineInfo())
 
 proc instantiateDestructor(c: PContext, typ: PType): PType
 
@@ -150,19 +149,19 @@ proc instantiateDestructor(c: PContext, typ: PType): PType =
     let generated = generateDestructor(c, t)
     if generated != nil:
       internalAssert t.sym != nil
-      var i = t.sym.info
-      let fullDef = newNode(nkProcDef, i, @[
-        newIdentNode(destructorName, i),
+      let info = t.sym.info
+      let fullDef = newNode(nkProcDef, info, @[
+        newIdentNode(destructorName, info),
         emptyNode,
         emptyNode,
-        newNode(nkFormalParams, i, @[
+        newNode(nkFormalParams, info, @[
           emptyNode,
-          newNode(nkIdentDefs, i, @[
-            newIdentNode(destructorParam, i),
+          newNode(nkIdentDefs, info, @[
+            newIdentNode(destructorParam, info),
             symNodeFromType(c, makeVarType(c, t), t.sym.info),
             emptyNode]),
           ]),
-        newNode(nkPragma, i, @[destructorPragma]),
+        emptyNode,
         emptyNode,
         generated
         ])
diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim
index ad199a215..c0934a45b 100644
--- a/lib/pure/htmlgen.nim
+++ b/lib/pure/htmlgen.nim
@@ -59,8 +59,8 @@ proc xmlCheckedTag*(e: NimNode, tag: string, optAttr = "", reqAttr = "",
 
   # copy the attributes; when iterating over them these lists
   # will be modified, so that each attribute is only given one value
-  var req = split(reqAttr)
-  var opt = split(optAttr)
+  var req = splitWhitespace(reqAttr)
+  var opt = splitWhitespace(optAttr)
   result = newNimNode(nnkBracket, e)
   result.add(newStrLitNode("<"))
   result.add(newStrLitNode(tag))
diff --git a/lib/pure/mimetypes.nim b/lib/pure/mimetypes.nim
index 1e315afb4..b397ef47b 100644
--- a/lib/pure/mimetypes.nim
+++ b/lib/pure/mimetypes.nim
@@ -491,6 +491,8 @@ const mimes* = {
     "vrml": "x-world/x-vrml",
     "wrl": "x-world/x-vrml"}
 
+from strutils import startsWith
+
 proc newMimetypes*(): MimeDB =
   ## Creates a new Mimetypes database. The database will contain the most
   ## common mimetypes.
@@ -498,8 +500,11 @@ proc newMimetypes*(): MimeDB =
 
 proc getMimetype*(mimedb: MimeDB, ext: string, default = "text/plain"): string =
   ## Gets mimetype which corresponds to ``ext``. Returns ``default`` if ``ext``
-  ## could not be found.
-  result = mimedb.mimes.getOrDefault(ext)
+  ## could not be found. ``ext`` can start with an optional dot which is ignored.
+  if ext.startsWith("."):
+    result = mimedb.mimes.getOrDefault(ext.substr(1))
+  else:
+    result = mimedb.mimes.getOrDefault(ext)
   if result == "":
     return default
 
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 6fe2df216..62ceaa2e8 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -502,16 +502,15 @@ template splitCommon(s, sep, maxsplit, sepLen) =
   var last = 0
   var splits = maxsplit
 
-  if len(s) > 0:
-    while last <= len(s):
-      var first = last
-      while last < len(s) and not stringHasSep(s, last, sep):
-        inc(last)
-      if splits == 0: last = len(s)
-      yield substr(s, first, last-1)
-      if splits == 0: break
-      dec(splits)
-      inc(last, sepLen)
+  while last <= len(s):
+    var first = last
+    while last < len(s) and not stringHasSep(s, last, sep):
+      inc(last)
+    if splits == 0: last = len(s)
+    yield substr(s, first, last-1)
+    if splits == 0: break
+    dec(splits)
+    inc(last, sepLen)
 
 template oldSplit(s, seps, maxsplit) =
   var last = 0
@@ -669,30 +668,29 @@ template rsplitCommon(s, sep, maxsplit, sepLen) =
     splits = maxsplit
     startPos = 0
 
-  if len(s) > 0:
-    # go to -1 in order to get separators at the beginning
-    while first >= -1:
-      while first >= 0 and not stringHasSep(s, first, sep):
-        dec(first)
+  # go to -1 in order to get separators at the beginning
+  while first >= -1:
+    while first >= 0 and not stringHasSep(s, first, sep):
+      dec(first)
 
-      if splits == 0:
-        # No more splits means set first to the beginning
-        first = -1
+    if splits == 0:
+      # No more splits means set first to the beginning
+      first = -1
 
-      if first == -1:
-        startPos = 0
-      else:
-        startPos = first + sepLen
+    if first == -1:
+      startPos = 0
+    else:
+      startPos = first + sepLen
 
-      yield substr(s, startPos, last)
+    yield substr(s, startPos, last)
 
-      if splits == 0:
-        break
+    if splits == 0:
+      break
 
-      dec(splits)
-      dec(first)
+    dec(splits)
+    dec(first)
 
-      last = first
+    last = first
 
 iterator rsplit*(s: string, seps: set[char] = Whitespace,
                  maxsplit: int = -1): string =
@@ -820,12 +818,18 @@ proc split*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): seq[st
   noSideEffect, rtl, extern: "nsuSplitCharSet".} =
   ## The same as the `split iterator <#split.i,string,set[char],int>`_, but is a
   ## proc that returns a sequence of substrings.
+  runnableExamples:
+    doAssert "a,b;c".split({',', ';'}) == @["a", "b", "c"]
+    doAssert "".split({' '}) == @[""]
   accumulateResult(split(s, seps, maxsplit))
 
 proc split*(s: string, sep: char, maxsplit: int = -1): seq[string] {.noSideEffect,
   rtl, extern: "nsuSplitChar".} =
   ## The same as the `split iterator <#split.i,string,char,int>`_, but is a proc
   ## that returns a sequence of substrings.
+  runnableExamples:
+    doAssert "a,b,c".split(',') == @["a", "b", "c"]
+    doAssert "".split(' ') == @[""]
   accumulateResult(split(s, sep, maxsplit))
 
 proc split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.noSideEffect,
@@ -834,6 +838,13 @@ proc split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.noSideEff
   ##
   ## Substrings are separated by the string `sep`. This is a wrapper around the
   ## `split iterator <#split.i,string,string,int>`_.
+  runnableExamples:
+    doAssert "a,b,c".split(",") == @["a", "b", "c"]
+    doAssert "a man a plan a canal panama".split("a ") == @["", "man ", "plan ", "canal panama"]
+    doAssert "".split("Elon Musk") == @[""]
+    doAssert "a  largely    spaced sentence".split(" ") == @["a", "", "largely", "", "", "", "spaced", "sentence"]
+
+    doAssert "a  largely    spaced sentence".split(" ", maxsplit=1) == @["a", " largely    spaced sentence"]
   doAssert(sep.len > 0)
 
   accumulateResult(split(s, sep, maxsplit))
@@ -902,6 +913,13 @@ proc rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string]
   ## .. code-block:: nim
   ##   @["Root#Object#Method", "Index"]
   ##
+  runnableExamples:
+    doAssert "a  largely    spaced sentence".rsplit(" ", maxsplit=1) == @["a  largely    spaced", "sentence"]
+
+    doAssert "a,b,c".rsplit(",") == @["a", "b", "c"]
+    doAssert "a man a plan a canal panama".rsplit("a ") == @["", "man ", "plan ", "canal panama"]
+    doAssert "".rsplit("Elon Musk") == @[""]
+    doAssert "a  largely    spaced sentence".rsplit(" ") == @["a", "", "largely", "", "", "", "spaced", "sentence"]
   accumulateResult(rsplit(s, sep, maxsplit))
   result.reverse()