2016-04-24 02:53:11 +03:00
local helpers = require ( ' test.functional.helpers ' ) ( after_each )
2015-03-20 13:58:42 +01:00
local Screen = require ( ' test.functional.ui.screen ' )
2017-04-09 03:07:02 +03:00
2016-02-24 01:42:38 +01:00
local clear , feed , insert = helpers.clear , helpers.feed , helpers.insert
2018-01-13 10:15:23 +01:00
local command , neq = helpers.command , helpers.neq
2018-12-07 17:28:51 +01:00
local meths = helpers.meths
2018-10-23 10:10:23 +02:00
local curbufmeths , eq = helpers.curbufmeths , helpers.eq
2015-03-20 13:58:42 +01:00
describe ( ' Buffer highlighting ' , function ( )
local screen
before_each ( function ( )
clear ( )
2017-04-09 03:23:16 +03:00
command ( ' syntax on ' )
2015-03-20 13:58:42 +01:00
screen = Screen.new ( 40 , 8 )
screen : attach ( )
screen : set_default_attr_ids ( {
2016-08-09 14:00:41 +02:00
[ 1 ] = { bold = true , foreground = Screen.colors . Blue } ,
[ 2 ] = { foreground = Screen.colors . Fuchsia } , -- String
[ 3 ] = { foreground = Screen.colors . Brown , bold = true } , -- Statement
[ 4 ] = { foreground = Screen.colors . SlateBlue } , -- Special
[ 5 ] = { bold = true , foreground = Screen.colors . SlateBlue } ,
[ 6 ] = { foreground = Screen.colors . DarkCyan } , -- Identifier
[ 7 ] = { bold = true } ,
[ 8 ] = { underline = true , bold = true , foreground = Screen.colors . SlateBlue } ,
2017-10-19 11:46:07 +02:00
[ 9 ] = { foreground = Screen.colors . SlateBlue , underline = true } ,
2018-03-24 14:26:20 +01:00
[ 10 ] = { foreground = Screen.colors . Red } ,
[ 11 ] = { foreground = Screen.colors . Grey100 , background = Screen.colors . Red } ,
[ 12 ] = { foreground = Screen.colors . Blue1 } ,
[ 13 ] = { background = Screen.colors . LightGrey } ,
2018-10-23 10:10:23 +02:00
[ 14 ] = { background = Screen.colors . Gray90 } ,
[ 15 ] = { background = Screen.colors . Gray90 , bold = true , foreground = Screen.colors . Brown } ,
[ 16 ] = { foreground = Screen.colors . Magenta , background = Screen.colors . Gray90 } ,
2015-03-20 13:58:42 +01:00
} )
end )
after_each ( function ( )
screen : detach ( )
end )
2018-11-29 15:08:40 +01:00
local add_highlight = curbufmeths.add_highlight
local clear_namespace = curbufmeths.clear_namespace
2015-03-20 13:58:42 +01:00
it ( ' works ' , function ( )
insert ( [ [
these are some lines
with colorful text ] ] )
feed ( ' + ' )
screen : expect ( [ [
these are some lines |
with colorful tex ^ t |
2016-08-09 14:00:41 +02:00
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2015-03-20 13:58:42 +01:00
|
] ] )
2018-11-29 15:08:40 +01:00
add_highlight ( - 1 , " String " , 0 , 10 , 14 )
add_highlight ( - 1 , " Statement " , 1 , 5 , - 1 )
2015-03-20 13:58:42 +01:00
screen : expect ( [ [
2016-08-09 14:00:41 +02:00
these are { 2 : some } lines |
with { 3 : colorful tex ^ t } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2015-03-20 13:58:42 +01:00
|
] ] )
feed ( " ggo<esc> " )
screen : expect ( [ [
2016-08-09 14:00:41 +02:00
these are { 2 : some } lines |
2015-03-20 13:58:42 +01:00
^ |
2016-08-09 14:00:41 +02:00
with { 3 : colorful text } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2015-03-20 13:58:42 +01:00
|
] ] )
2018-11-29 15:08:40 +01:00
clear_namespace ( - 1 , 0 , - 1 )
2015-03-20 13:58:42 +01:00
screen : expect ( [ [
these are some lines |
^ |
with colorful text |
2016-08-09 14:00:41 +02:00
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2015-03-20 13:58:42 +01:00
|
] ] )
end )
2018-11-29 15:08:40 +01:00
describe ( ' support using multiple namespaces ' , function ( )
2015-03-20 13:58:42 +01:00
local id1 , id2
before_each ( function ( )
insert ( [ [
a longer example
in order to demonstrate
combining highlights
from different sources ] ] )
2017-04-09 00:12:26 +03:00
command ( " hi ImportantWord gui=bold cterm=bold " )
2018-11-29 15:08:40 +01:00
id1 = add_highlight ( 0 , " ImportantWord " , 0 , 2 , 8 )
add_highlight ( id1 , " ImportantWord " , 1 , 12 , - 1 )
add_highlight ( id1 , " ImportantWord " , 2 , 0 , 9 )
add_highlight ( id1 , " ImportantWord " , 3 , 5 , 14 )
2015-03-20 13:58:42 +01:00
2016-08-16 21:55:37 +02:00
-- add_highlight can be called like this to get a new source
-- without adding any highlight
2018-11-29 15:08:40 +01:00
id2 = add_highlight ( 0 , " " , 0 , 0 , 0 )
2016-08-16 21:55:37 +02:00
neq ( id1 , id2 )
2018-11-29 15:08:40 +01:00
add_highlight ( id2 , " Special " , 0 , 2 , 8 )
add_highlight ( id2 , " Identifier " , 1 , 3 , 8 )
add_highlight ( id2 , " Special " , 1 , 14 , 20 )
add_highlight ( id2 , " Underlined " , 2 , 6 , 12 )
add_highlight ( id2 , " Underlined " , 3 , 0 , 9 )
2015-03-20 13:58:42 +01:00
screen : expect ( [ [
2016-08-09 14:00:41 +02:00
a { 5 : longer } example |
in { 6 : order } to { 7 : de } { 5 : monstr } { 7 : ate } |
{ 7 : combin } { 8 : ing } { 9 : hi } ghlights |
{ 9 : from } { 8 : diff } { 7 : erent } source ^ s |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2017-04-09 03:07:02 +03:00
|
2015-03-20 13:58:42 +01:00
] ] )
end )
it ( ' and clearing the first added ' , function ( )
2018-11-29 15:08:40 +01:00
clear_namespace ( id1 , 0 , - 1 )
screen : expect ( [ [
a { 4 : longer } example |
in { 6 : order } to de { 4 : monstr } ate |
combin { 9 : ing hi } ghlights |
{ 9 : from diff } erent source ^ s |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
end )
it ( ' and clearing using deprecated name ' , function ( )
curbufmeths.clear_highlight ( id1 , 0 , - 1 )
2015-03-20 13:58:42 +01:00
screen : expect ( [ [
2016-08-09 14:00:41 +02:00
a { 4 : longer } example |
in { 6 : order } to de { 4 : monstr } ate |
combin { 9 : ing hi } ghlights |
{ 9 : from diff } erent source ^ s |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2017-04-09 03:07:02 +03:00
|
2015-03-20 13:58:42 +01:00
] ] )
end )
it ( ' and clearing the second added ' , function ( )
2018-11-29 15:08:40 +01:00
clear_namespace ( id2 , 0 , - 1 )
2015-03-20 13:58:42 +01:00
screen : expect ( [ [
2016-08-09 14:00:41 +02:00
a { 7 : longer } example |
in order to { 7 : demonstrate } |
{ 7 : combining } highlights |
from { 7 : different } source ^ s |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2017-04-09 03:07:02 +03:00
|
2015-03-20 13:58:42 +01:00
] ] )
end )
it ( ' and clearing line ranges ' , function ( )
2018-11-29 15:08:40 +01:00
clear_namespace ( - 1 , 0 , 1 )
clear_namespace ( id1 , 1 , 2 )
clear_namespace ( id2 , 2 , - 1 )
2015-03-20 13:58:42 +01:00
screen : expect ( [ [
a longer example |
2016-08-09 14:00:41 +02:00
in { 6 : order } to de { 4 : monstr } ate |
{ 7 : combining } highlights |
from { 7 : different } source ^ s |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2017-04-09 03:07:02 +03:00
|
2015-03-20 13:58:42 +01:00
] ] )
end )
it ( ' and renumbering lines ' , function ( )
feed ( ' 3Gddggo<esc> ' )
screen : expect ( [ [
2016-08-09 14:00:41 +02:00
a { 5 : longer } example |
2015-03-20 13:58:42 +01:00
^ |
2016-08-09 14:00:41 +02:00
in { 6 : order } to { 7 : de } { 5 : monstr } { 7 : ate } |
{ 9 : from } { 8 : diff } { 7 : erent } sources |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2015-03-20 13:58:42 +01:00
|
] ] )
2017-04-09 00:12:26 +03:00
command ( ' :3move 4 ' )
2015-03-20 13:58:42 +01:00
screen : expect ( [ [
2016-08-09 14:00:41 +02:00
a { 5 : longer } example |
2015-03-20 13:58:42 +01:00
|
2016-08-09 14:00:41 +02:00
{ 9 : from } { 8 : diff } { 7 : erent } sources |
^ in { 6 : order } to { 7 : de } { 5 : monstr } { 7 : ate } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2017-04-09 03:07:02 +03:00
|
2015-03-20 13:58:42 +01:00
] ] )
end )
end )
it ( ' prioritizes latest added highlight ' , function ( )
insert ( [ [
three overlapping colors ] ] )
2018-11-29 15:08:40 +01:00
add_highlight ( 0 , " Identifier " , 0 , 6 , 17 )
add_highlight ( 0 , " String " , 0 , 14 , 23 )
local id = add_highlight ( 0 , " Special " , 0 , 0 , 9 )
2015-03-20 13:58:42 +01:00
screen : expect ( [ [
2016-08-09 14:00:41 +02:00
{ 4 : three ove } { 6 : rlapp } { 2 : ing color } ^ s |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2015-03-20 13:58:42 +01:00
|
] ] )
2018-11-29 15:08:40 +01:00
clear_namespace ( id , 0 , 1 )
2015-03-20 13:58:42 +01:00
screen : expect ( [ [
2016-08-09 14:00:41 +02:00
three { 6 : overlapp } { 2 : ing color } ^ s |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2015-03-20 13:58:42 +01:00
|
] ] )
end )
it ( ' works with multibyte text ' , function ( )
insert ( [ [
Ta båten ö ver sjön ! ] ] )
2018-11-29 15:08:40 +01:00
add_highlight ( - 1 , " Identifier " , 0 , 3 , 9 )
add_highlight ( - 1 , " String " , 0 , 16 , 21 )
2015-03-20 13:58:42 +01:00
screen : expect ( [ [
2016-08-09 14:00:41 +02:00
Ta { 6 : båten } ö ver { 2 : sjön } ^ ! |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
2015-03-20 13:58:42 +01:00
|
] ] )
end )
2017-10-19 11:46:07 +02:00
it ( ' works with new syntax groups ' , function ( )
insert ( [ [
fancy code in a new fancy language ] ] )
2018-11-29 15:08:40 +01:00
add_highlight ( - 1 , " FancyLangItem " , 0 , 0 , 5 )
2017-10-19 11:46:07 +02:00
screen : expect ( [ [
fancy code in a new fancy languag ^ e |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
command ( ' hi FancyLangItem guifg=red ' )
screen : expect ( [ [
{ 10 : fancy } code in a new fancy languag ^ e |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
end )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
describe ( ' virtual text annotations ' , function ( )
2018-03-24 14:26:20 +01:00
local set_virtual_text = curbufmeths.set_virtual_text
2018-10-23 10:10:23 +02:00
local id1 , id2
before_each ( function ( )
insert ( [ [
1 + 2
3 +
x = 4 ] ] )
feed ( ' O<esc>20A5, <esc>gg ' )
screen : expect ( [ [
^ 1 + 2 |
3 + |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
id1 = set_virtual_text ( 0 , 0 , { { " = " , " Statement " } , { " 3 " , " Number " } } , { } )
set_virtual_text ( id1 , 1 , { { " ERROR: " , " ErrorMsg " } , { " invalid syntax " } } , { } )
id2 = set_virtual_text ( 0 , 2 , { { " Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " } } , { } )
neq ( id2 , id1 )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
end )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
it ( ' works ' , function ( )
screen : expect ( [ [
^ 1 + 2 { 3 : = } { 2 : 3 } |
3 + { 11 : ERROR : } invalid syntax |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
2018-03-24 14:26:20 +01:00
2018-11-29 15:08:40 +01:00
clear_namespace ( id1 , 0 , - 1 )
2018-10-23 10:10:23 +02:00
screen : expect ( [ [
^ 1 + 2 |
3 + |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
-- Handles doublewidth chars, leaving a space if truncating
-- in the middle of a char
eq ( - 1 , set_virtual_text ( - 1 , 1 , { { " 暗x事zz速野谷質結育副住新覚丸活解終事 " , " Comment " } } , { } ) )
screen : expect ( [ [
^ 1 + 2 |
3 + { 12 : 暗 x事zz速野谷質結育副住新覚丸活解終 } |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
feed ( " 2Gx " )
screen : expect ( [ [
1 + 2 |
^ + { 12 : 暗 x事zz速野谷質結育副住新覚丸活解終事 } |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
feed ( " 2Gdd " )
screen : expect ( [ [
1 + 2 |
^ 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
end )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
it ( ' is not highlighted by visual selection ' , function ( )
feed ( " ggVG " )
screen : expect ( [ [
{ 13 : 1 + 2 } { 3 : = } { 2 : 3 } |
{ 13 : 3 + } { 11 : ERROR : } invalid syntax |
{ 13 : 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 } |
{ 13 : , 5 , 5 , 5 , 5 , 5 , 5 , } Lorem ipsum dolor s |
^ x { 13 : = 4 } |
{ 1 : ~ } |
{ 1 : ~ } |
{ 7 : -- VISUAL LINE --} |
] ] )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
feed ( " <esc> " )
screen : expect ( [ [
1 + 2 { 3 : = } { 2 : 3 } |
3 + { 11 : ERROR : } invalid syntax |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
^ x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
-- special case: empty line has extra eol highlight
feed ( " ggd$ " )
screen : expect ( [ [
^ { 3 : = } { 2 : 3 } |
3 + { 11 : ERROR : } invalid syntax |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
2018-03-24 14:26:20 +01:00
2018-10-23 10:10:23 +02:00
feed ( " jvk " )
screen : expect ( [ [
^ { 3 : = } { 2 : 3 } |
{ 13 : 3 } + { 11 : ERROR : } invalid syntax |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
{ 7 : -- VISUAL --} |
] ] )
feed ( " o " )
screen : expect ( [ [
{ 13 : } { 3 : = } { 2 : 3 } |
^ 3 + { 11 : ERROR : } invalid syntax |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
{ 7 : -- VISUAL --} |
] ] )
end )
it ( ' works with listchars ' , function ( )
command ( " set list listchars+=eol:$ " )
screen : expect ( [ [
^ 1 + 2 { 1 : $ } { 3 : = } { 2 : 3 } |
3 + { 1 : $ } { 11 : ERROR : } invalid syntax |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , { 1 : - $ } Lorem ipsum dolor s |
x = 4 { 1 : $ } |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
2018-11-29 15:08:40 +01:00
clear_namespace ( - 1 , 0 , - 1 )
2018-10-23 10:10:23 +02:00
screen : expect ( [ [
^ 1 + 2 { 1 : $ } |
3 + { 1 : $ } |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , { 1 : - $ } |
x = 4 { 1 : $ } |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
end )
it ( ' works with cursorline ' , function ( )
command ( " set cursorline " )
screen : expect ( [ [
{ 14 : ^ 1 + 2 } { 15 : = } { 16 : 3 } { 14 : } |
3 + { 11 : ERROR : } invalid syntax |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
feed ( ' j ' )
screen : expect ( [ [
1 + 2 { 3 : = } { 2 : 3 } |
{ 14 : ^ 3 + } { 11 : ERROR : } { 14 : invalid syntax } |
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 |
, 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
feed ( ' j ' )
screen : expect ( [ [
1 + 2 { 3 : = } { 2 : 3 } |
3 + { 11 : ERROR : } invalid syntax |
{ 14 : ^ 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 } |
{ 14 : , 5 , 5 , 5 , 5 , 5 , 5 , Lorem ipsum dolor s } |
x = 4 |
{ 1 : ~ } |
{ 1 : ~ } |
|
] ] )
end )
2018-03-24 14:26:20 +01:00
end )
2018-10-23 10:10:23 +02:00
2018-12-07 17:28:51 +01:00
it ( ' and virtual text use the same namespace counter ' , function ( )
local set_virtual_text = curbufmeths.set_virtual_text
eq ( 1 , add_highlight ( 0 , " String " , 0 , 0 , - 1 ) )
eq ( 2 , set_virtual_text ( 0 , 0 , { { " = text " , " Comment " } } , { } ) )
eq ( 3 , meths.create_namespace ( " my-ns " ) )
eq ( 4 , add_highlight ( 0 , " String " , 0 , 0 , - 1 ) )
eq ( 5 , set_virtual_text ( 0 , 0 , { { " = text " , " Comment " } } , { } ) )
eq ( 6 , meths.create_namespace ( " other-ns " ) )
end )
2015-03-20 13:58:42 +01:00
end )