diff --git a/Data/Text/Format/Heavy.hs b/Data/Text/Format/Heavy.hs
--- a/Data/Text/Format/Heavy.hs
+++ b/Data/Text/Format/Heavy.hs
@@ -38,5 +38,5 @@
 import Data.Text.Format.Heavy.Types
 import Data.Text.Format.Heavy.Formats
 import Data.Text.Format.Heavy.Build (format)
-import Data.Text.Format.Heavy.Instances (Single (..), Shown (..))
+import Data.Text.Format.Heavy.Instances hiding (genericIntFormat, genericFloatFormat)
 
diff --git a/Data/Text/Format/Heavy/Build.hs b/Data/Text/Format/Heavy/Build.hs
--- a/Data/Text/Format/Heavy/Build.hs
+++ b/Data/Text/Format/Heavy/Build.hs
@@ -4,7 +4,7 @@
   (format, formatEither,
    makeBuilder,
    -- * Formatters building utilities
-   align, applySign, applySharp,
+   align, applySign, applySharp, convertText,
    formatInt, formatStr, formatFloat, formatBool
   ) where
 
@@ -77,6 +77,16 @@
 applySharp True Decimal text = text
 applySharp True Hexadecimal text = B.fromLazyText "0x" <> text
 
+-- | Apply text conversion.
+convertText :: Maybe Conversion -> B.Builder -> B.Builder
+convertText Nothing builder = builder
+convertText (Just conv) builder = B.fromLazyText $ converter $ B.toLazyText builder
+  where
+    converter = case conv of
+                  UpperCase -> TL.toUpper
+                  LowerCase -> TL.toLower
+                  TitleCase -> TL.toTitle
+
 -- | Format integer number according to GenericFormat
 formatInt :: Integral a => GenericFormat -> a -> B.Builder
 formatInt fmt x = align fmt $ applySign (gfSign fmt) x $ applySharp (gfLeading0x fmt) radix $ inRadix
@@ -89,11 +99,14 @@
 -- | Format floating-point number according to GenericFormat
 formatFloat :: RealFloat a => GenericFormat -> a -> B.Builder
 formatFloat fmt x =
-  align fmt $ applySign (gfSign fmt) x $ formatRealFloat Fixed (gfPrecision fmt) $ abs x
+    align fmt
+    $ applySign (gfSign fmt) x
+    $ formatRealFloat Fixed (gfPrecision fmt)
+    $ abs x
 
 -- | Format Text according to GenericFormat.
 formatStr :: GenericFormat -> TL.Text -> B.Builder
-formatStr fmt text = align fmt $ B.fromLazyText text
+formatStr fmt text = convertText (gfConvert fmt) $ align fmt $ B.fromLazyText text
 
 -- | Format boolean value.
 formatBool :: BoolFormat -> Bool -> B.Builder
diff --git a/Data/Text/Format/Heavy/Formats.hs b/Data/Text/Format/Heavy/Formats.hs
--- a/Data/Text/Format/Heavy/Formats.hs
+++ b/Data/Text/Format/Heavy/Formats.hs
@@ -19,6 +19,13 @@
 data Radix = Decimal | Hexadecimal
   deriving (Eq, Show)
 
+-- | Supported text conversions
+data Conversion =
+    UpperCase
+  | LowerCase
+  | TitleCase
+  deriving (Eq, Show)
+
 -- | Generic format description. This is usable for integers, floats and strings.
 data GenericFormat = GenericFormat {
     gfFillChar :: Char
@@ -28,6 +35,7 @@
   , gfWidth :: Maybe Int
   , gfPrecision :: Maybe Int
   , gfRadix :: Maybe Radix
+  , gfConvert :: Maybe Conversion
   }
   deriving (Eq, Show)
 
@@ -40,6 +48,7 @@
         , gfWidth = Nothing
         , gfPrecision = Nothing
         , gfRadix = Nothing
