#!/bin/sh # # This program launch a web browser on the html page # describing a git command. # # Copyright (c) 2007 Christian Couder # Copyright (c) 2006 Theodore Y. Ts'o # # This file is heavily stolen from git-mergetool.sh, by # Theodore Y. Ts'o (thanks) that is: # # Copyright (c) 2006 Theodore Y. Ts'o # # This file is licensed under the GPL v2, or a later version # at the discretion of Junio C Hamano or any other official # git maintainer. # global USAGE := ''[--browser=browser|--tool=browser] [--config=conf.var] url/file ...'' # This must be capable of running outside of git directory, so # the vanilla git-sh-setup should not be used. global NONGIT_OK := 'Yes' source git-sh-setup proc valid_custom_tool { global browser_cmd := $[git config "browser.$1.cmd] test -n $browser_cmd } proc valid_tool { matchstr $1 { firefox | iceweasel | seamonkey | iceape | \ chrome | google-chrome | chromium | chromium-browser | \ konqueror | opera | w3m | elinks | links | lynx | dillo | open | \ start | cygstart | xdg-open { } # happy * { valid_custom_tool $1 || return 1 } } } proc init_browser_path { global browser_path := $[git config "browser.$1.path] if test -z $browser_path && test $1 = chromium && type chromium-browser >/dev/null !2 > !1 { global browser_path := 'chromium-browser' } : $(browser_path:="$1") } while test $# != 0 { matchstr $1 { -b|--browser*|-t|--tool* { matchstr "$Argc,$1" { *,*=* { global browser := $[expr "z$1" : 'z-[^=]*=\(.*\)] } 1,* { usage } * { global browser := $2 shift } } } -c|--config* { matchstr "$Argc,$1" { *,*=* { global conf := $[expr "z$1" : 'z-[^=]*=\(.*\)] } 1,* { usage } * { global conf := $2 shift } } } -- { break } -* { usage } * { break } } shift } test $Argc = 0 && usage if test -z $browser { for opt in [$conf "web.browser]" { test -z $opt && continue global browser := $[git config $opt] test -z $browser || break } if test -n $browser && ! valid_tool $browser { echo >&2 "git config option $opt set to unknown browser: $browser> !2 "git config option $opt set to unknown browser: $browser" echo >&2 "Resetting to default...> !2 "Resetting to default..." unset browser } } if test -z $browser { if test -n $DISPLAY { global browser_candidates := '"firefox iceweasel google-chrome chrome chromium chromium-browser konqueror opera seamonkey iceape w3m elinks links lynx dillo xdg-open'" if test $KDE_FULL_SESSION = "true" { global browser_candidates := ""konqueror $browser_candidates"" } } else { global browser_candidates := '"w3m elinks links lynx'" } # SECURITYSESSIONID indicates an OS X GUI login session if test -n $SECURITYSESSIONID || test -n $TERM_PROGRAM { global browser_candidates := ""open $browser_candidates"" } # /bin/start indicates MinGW if test -x /bin/start { global browser_candidates := ""start $browser_candidates"" } # /usr/bin/cygstart indicates Cygwin if test -x /usr/bin/cygstart { global browser_candidates := ""cygstart $browser_candidates"" } for i in [$browser_candidates] { init_browser_path $i if type $browser_path > /dev/null !2 > !1 { global browser := $i break } } test -z $browser && die "No known browser available." } else { valid_tool $browser || die "Unknown browser '$browser'." init_browser_path $browser if test -z $browser_cmd && ! type $browser_path > /dev/null !2 > !1 { die "The browser $browser is not available as '$browser_path'." } } matchstr $browser { firefox|iceweasel|seamonkey|iceape { # Check version because firefox < 2.0 does not support "-new-tab". global vers := $[expr $[$browser_path -version] : '.* \([0-9][0-9]*\)\..*] global NEWTAB := ''-new-tab'' test $vers -lt 2 && global NEWTAB := '''' $browser_path $NEWTAB @Argv & } google-chrome|chrome|chromium|chromium-browser { # No need to specify newTab. It's default in chromium $browser_path @Argv & } konqueror { matchstr $[basename $browser_path] { konqueror { # It's simpler to use kfmclient to open a new tab in konqueror. global browser_path := $[echo $browser_path | sed -e 's/konqueror$/kfmclient/] type $browser_path > /dev/null !2 > !1 || die "No '$browser_path' found." $browser_path newTab @Argv & } kfmclient { $browser_path newTab @Argv & } * { $browser_path @Argv & } } } w3m|elinks|links|lynx|open|cygstart|xdg-open { $browser_path @Argv } start { exec $browser_path '"web-browse"' @Argv } opera|dillo { $browser_path @Argv & } * { if test -n $browser_cmd { shell { eval "$browser_cmd \"\$@\"" } } } } (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:USAGE) op: Equal rhs: {(SQ <"[--browser=browser|--tool=browser] [--config=conf.var] url/file ...">)} spids: [52] ) ] spids: [52] ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:NONGIT_OK) op:Equal rhs:{(Yes)} spids:[64])] spids: [64] ) (C {(.)} {(git-sh-setup)}) (FuncDef name: valid_custom_tool body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser_cmd) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (C {(git)} {(config)} {(DQ (browser.) ($ VSub_Number "$1") (.cmd))}) ] ) left_token: spids: [81 91] ) ) } spids: [79] ) ] spids: [79] ) (C {(test)} {(-n)} {(DQ ($ VSub_Name "$browser_cmd"))}) ] spids: [76] ) spids: [72 75] ) (FuncDef name: valid_tool body: (BraceGroup children: [ (Case to_match: {(DQ ($ VSub_Number "$1"))} arms: [ (case_arm pat_list: [ {(firefox)} {(iceweasel)} {(seamonkey)} {(iceape)} {(chrome)} {(google-chrome)} {(chromium)} {(chromium-browser)} {(konqueror)} {(opera)} {(w3m)} {(elinks)} {(links)} {(lynx)} {(dillo)} {(open)} {(start)} {(cygstart)} {(xdg-open)} ] spids: [122 201 204 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (AndOr children: [ (C {(valid_custom_tool)} {(DQ ($ VSub_Number "$1"))}) (ControlFlow token: arg_word: {(1)} ) ] op_id: Op_DPipe ) ] spids: [210 211 227 -1] ) ] spids: [113 119 230] ) ] spids: [110] ) spids: [106 109] ) (FuncDef name: init_browser_path body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser_path) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (C {(git)} {(config)} {(DQ (browser.) ($ VSub_Number "$1") (.path))}) ] ) left_token: spids: [243 253] ) } spids: [242] ) ] spids: [242] ) (If arms: [ (if_arm cond: [ (AndOr children: [ (C {(test)} {(-z)} {(DQ ($ VSub_Name "$browser_path"))}) (AndOr children: [ (C {(test)} {(DQ ($ VSub_Number "$1"))} {(Lit_Other "=")} {(chromium)}) (SimpleCommand words: [{(type)} {(chromium-browser)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(/dev/null)} spids: [286] ) (Redir op_id: Redir_GreatAnd fd: 2 arg_word: {(1)} spids: [289] ) ] ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser_path) op: Equal rhs: {(chromium-browser)} spids: [296] ) ] spids: [296] ) ] spids: [-1 293] ) ] spids: [-1 300] ) (C {(Lit_Other ":")} { (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonEquals arg_word:{(DQ ($ VSub_Number "$1"))}) spids: [305 311] ) } ) ] spids: [239] ) spids: [235 238] ) (While cond: [(C {(test)} {($ VSub_Pound "$#")} {(KW_Bang "!") (Lit_Other "=")} {(0)})] body: (DoGroup children: [ (Case to_match: {(DQ ($ VSub_Number "$1"))} arms: [ (case_arm pat_list: [{(-b)} {(--browser) (Lit_Other "*")} {(-t)} {(--tool) (Lit_Other "*")}] action: [ (Case to_match: {(DQ ($ VSub_Pound "$#") (",") ($ VSub_Number "$1"))} arms: [ (case_arm pat_list: [ {(Lit_Other "*") (Lit_Comma ",") (Lit_Other "*") (Lit_Other "=") (Lit_Other "*") } ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (C {(expr)} {(DQ (z) ($ VSub_Number "$1"))} {(Lit_Other ":")} {(SQ <"z-[^=]*=\\(.*\\)">)} ) ] ) left_token: spids: [371 384] ) } spids: [370] ) ] spids: [370] ) ] spids: [362 367 387 -1] ) (case_arm pat_list: [{(1) (Lit_Comma ",") (Lit_Other "*")}] action: [(C {(usage)})] spids: [390 393 398 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser) op: Equal rhs: {(DQ ($ VSub_Number "$2"))} spids: [405] ) ] spids: [405] ) (C {(shift)}) ] spids: [401 402 413 -1] ) ] spids: [351 359 416] ) ] spids: [339 348 419 -1] ) (case_arm pat_list: [{(-c)} {(--config) (Lit_Other "*")}] action: [ (Case to_match: {(DQ ($ VSub_Pound "$#") (",") ($ VSub_Number "$1"))} arms: [ (case_arm pat_list: [ {(Lit_Other "*") (Lit_Comma ",") (Lit_Other "*") (Lit_Other "=") (Lit_Other "*") } ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:conf) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (C {(expr)} {(DQ (z) ($ VSub_Number "$1"))} {(Lit_Other ":")} {(SQ <"z-[^=]*=\\(.*\\)">)} ) ] ) left_token: spids: [449 462] ) } spids: [448] ) ] spids: [448] ) ] spids: [440 445 465 -1] ) (case_arm pat_list: [{(1) (Lit_Comma ",") (Lit_Other "*")}] action: [(C {(usage)})] spids: [468 471 476 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:conf) op: Equal rhs: {(DQ ($ VSub_Number "$2"))} spids: [483] ) ] spids: [483] ) (C {(shift)}) ] spids: [479 480 491 -1] ) ] spids: [429 437 494] ) ] spids: [422 426 497 -1] ) (case_arm pat_list: [{(--)}] action: [(ControlFlow token:)] spids: [500 501 507 -1] ) (case_arm pat_list: [{(-) (Lit_Other "*")}] action: [(C {(usage)})] spids: [510 512 518 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [(ControlFlow token:)] spids: [521 522 528 -1] ) ] spids: [330 336 531] ) (C {(shift)}) ] spids: [327 536] ) ) (AndOr children: [(C {(test)} {($ VSub_Pound "$#")} {(Lit_Other "=")} {(0)}) (C {(usage)})] op_id: Op_DAmp ) (If arms: [ (if_arm cond: [(C {(test)} {(-z)} {(DQ ($ VSub_Name "$browser"))})] action: [ (ForEach iter_name: opt iter_words: [{(DQ ($ VSub_Name "$conf"))} {(DQ (web.browser))}] do_arg_iter: False body: (DoGroup children: [ (AndOr children: [ (C {(test)} {(-z)} {(DQ ($ VSub_Name "$opt"))}) (ControlFlow token:) ] op_id: Op_DAmp ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [(C {(git)} {(config)} {($ VSub_Name "$opt")})] ) left_token: spids: [598 604] ) ) } spids: [596] ) ] spids: [596] ) (AndOr children: [ (C {(test)} {(-z)} {(DQ ($ VSub_Name "$browser"))}) (ControlFlow token:) ] op_id: Op_DPipe ) ] spids: [580 621] ) spids: [570 -1] ) (If arms: [ (if_arm cond: [ (Sentence child: (AndOr children: [ (C {(test)} {(-n)} {(DQ ($ VSub_Name "$browser"))}) (Pipeline children: [(C {(valid_tool)} {(DQ ($ VSub_Name "$browser"))})] negated: True ) ] op_id: Op_DAmp ) terminator: ) ] action: [ (SimpleCommand words: [ {(echo)} { (DQ ("git config option ") ($ VSub_Name "$opt") (" set to unknown browser: ") ($ VSub_Name "$browser") ) } ] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[650])] ) (SimpleCommand words: [{(echo)} {(DQ ("Resetting to default..."))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[663])] ) (C {(unset)} {(browser)}) ] spids: [-1 645] ) ] spids: [-1 676] ) ] spids: [-1 562] ) ] spids: [-1 678] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(test)} {(-z)} {(DQ ($ VSub_Name "$browser"))}) terminator: ) ] action: [ (If arms: [ (if_arm cond: [ (Sentence child: (C {(test)} {(-n)} {(DQ ($ VSub_Name "$DISPLAY"))}) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser_candidates) op: Equal rhs: { (DQ ( "firefox iceweasel google-chrome chrome chromium chromium-browser konqueror opera seamonkey iceape w3m elinks links lynx dillo xdg-open" ) ) } spids: [710] ) ] spids: [710] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(test)} {(DQ ($ VSub_Name "$KDE_FULL_SESSION"))} {(Lit_Other "=")} {(DQ (true))} ) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser_candidates) op: Equal rhs: {(DQ ("konqueror ") ($ VSub_Name "$browser_candidates"))} spids: [734] ) ] spids: [734] ) ] spids: [-1 731] ) ] spids: [-1 741] ) ] spids: [-1 707] ) ] else_action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser_candidates) op: Equal rhs: {(DQ ("w3m elinks links lynx"))} spids: [747] ) ] spids: [747] ) ] spids: [744 753] ) (If arms: [ (if_arm cond: [ (AndOr children: [ (C {(test)} {(-n)} {(DQ ($ VSub_Name "$SECURITYSESSIONID"))}) (C {(test)} {(-n)} {(DQ ($ VSub_Name "$TERM_PROGRAM"))}) ] op_id: Op_DPipe ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser_candidates) op: Equal rhs: {(DQ ("open ") ($ VSub_Name "$browser_candidates"))} spids: [784] ) ] spids: [784] ) ] spids: [-1 781] ) ] spids: [-1 791] ) (If arms: [ (if_arm cond: [(Sentence child:(C {(test)} {(-x)} {(/bin/start)}) terminator:)] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser_candidates) op: Equal rhs: {(DQ ("start ") ($ VSub_Name "$browser_candidates"))} spids: [810] ) ] spids: [810] ) ] spids: [-1 807] ) ] spids: [-1 817] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(test)} {(-x)} {(/usr/bin/cygstart)}) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser_candidates) op: Equal rhs: {(DQ ("cygstart ") ($ VSub_Name "$browser_candidates"))} spids: [836] ) ] spids: [836] ) ] spids: [-1 833] ) ] spids: [-1 843] ) (ForEach iter_name: i iter_words: [{($ VSub_Name "$browser_candidates")}] do_arg_iter: False body: (DoGroup children: [ (C {(init_browser_path)} {($ VSub_Name "$i")}) (If arms: [ (if_arm cond: [ (Sentence child: (SimpleCommand words: [{(type)} {(DQ ($ VSub_Name "$browser_path"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(/dev/null)} spids: [872] ) (Redir op_id: Redir_GreatAnd fd: 2 arg_word: {(1)} spids: [876] ) ] ) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser) op: Equal rhs: {($ VSub_Name "$i")} spids: [883] ) ] spids: [883] ) (ControlFlow token:) ] spids: [-1 880] ) ] spids: [-1 890] ) ] spids: [856 893] ) spids: [852 854] ) (AndOr children: [ (C {(test)} {(-z)} {(DQ ($ VSub_Name "$browser"))}) (C {(die)} {(DQ ("No known browser available."))}) ] op_id: Op_DAmp ) ] spids: [-1 693] ) ] else_action: [ (AndOr children: [ (C {(valid_tool)} {(DQ ($ VSub_Name "$browser"))}) (C {(die)} {(DQ ("Unknown browser '") ($ VSub_Name "$browser") ("'."))}) ] op_id: Op_DPipe ) (C {(init_browser_path)} {(DQ ($ VSub_Name "$browser"))}) (If arms: [ (if_arm cond: [ (Sentence child: (AndOr children: [ (C {(test)} {(-z)} {(DQ ($ VSub_Name "$browser_cmd"))}) (Pipeline children: [ (SimpleCommand words: [{(type)} {(DQ ($ VSub_Name "$browser_path"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(/dev/null)} spids: [961] ) (Redir op_id: Redir_GreatAnd fd: 2 arg_word: {(1)} spids: [965] ) ] ) ] negated: True ) ] op_id: Op_DAmp ) terminator: ) ] action: [ (C {(die)} { (DQ ("The browser ") ($ VSub_Name "$browser") (" is not available as '") ($ VSub_Name "$browser_path") ("'.") ) } ) ] spids: [-1 969] ) ] spids: [-1 983] ) ] spids: [912 985] ) (Case to_match: {(DQ ($ VSub_Name "$browser"))} arms: [ (case_arm pat_list: [{(firefox)} {(iceweasel)} {(seamonkey)} {(iceape)}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:vers) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (C {(expr)} { (DQ (CommandSubPart command_list: (CommandList children: [(C {($ VSub_Name "$browser_path")} {(-version)})] ) left_token: spids: [1015 1019] ) ) } {(Lit_Other ":")} {(SQ <".* \\([0-9][0-9]*\\)\\..*">)} ) ] ) left_token: spids: [1011 1027] ) } spids: [1010] ) ] spids: [1010] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:NEWTAB) op: Equal rhs: {(SQ <-new-tab>)} spids: [1030] ) ] spids: [1030] ) (AndOr children: [ (C {(test)} {(DQ ($ VSub_Name "$vers"))} {(-lt)} {(2)}) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:NEWTAB) op:Equal rhs:{(SQ )} spids:[1048])] spids: [1048] ) ] op_id: Op_DAmp ) (Sentence child: (C {(DQ ($ VSub_Name "$browser_path"))} {($ VSub_Name "$NEWTAB")} {(DQ ($ VSub_At "$@"))}) terminator: ) ] spids: [996 1003 1066 -1] ) (case_arm pat_list: [{(google-chrome)} {(chrome)} {(chromium)} {(chromium-browser)}] action: [ (Sentence child: (C {(DQ ($ VSub_Name "$browser_path"))} {(DQ ($ VSub_At "$@"))}) terminator: ) ] spids: [1068 1075 1093 -1] ) (case_arm pat_list: [{(konqueror)}] action: [ (Case to_match: { (DQ (CommandSubPart command_list: (CommandList children: [(C {(basename)} {(DQ ($ VSub_Name "$browser_path"))})] ) left_token: spids: [1102 1108] ) ) } arms: [ (case_arm pat_list: [{(konqueror)}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:browser_path) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(echo)} {(DQ ($ VSub_Name "$browser_path"))}) (C {(sed)} {(-e)} {(SQ <"s/konqueror$/kfmclient/">)}) ] negated: False ) ] ) left_token: spids: [1124 1140] ) ) } spids: [1122] ) ] spids: [1122] ) (AndOr children: [ (SimpleCommand words: [{(type)} {(DQ ($ VSub_Name "$browser_path"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(/dev/null)} spids: [1150] ) (Redir op_id: Redir_GreatAnd fd: 2 arg_word: {(1)} spids: [1154] ) ] ) (C {(die)} {(DQ ("No '") ($ VSub_Name "$browser_path") ("' found."))}) ] op_id: Op_DPipe ) (Sentence child: (C {(DQ ($ VSub_Name "$browser_path"))} {(newTab)} {(DQ ($ VSub_At "$@"))}) terminator: ) ] spids: [1114 1115 1181 -1] ) (case_arm pat_list: [{(kfmclient)}] action: [ (Sentence child: (C {(DQ ($ VSub_Name "$browser_path"))} {(newTab)} {(DQ ($ VSub_At "$@"))}) terminator: ) ] spids: [1184 1185 1201 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (Sentence child: (C {(DQ ($ VSub_Name "$browser_path"))} {(DQ ($ VSub_At "$@"))}) terminator: ) ] spids: [1204 1205 1219 -1] ) ] spids: [1099 1111 1222] ) ] spids: [1095 1096 1225 -1] ) (case_arm pat_list: [{(w3m)} {(elinks)} {(links)} {(lynx)} {(open)} {(cygstart)} {(xdg-open)}] action: [(C {(DQ ($ VSub_Name "$browser_path"))} {(DQ ($ VSub_At "$@"))})] spids: [1227 1240 1252 -1] ) (case_arm pat_list: [{(start)}] action: [ (C {(exec)} {(DQ ($ VSub_Name "$browser_path"))} {(SQ <"\"web-browse\"">)} {(DQ ($ VSub_At "$@"))} ) ] spids: [1254 1255 1273 -1] ) (case_arm pat_list: [{(opera)} {(dillo)}] action: [ (Sentence child: (C {(DQ ($ VSub_Name "$browser_path"))} {(DQ ($ VSub_At "$@"))}) terminator: ) ] spids: [1275 1278 1292 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (If arms: [ (if_arm cond: [ (Sentence child: (C {(test)} {(-n)} {(DQ ($ VSub_Name "$browser_cmd"))}) terminator: ) ] action: [ (Subshell child: (C {(eval)} { (DQ ($ VSub_Name "$browser_cmd") (" ") (EscapedLiteralPart token: ) (EscapedLiteralPart token:) ("@") (EscapedLiteralPart token: ) ) } ) spids: [1312 1325] ) ] spids: [-1 1309] ) ] spids: [-1 1328] ) ] spids: [1294 1295 1331 -1] ) ] spids: [988 994 1333] ) ] )