diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
 # Revision history for curly-expander
 
+## 0.3.0.0
+* Added customCurlyExpand function.
+
 ## 0.2.0.3
 * Improved README
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
 # curly-expander
-This is tool for curly brackets expanding, similar to bash curly expanding.
+This is tool for curly brackets expanding, similar to bash curly expanding. It also contain an extended version of it.
 
 Please refer to the package description on [Hackage](https://hackage.haskell.org/package/curly-expander-0.2.0.2/docs/Text-CurlyExpander.html) for more information.
diff --git a/Text/CurlyExpander.hs b/Text/CurlyExpander.hs
--- a/Text/CurlyExpander.hs
+++ b/Text/CurlyExpander.hs
@@ -5,13 +5,21 @@
 Stability   : testing
 Portability : POSIX
 
-This is the main module of the curly-expander package.
+This is the main (and only) module of the curly-expander package.
 
 -}
 
 {-# LANGUAGE OverloadedStrings #-}
 
-module Text.CurlyExpander (curlyExpand) where
+module Text.CurlyExpander 
+  (
+    curlyExpand, 
+    BackslashConfig (NoHandle, Preserve, Standard), 
+    ExpandConfig (ExpandConfig, quotePairs, backslashConfig, persistQuotePairs, allowOneElementExpand), 
+    defaultExpandConfig, 
+    customCurlyExpand
+  ) 
+where
 
 import qualified Data.Text as T
 import qualified Data.Text.Lazy as L
@@ -24,101 +32,223 @@
 
 import Data.Char
 
+-- | This configuration specify, how should be backslashes handled.
+-- It is part of `ExpandConfig`.
+data BackslashConfig = 
+    -- | If no handle is used, then backslashes are not handled in any special way.
+    NoHandle | 
 
-cumulatorComma :: Parser [L.Text]
-cumulatorComma = do
-  atoms <- (try p_range) <|> (try p_char_range) <|> p_atoms
-  return atoms 
-  
-  where
-    p_range :: Parser [L.Text]
-    p_range = do
-      nb1 <- many1 digit
-      _ <- string ".."
-      nb2 <- many1 digit
+    -- | If preserve is used, backslashes are processed, any backslashed char is processed as nonspecial char 
+    -- and backslashes aren't deleted from result.
+    Preserve | 
 
-      return$ map (toLazyText . decimal) $ get_range (read nb1) (read nb2)
-      where
-        get_range :: Int -> Int -> [Int]
-        get_range n1 n2
-          | n1 > n2 = reverse$ get_range n2 n1
-          | otherwise = [n1..n2]
+    -- | If standard is used, backslashes are processed, any backslashed char is processed as nonspecial char
+    -- and backslashes are deleted from result.
+    Standard
+  deriving Eq
 
-    p_char_range :: Parser [L.Text]
-    p_char_range = do
-      char1 <- anyChar
-      _ <- string ".."
-      char2 <- anyChar
+
+-- | The curly braces expand config. 
+-- It is used in `customCurlyExpand`.
+data ExpandConfig = ExpandConfig {
+    -- | The configuration, which defines, how should be backslashes handled (\\)
+    backslashConfig :: BackslashConfig,
+
+    -- | Quote pairs, which encloses a substrings, tells expander, that the substring shouldn't be expanded.
+    -- For example (\"[\", \"]\") pairs tells to expander, that anything inside [ANYTHING] shouldn't be expanded.
+    quotePairs :: [(String, String)],
+
+    -- | If true, quote pairs aren't deleted. Otherwise they are deleted from a result.
+    persistQuotePairs :: Bool,
+
+    -- | If true, curly brackets around one element will be deleted. Otherwise they are persisted.
+    allowOneElementExpand :: Bool
+  }
+
+
+-- | The default curly braces expand function config.
+-- By default backslashes are not handeled, there are no quote pairs and one element expand is forbidden.
+-- See the source code for details.
+defaultExpandConfig :: ExpandConfig
+defaultExpandConfig = ExpandConfig { 
+    backslashConfig = NoHandle, 
+    quotePairs = [],
+    persistQuotePairs = False,
+    allowOneElementExpand = False
+  }
+
+-- | Custom curly braces (brackets) expand function.
+-- It works in the same way as curlyExpand, bud accept custom configuration `ExpandConfig` in the first argument.
+
+customCurlyExpand :: ExpandConfig -> T.Text -> [T.Text]
+customCurlyExpand config input =
+  case parse inputP "bracket expansion"$ input of
+    Left _ -> [input]
+    Right ret -> map L.toStrict ret
+
+  where 
+    cumulatorComma :: Parser [L.Text]
+    cumulatorComma = do
+      atoms <- (try p_range) <|> (try p_char_range) <|> p_atoms
+      return atoms 
       
-      return [ L.pack [p] | p <- get_range char1 char2 ]
       where
-        get_range :: Char -> Char -> [Char]
-        get_range c1 c2
-          | n1 > n2 = reverse$ get_range c2 c1
-          | otherwise = map chr [n1..n2]
+        p_range :: Parser [L.Text]
+        p_range = do
+          nb1 <- many1 digit
+          _ <- string ".."
+          nb2 <- many1 digit
 
+          return$ map (toLazyText . decimal) $ get_range (read nb1) (read nb2)
           where
-            n1 = ord c1
-            n2 = ord c2
+            get_range :: Int -> Int -> [Int]
+            get_range n1 n2
+              | n1 > n2 = reverse$ get_range n2 n1
+              | otherwise = [n1..n2]
 
-    p_atoms :: Parser [L.Text]
-    p_atoms = do
-      molecule <- many1$ try p_atom
-      terminal_atom <- innerInputP
-      return $ (concat molecule) ++ terminal_atom
+        p_char_range :: Parser [L.Text]
+        p_char_range = do
+          char1 <- anyChar
+          _ <- string ".."
+          char2 <- anyChar
+          
+          return [ L.pack [p] | p <- get_range char1 char2 ]
+          where
+            get_range :: Char -> Char -> [Char]
+            get_range c1 c2
+              | n1 > n2 = reverse$ get_range c2 c1
+              | otherwise = map chr [n1..n2]
 
-    p_atom :: Parser [L.Text]
-    p_atom = do
+              where
+                n1 = ord c1
+                n2 = ord c2
 
-      atom <- innerInputP
-      _ <- char ','
-      return atom
+        p_atoms :: Parser [L.Text]
+        p_atoms = do
+          molecule <- moleculeP
+          terminal_atom <- innerInputP
+          return $ (concat molecule) ++ terminal_atom
 
+         where 
+            moleculeP :: Parser [[L.Text]]
+            moleculeP = 
+             if allowOneElementExpand config; then
+               many (try p_atom)
+             else
+               many1 (try p_atom)
 
-bracketP :: Parser [L.Text]
-bracketP = do
+        p_atom :: Parser [L.Text]
+        p_atom = do
 
-  _ <- char '{'
-  ret <- cumulatorComma
-  _ <- char '}'
+          atom <- innerInputP
+          _ <- char ','
+          return atom
 
-  return$ ret
 
-charP :: Parser [L.Text]
-charP = do
-  c <- anyChar
-  return [L.pack [c]]
+    bracketP :: Parser [L.Text]
+    bracketP = do
 
-nonSpecialCharP :: Parser [L.Text]
-nonSpecialCharP = do
-  c <- noneOf ",}"
-  return [L.pack [c]]
+      _ <- char '{'
+      ret <- cumulatorComma
+      _ <- char '}'
 
-innerNonEmptyInputP :: Parser [L.Text]
-innerNonEmptyInputP = do
-  molecule <- (try bracketP <|> nonSpecialCharP)
-  rest <- innerInputP
+      return$ ret
 
-  return [ L.append a b | a <- molecule, b <- rest ]
+    charP :: Parser [L.Text]
+    charP = do
+      c <- anyChar
+      return [L.pack [c]]
 
-innerInputP :: Parser [L.Text]
-innerInputP = (innerNonEmptyInputP <|> emptyInputP)
+    nonSpecialCharP :: Parser [L.Text]
+    nonSpecialCharP = do
+      c <- noneOf ",}"
+      return [L.pack [c]]
 
-nonEmptyInputP :: Parser [L.Text]
-nonEmptyInputP = do
-  molecule <- (try bracketP <|> charP)
-  rest <- inputP
+    backslashedP :: Parser [L.Text]
+    backslashedP = do
+      if handleBackslash then do
+        _ <- char '\\'
+        c <- anyChar
 
-  return [ L.append a b | a <- molecule, b <- rest ]
+        return$ getReturnValue c
+      else do
+        unexpected "Char is not backslashed."
 
-emptyInputP :: Parser [L.Text]
-emptyInputP = do
-  return [""]
+      where
+        handleBackslash :: Bool
+        handleBackslash = 
+          if backslashConfig config == NoHandle then
+            False
+          else 
+            True
 
-inputP :: Parser [L.Text]
-inputP = (nonEmptyInputP <|> emptyInputP)
-  
+        getReturnValue :: Char -> [L.Text]
+        getReturnValue c =
+          if backslashConfig config == Preserve then
+            [ L.pack ['\\', c] ]
+          else
+            [ L.pack [c] ]
 
+    specialQuotedP :: (String, String) -> Parser [L.Text]
+    specialQuotedP (lQuote,rQuote) = do
+      _ <- string lQuote
+      ret <- quoteNext
+
+      return$ [enrichReturnValue ret]
+      where
+        quoteClosure :: Parser L.Text
+        quoteClosure = do
+          _ <- string rQuote
+          return ""
+
+        quoteNextChar :: Parser L.Text
+        quoteNextChar = do
+          c <- anyChar
+          rest <- quoteNext
+          return$ L.pack [c] `L.append` rest
+
+        quoteNext :: Parser L.Text
+        quoteNext = (try quoteClosure <|> quoteNextChar)
+
+        enrichReturnValue :: L.Text -> L.Text
+        enrichReturnValue ret = 
+          if persistQuotePairs config; then
+            (L.pack lQuote) `L.append` ret `L.append` (L.pack rQuote) 
+          else
+            ret
+
+        
+    quotedP :: [(String, String)] -> Parser [L.Text]
+    quotedP (quotes : rest) = (try$ specialQuotedP quotes) <|> quotedP rest
+    quotedP [] = unexpected "String is not quoted."
+
+    allQuotedP :: Parser [L.Text]
+    allQuotedP = quotedP$ quotePairs config
+
+    innerNonEmptyInputP :: Parser [L.Text]
+    innerNonEmptyInputP = do
+      molecule <- (backslashedP <|> try allQuotedP <|> try bracketP <|> nonSpecialCharP)
+      rest <- innerInputP
+
+      return [ L.append a b | a <- molecule, b <- rest ]
+
+    innerInputP :: Parser [L.Text]
+    innerInputP = (innerNonEmptyInputP <|> emptyInputP)
+
+    nonEmptyInputP :: Parser [L.Text]
+    nonEmptyInputP = do
+      molecule <- (backslashedP <|> try allQuotedP <|> try bracketP <|> charP)
+      rest <- inputP
+
+      return [ L.append a b | a <- molecule, b <- rest ]
+
+    emptyInputP :: Parser [L.Text]
+    emptyInputP = do
+      return [""]
+
+    inputP :: Parser [L.Text]
+    inputP = (nonEmptyInputP <|> emptyInputP)
+
 -- | Curly braces (brackets) expand function
 --
 -- First argument is a `Data.Text`, which you want to expand. Second argument is a list of expanded `Data.Text`s.
@@ -141,7 +271,5 @@
 
 curlyExpand :: T.Text -> [T.Text]
 curlyExpand input =
-  case parse inputP "bracket expansion"$ input of
-    Left _ -> [input]
-    Right ret -> map L.toStrict ret
+  customCurlyExpand defaultExpandConfig input
 
diff --git a/curly-expander.cabal b/curly-expander.cabal
--- a/curly-expander.cabal
+++ b/curly-expander.cabal
@@ -1,9 +1,9 @@
 cabal-version:       3.0
 
 name:                curly-expander
-version:             0.2.0.3
+version:             0.3.0.0
 synopsis:            Curly braces (brackets) expanding
-description:         A library for curly braces (brackets) expanding - similar to bash curly expanding
+description:         A library for curly braces (brackets) expanding - similar to bash curly expanding. It also contain an extended version of it.
 
 license:             LGPL-3.0-only
 license-file:        LICENSE
@@ -47,6 +47,11 @@
   main-is: NestedCaseTest.hs
   type: exitcode-stdio-1.0
 
+test-suite custom-case-test
+  import: tests
+  main-is: CustomCaseTest.hs
+  type: exitcode-stdio-1.0
+
 source-repository head
     type: git
     location: https://github.com/stastnypremysl/curly-expander
@@ -54,4 +59,4 @@
 source-repository this
     type: git
     location: https://github.com/stastnypremysl/curly-expander
-    tag: 0.2.0.3
+    tag: 0.3.0.0
diff --git a/tests/CustomCaseTest.hs b/tests/CustomCaseTest.hs
new file mode 100644
--- /dev/null
+++ b/tests/CustomCaseTest.hs
@@ -0,0 +1,123 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import Prelude
+import Control.Monad
+import System.Exit 
+import Text.CurlyExpander
+
+import qualified Data.Text as T
+
+denyOneElement :: Bool
+denyOneElement = (curlyExpand "{a}" == ["{a}"])
+
+allowOneElement :: Bool
+allowOneElement = (expand "{a}" == ["a"])
+  where
+    expand :: T.Text -> [T.Text]
+    expand = customCurlyExpand (defaultExpandConfig {allowOneElementExpand = True})
+
+escapedString :: T.Text
+escapedString = "\\ab\\c"
+
+escapedString2 :: T.Text
+escapedString2 = "a{1,2}bc\\{,5}"
+
+noEscaping :: Bool
+noEscaping = (curlyExpand escapedString == [escapedString])
+
+preserveEscaping :: Bool
+preserveEscaping = (expand escapedString == [escapedString])
+  where
+    expand :: T.Text -> [T.Text]
+    expand = customCurlyExpand (defaultExpandConfig {backslashConfig = Preserve})
+
+standardEscapeConfig :: ExpandConfig
+standardEscapeConfig = defaultExpandConfig {backslashConfig = Standard}
+
+standardEscaping :: Bool
+standardEscaping = (customCurlyExpand standardEscapeConfig escapedString == ["abc"])
+
+standardEscaping2 :: Bool
+standardEscaping2 = (customCurlyExpand standardEscapeConfig escapedString2 == ["a1bc{,5}", "a2bc{,5}"])
+
+quotedString1 :: T.Text
+quotedString1 = "abc''abc''abc"
+
+quotedString2 :: T.Text
+quotedString2 = "a[ab]cc"
+
+quotedString3 :: T.Text
+quotedString3 = "a[{a,b}]c"
+
+quotedString4 :: T.Text
+quotedString4 = "a{b,[{1..2}]}c"
+
+qPairs1 :: [(String, String)]
+qPairs1 = [("[", "]")]
+
+qPairs2 :: [(String, String)]
+qPairs2 = qPairs1 ++ [("''", "''")]
+
+queted1PersistE :: T.Text -> [T.Text]
+queted1PersistE = customCurlyExpand (defaultExpandConfig {persistQuotePairs = True, quotePairs = qPairs1})
+
+queted1NopersistE :: T.Text -> [T.Text]
+queted1NopersistE = customCurlyExpand (defaultExpandConfig {persistQuotePairs = False, quotePairs = qPairs1})
+
+queted2PersistE :: T.Text -> [T.Text]
+queted2PersistE = customCurlyExpand (defaultExpandConfig {persistQuotePairs = True, quotePairs = qPairs2})
+
+queted2NopersistE :: T.Text -> [T.Text]
+queted2NopersistE = customCurlyExpand (defaultExpandConfig {persistQuotePairs = False, quotePairs = qPairs2})
+
+queted1Persist1 :: Bool
+queted1Persist1 = ( queted1PersistE quotedString1 == [quotedString1] )
+
+queted1Nopersist1 :: Bool
+queted1Nopersist1 = ( queted1NopersistE quotedString1 == [quotedString1] )
+
+queted2Persist1 :: Bool
+queted2Persist1 = ( queted2PersistE quotedString1 == [quotedString1] )
+
+queted2Nopersist1 :: Bool
+queted2Nopersist1 = ( queted2NopersistE quotedString1 == ["abcabcabc"] )
+
+queted2Persist2 :: Bool
+queted2Persist2 = ( queted2PersistE quotedString2 == [quotedString2] )
+
+queted2Nopersist2 :: Bool
+queted2Nopersist2 = ( queted2NopersistE quotedString2 == ["aabcc"] )
+
+queted2Persist3 :: Bool
+queted2Persist3 = ( queted2PersistE quotedString3 == [quotedString3] )
+
+queted2Nopersist4 :: Bool
+queted2Nopersist4 = ( queted2NopersistE quotedString4 == ["abc", "a{1..2}c"] )
+
+main :: IO a
+main = do
+  when (not denyOneElement) $ die "Test denyOneElement failed"
+  when (not allowOneElement) $ die "Test allowOneElement failed"
+
+  when (not noEscaping) $ die "Test noEscaping failed"
+  when (not preserveEscaping) $ die "Test preserveEscaping failed"
+  when (not standardEscaping) $ die "Test standardEscaping failed"
+  when (not standardEscaping2) $ die "Test standardEscaping2 failed"
+
+  when (not queted1Persist1) $ die "Test queted1Persist1 failed"
+  when (not queted1Nopersist1) $ die "Test queted1Nopersist1 failed"
+  when (not queted2Persist1) $ die "Test queted2Persist1 failed"
+  when (not queted2Nopersist1) $ die "Test queted2Nopersist1 failed"
+
+  when (not queted2Persist2) $ die "Test queted2Persist2 failed"
+  when (not queted2Nopersist2) $ die "Test queted2Nopersist2 failed"
+
+  when (not queted2Persist3) $ die "Test queted2Persist3 failed"
+
+  when (not queted2Nopersist4) $ die "Test queted2Nopersist4 failed"
+
+
+  exitSuccess
+
+  