+        , gfConvert = Nothing
         }
 
 data BoolFormat = BoolFormat {
diff --git a/Data/Text/Format/Heavy/Instances.hs b/Data/Text/Format/Heavy/Instances.hs
--- a/Data/Text/Format/Heavy/Instances.hs
+++ b/Data/Text/Format/Heavy/Instances.hs
@@ -4,7 +4,7 @@
   (-- * Utility data types
    Single (..), Several (..), Shown (..),
    -- * Combinators
-   DefaultValue (..), ThenCheck (..),
+   DefaultValue (..), ThenCheck (..), WithDefault,
    withDefault, optional,
    -- * Generic formatters
    genericIntFormat, genericFloatFormat
@@ -261,6 +261,48 @@
   lookupVar "6" (_,_,_,_,_,_,g) = Just $ Variable g
   lookupVar _ _ = Nothing
 
+instance (Formatable a, Formatable b, Formatable c, Formatable d, Formatable e, Formatable f, Formatable g,
+          Formatable h)
+     => VarContainer (a, b, c, d, e, f, g, h) where
+  lookupVar "0" (a,_,_,_,_,_,_,_) = Just $ Variable a
+  lookupVar "1" (_,b,_,_,_,_,_,_) = Just $ Variable b
+  lookupVar "2" (_,_,c,_,_,_,_,_) = Just $ Variable c
+  lookupVar "3" (_,_,_,d,_,_,_,_) = Just $ Variable d
+  lookupVar "4" (_,_,_,_,e,_,_,_) = Just $ Variable e
+  lookupVar "5" (_,_,_,_,_,f,_,_) = Just $ Variable f
+  lookupVar "6" (_,_,_,_,_,_,g,_) = Just $ Variable g
+  lookupVar "7" (_,_,_,_,_,_,_,h) = Just $ Variable h
+  lookupVar _ _ = Nothing
+
+instance (Formatable a, Formatable b, Formatable c, Formatable d, Formatable e, Formatable f, Formatable g,
+          Formatable h, Formatable i)
+     => VarContainer (a, b, c, d, e, f, g, h, i) where
+  lookupVar "0" (a,_,_,_,_,_,_,_,_) = Just $ Variable a
+  lookupVar "1" (_,b,_,_,_,_,_,_,_) = Just $ Variable b
+  lookupVar "2" (_,_,c,_,_,_,_,_,_) = Just $ Variable c
+  lookupVar "3" (_,_,_,d,_,_,_,_,_) = Just $ Variable d
+  lookupVar "4" (_,_,_,_,e,_,_,_,_) = Just $ Variable e
+  lookupVar "5" (_,_,_,_,_,f,_,_,_) = Just $ Variable f
+  lookupVar "6" (_,_,_,_,_,_,g,_,_) = Just $ Variable g
+  lookupVar "7" (_,_,_,_,_,_,_,h,_) = Just $ Variable h
+  lookupVar "8" (_,_,_,_,_,_,_,_,i) = Just $ Variable i
+  lookupVar _ _ = Nothing
+
+instance (Formatable a, Formatable b, Formatable c, Formatable d, Formatable e, Formatable f, Formatable g,
+          Formatable h, Formatable i, Formatable j)
+     => VarContainer (a, b, c, d, e, f, g, h, i, j) where
+  lookupVar "0" (a,_,_,_,_,_,_,_,_,_) = Just $ Variable a
+  lookupVar "1" (_,b,_,_,_,_,_,_,_,_) = Just $ Variable b
+  lookupVar "2" (_,_,c,_,_,_,_,_,_,_) = Just $ Variable c
+  lookupVar "3" (_,_,_,d,_,_,_,_,_,_) = Just $ Variable d
+  lookupVar "4" (_,_,_,_,e,_,_,_,_,_) = Just $ Variable e
+  lookupVar "5" (_,_,_,_,_,f,_,_,_,_) = Just $ Variable f
+  lookupVar "6" (_,_,_,_,_,_,g,_,_,_) = Just $ Variable g
+  lookupVar "7" (_,_,_,_,_,_,_,h,_,_) = Just $ Variable h
+  lookupVar "8" (_,_,_,_,_,_,_,_,i,_) = Just $ Variable i
+  lookupVar "9" (_,_,_,_,_,_,_,_,_,j) = Just $ Variable j
+  lookupVar _ _ = Nothing
+
 instance Formatable a => VarContainer (Several a) where
   lookupVar name (Several lst) =
     if not $ TL.all isDigit name
@@ -286,15 +328,22 @@
 -- and if variable is not found there it will check in @c2@.
 data ThenCheck c1 c2 = ThenCheck c1 c2
 
+-- | Convenience type synonym.
+type WithDefault c = ThenCheck c DefaultValue
+
 instance (VarContainer c1, VarContainer c2) => VarContainer (ThenCheck c1 c2) where
   lookupVar name (ThenCheck c1 c2) =
     case lookupVar name c1 of
       Just result -> Just result
       Nothing -> lookupVar name c2
 
-withDefault :: VarContainer c => c -> Variable -> ThenCheck c DefaultValue
+-- | Use variables from specified container, or use default value if
+-- variable is not found in container.
+withDefault :: VarContainer c => c -> Variable -> WithDefault c
 withDefault c value = c `ThenCheck` DefaultValue value
 
-optional :: VarContainer c => c -> ThenCheck c DefaultValue
+-- | Use variables from specified container, or use empty string
+-- variable is not found in container.
+optional :: VarContainer c => c -> WithDefault c
 optional c = c `withDefault` (Variable TL.empty)
 
diff --git a/Data/Text/Format/Heavy/Parse/Braces.hs b/Data/Text/Format/Heavy/Parse/Braces.hs
--- a/Data/Text/Format/Heavy/Parse/Braces.hs
+++ b/Data/Text/Format/Heavy/Parse/Braces.hs
@@ -43,7 +43,7 @@
     return $ FVariable (TL.pack name) fmt
   where
     variable = do
-      name <- many alphaNum
+      name <- many $ try alphaNum <|> try (char '-') <|> char '.'
       mbColon <- optionMaybe $ char ':'
       fmt <- case mbColon of
                Nothing -> return Nothing
diff --git a/Data/Text/Format/Heavy/Parse/Shell.hs b/Data/Text/Format/Heavy/Parse/Shell.hs
--- a/Data/Text/Format/Heavy/Parse/Shell.hs
+++ b/Data/Text/Format/Heavy/Parse/Shell.hs
@@ -64,7 +64,7 @@
     return $ FVariable (TL.pack name) fmt
   where
     bracedVariable = between (char '{') (char '}') $ do
-      name <- many alphaNum
+      name <- many $ try alphaNum <|> try (char '-') <|> char '.'
       mbColon <- optionMaybe $ char ':'
       fmt <- case mbColon of
                Nothing -> return Nothing
diff --git a/Data/Text/Format/Heavy/Parse/VarFormat.hs b/Data/Text/Format/Heavy/Parse/VarFormat.hs
--- a/Data/Text/Format/Heavy/Parse/VarFormat.hs
+++ b/Data/Text/Format/Heavy/Parse/VarFormat.hs
@@ -25,6 +25,7 @@
     mbWidth <- optionMaybe (pWidth <?> "width specification")
     mbPrecision <- optionMaybe (pPrecision <?> "precision specification")
     mbRadix <- optionMaybe (pRadix <?> "radix specification")
+    mbConvert <- optionMaybe (pConvert <?> "conversion specification")
     return $ GenericFormat {
                gfFillChar = fill
              , gfAlign = align
@@ -33,6 +34,7 @@
              , gfWidth = mbWidth
              , gfPrecision = mbPrecision
              , gfRadix = mbRadix
+             , gfConvert = mbConvert
              }
   where
     pAlign :: Parsec TL.Text st Align
@@ -98,12 +100,21 @@
         'h' -> return Hexadecimal
         'd' -> return Decimal
 
+    pConvert :: Parsec TL.Text st Conversion
+    pConvert = do
+      char '~'
+      conv <- oneOf "ult"
+      case conv of
+        'u' -> return UpperCase
+        'l' -> return LowerCase
+        't' -> return TitleCase
+
 -- | Parse generic variable format.
 --
 -- Syntax is:
 --
 -- @
--- [[fill]align][sign][#][width][.precision][radix]
+-- [[fill]align][sign][#][width][.precision][radix][~conversion]
 -- @
 --
 -- where:
@@ -115,6 +126,8 @@
 -- * width - minimum length of the field
 -- * precision - number of decimal places after point, for floatting-point numbers
 -- * radix - @h@ or @x@ for hexadecimal, @d@ for decimal (default).
+-- * conversion - text conversion symbol. Supported are: @u@ - convert to upper case,
+--   @l@ - convert to lower case, @t@ - convert to title case (capitalize all words).
 --
 parseGenericFormat :: TL.Text -> Either ParseError GenericFormat
 parseGenericFormat text = runParser pGenericFormat () "<variable format specification>" text
diff --git a/Data/Text/Format/Heavy/Types.hs b/Data/Text/Format/Heavy/Types.hs
--- a/Data/Text/Format/Heavy/Types.hs
+++ b/Data/Text/Format/Heavy/Types.hs
@@ -21,12 +21,20 @@
       vName :: VarName      -- ^ Variable name
     , vFormat :: VarFormat  -- ^ Variable format
     }
-  deriving (Show)
+  deriving (Eq)
 
+instance Show FormatItem where
+  show (FString text) = TL.unpack text
+  show (FVariable name Nothing) = TL.unpack $ "{" <> name <> "}"
+  show (FVariable name (Just fmt)) = TL.unpack $ "{" <> name <> ":" <> fmt <> "}"
+
 -- | String format
 data Format = Format [FormatItem]
-  deriving (Show)
+  deriving (Eq)
 
+instance Show Format where
+  show (Format lst) = concat $ map show lst
+
 instance Monoid Format where
   mempty = Format []
   mappend (Format xs) (Format ys) = Format (xs ++ ys)
@@ -52,6 +60,12 @@
 -- This type may be also used to construct heterogeneous lists:
 -- @[Variable 1, Variable "x"] :: [Variable]@.
 data Variable = forall a. Formatable a => Variable a
+
+instance Show Variable where
+  show (Variable v) = either error toString $ formatVar Nothing v
+    where
+      toString :: B.Builder -> String
+      toString b = TL.unpack $ B.toLazyText b
 
 instance Formatable Variable where
   formatVar fmt (Variable x) = formatVar fmt x
diff --git a/examples/test.hs b/examples/test.hs
--- a/examples/test.hs
+++ b/examples/test.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 
 import Data.Time
+import qualified Data.Text.Lazy as TL
 import qualified Data.Text.Lazy.IO as TLIO
 import Data.Text.Format.Heavy
 import Data.Text.Format.Heavy.Time
@@ -13,7 +14,16 @@
       xs = (18 :: Int, "hello" :: String, 2.718281828 :: Double, Shown (Just (7 :: Int)), Just (8 :: Int), rt, True)
   TLIO.putStrLn $ format template xs
   time <- getZonedTime
-  TLIO.putStrLn $ format "Hello, {}! It is {:%H:%M:%S} now." $ ("Ilya" :: String, time)
+  let vars :: [(TL.Text, Variable)]
+      vars = [("name", Variable ("Ilya" :: String)),
+              ("time", Variable time),
+              ("header.content-type", Variable ("text/json" :: String)),
+              ("upper", Variable ("this will be uppercase" :: String)),
+              ("lower", Variable ("This will be ALL lower case" :: String)),
+              ("title", Variable ("this is the title" :: String)),
+              ("noun", Variable ("string" :: String))]
+  TLIO.putStrLn $
+    format "Hello, {name}! It is {time:%H:%M:%S} now. Test {noun}ification. Content: {header.content-type} x. Upper: <{upper:~u}>, lower <{lower:~l}>, title: <{title:~t}>." vars
   let mbX = Nothing :: Maybe Float
       mbY = Just 7.37491 :: Maybe Float
       mbZ = Nothing :: Maybe Float
diff --git a/text-format-heavy.cabal b/text-format-heavy.cabal
--- a/text-format-heavy.cabal
+++ b/text-format-heavy.cabal
@@ -1,5 +1,5 @@
 name:                text-format-heavy
-version:             0.1.4.0
+version:             0.1.5.0
 synopsis:            Full-weight string formatting library, analog of Python's string.format
 description:         This package contains full-featured string formatting function, similar to
                      Python's string.format. Features include:
