TransWikia.com

Can I make an entire listing a hyperlink rather than just the code?

TeX - LaTeX Asked on February 27, 2021

Using the method explained in https://tex.stackexchange.com/a/213413/218142 I can click on the code in a listings environment defined with lstnewenvironment. Students cut and paste their code from GlowScript.org into the newglowscriptblock environment, provide a caption and a URL so that when I click on the code I’m taken to their program so I can run it. I could probably leave things as they are, but is there a way to encapsulate this into a suitably defined environment? In other words, is there a way to include the use of the box within the environment definition or to define a new environment that make this all just work as simply as cutting and pasting the code into the environment? (I have a style defined with lstdefinestyle but I didn’t include it here.) I would also like to be able to click anywhere on the figure and not just on the actual code. Can that be accommodated too?

Here’s my MWE and its output.

documentclass{article}
usepackage{listings}
lstnewenvironment{newglowscriptblock}[3]{%
  lstset{caption={#1},label={#2}}}{}
usepackage{hyperref}
hypersetup{pdfborder=0 0 0}
begin{document}

% See https://tex.stackexchange.com/a/213413/218142
newsaveboxlstA
begin{lrbox}{lstA}
begin{newglowscriptblock}{Problem 37 Code}{pref2}{}
GlowScript 3.0 VPython

# a Young's modulus problem

Lo = 3   # wire's original length in m
d = 3e-3 # wire's diameter in m
g = 9.8  # surface grav. field strength in N/kg
m = 10   # ball's mass in kg
Y = 2e11 # steel's Young's modulus in N/m^2
# Find DeltaL, the amount the wire stretches.

area = (pi*d**2)/4
Force = m*g
DeltaL = (Force*Lo)/(area*Y)

print ("The wire stretches by ",DeltaL," m")
end{newglowscriptblock}
end{lrbox}
% The URL here is would the #3 in the definition of newglowscriptenvironment
href{https://google.com}{usebox{lstA}}

end{document}

Output code listing

2 Answers

This might do the trick - but - no warranties! ;-)

documentclass{article}

usepackage{listings}
usepackage[colorlinks=true]{hyperref}
%usepackage[colorlinks=false]{hyperref}

makeatletter
newsaveboxnewglowscriptblockTempBox
newcommandnewglowscriptblockURL{}%
newcommandnewglowscriptblockWrapInPartopsep[1]{%
   vskippartopsep#1vskippartopsep
}%
lstnewenvironment{newglowscriptblock}[3]{%
  gdefnewglowscriptblockURL{#3}%
  setboxnewglowscriptblockTempBoxhbox{begingroupaftergroup}%
  lstset{caption={#1},label={#2}}%
}{%
  endgroup
  hypersetup{hidelinks}%
  ifvmodeendgrafexpandafternewglowscriptblockWrapInPartopsepelseendgrafexpandafter@firstofonefi
  {%
    vskiptopsep
    noindent
    expandafterhrefexpandafter{newglowscriptblockURL}{usebox{newglowscriptblockTempBox}}%
    endgraf
    vskiptopsep
  }%
}%
% Make sure hyperref's href gets its argument "normalized
@ifdefinablenewglowscriptblock@@{%
  letnewglowscriptblock@@=newglowscriptblock@
  renewcommandnewglowscriptblock@[2]{hyper@normalise{newglowscriptblock@@unexpanded{{#1}{#2}}}}%
}%
makeatother


begin{document}

lstlistoflistings

newpage

Some text. Some text.
Some text. Some text.
begin{newglowscriptblock}{Problem 37 Code}{pref2}{https://google.com}
GlowScript 3.0 VPython

# a Young's modulus problem

Lo = 3   # wire's original length in m
d = 3e-3 # wire's diameter in m
g = 9.8  # surface grav. field strength in N/kg
m = 10   # ball's mass in kg
Y = 2e11 # steel's Young's modulus in N/m^2
# Find DeltaL, the amount the wire stretches.

area = (pi*d**2)/4
Force = m*g
DeltaL = (Force*Lo)/(area*Y)

print ("The wire stretches by ",DeltaL," m")
end{newglowscriptblock}
Some text. Some text.
Some text. Some text.

newpage

nameref-link to listing: nameref{pref2}

ref-link to listing: ref{pref2}

pageref-link to listing: pageref{pref2}

autoref-link to listing: autoref{pref2}

end{document}

Addendum in October 21, 2020

In a comment from October 20, 2020 you asked:

If I don't want to supply a URL, is there a way to suppress hyperref's warning about an empty target OR can I supply something that won't make the code highlight if I click it with the mouse?

The pdf-viewer used by me doesn't highlight things when clicking with the mouse. I assume the highlighting is not due to the pdf-file but is a feature "hardwired" in your pdf-viewing program.

If you don't mind changing the order of the arguments of the environment so that the argument holding the URL will not be the third one but will be the first one, you can make that argument optional, with an empty default.

You need to do some trickery to have the URL-argument normalized for hyperref. Otherwise you cannot have characters like # within the URL.

Then you can add forking to check whether the expansion of the macro newglowscriptblockURL defined from the URL-argument yields "blankness", i.e., emptiness or explicit space tokens only, and apply href only if this is not the case. This way if the now optional URL-argument is not provided or is provided empty, attempts at creating a hyperlink will not take place:

documentclass{article}

usepackage{listings}
usepackage[colorlinks=true]{hyperref}
%usepackage[colorlinks=false]{hyperref}

makeatletter

% Infrastructure for "hyperref-normalizing" an optional argument of a lstnewenvironment:
begingroup
catcode`^^A=14 %
catcode`^^Mactive^^A
catcode`%active^^A
@ifdefinablehyper@@normaliseoptarg{^^A
  gdefhyper@@normaliseoptarg#1#2#3]{^^A
    edefHy@tempa{^^A
      endgroupnoexpand#1[{Hy@RemovePercentCr#3%^^M@nil}]^^A
    }^^A
    Hy@tempa^^A
  }^^A
}^^A
endgroup
newcommandMY@exchange[2]{#2#1}%
expandafternewcommandexpandafter*expandafterhyper@normaliseoptargexpandafter{%
  romannumeral0%
  expandafterMY@exchangeexpandafter{hyper@normalise}{%
    @firstofone{expandafter} %
    MY@exchange{lethyper@@normalise=hyper@@normaliseoptarg}%
  }%
}%
newcommandlstenv@testhyper@normalizeopt[2]{%
  @ifnextchar[{catcode active 5relaxhyper@normaliseoptarg{lstenv@testoptnoexpand#1{#2}}}%
               {hyper@normaliseoptarg{#1}[{#2}]}%
}%
% end of Infrastructure for "hyperref-normalizing" an optional argument of a lstnewenvironment.


newsaveboxnewglowscriptblockTempBox
newcommandnewglowscriptblockURL{}%
newcommandnewglowscriptblockWrapInPartopsep[1]{%
   vskippartopsep#1vskippartopsep
}%
lstnewenvironment{newglowscriptblock}[3][]{%
  gdefnewglowscriptblockURL{#1}%
  setboxnewglowscriptblockTempBoxhbox{begingroupaftergroup}%
  lstset{caption={#2},label={#3}}%
}{%
  endgroup
  ifxnewglowscriptblockURLemptyelsehypersetup{hidelinks}fi
  ifvmodeendgrafexpandafternewglowscriptblockWrapInPartopsepelseendgrafexpandafter@firstofonefi
  {%
    vskiptopsep
    noindent
    ifcat $detokenizeexpandafterexpandafterexpandafter{expandafter@firstoftwonewglowscriptblockURL{}.}$%
    expandafter@firstoftwoelseexpandafter@secondoftwofi
    {@firstofone}%
    {expandafterhrefexpandafter{newglowscriptblockURL}}%
    {usebox{newglowscriptblockTempBox}}%
    endgraf
    vskiptopsep
  }%
}%
% Make sure hyperref's href gets its argument "hyperref-normalized" by replacing
% lstenv@testopt with lstenv@testhyper@normalizeopt
% in the definition of newglowscriptblock@.
expandafterrenewcommandexpandafter*expandafternewglowscriptblock@expandafter{%
  romannumeral0%
  expandafterMY@exchangeexpandafter{%
    csnamestringnewglowscriptblock@endcsname{}%<-the default for the opt arg is between these braces. The default is empty.
  }{ %
    ifxprotect@typeset@protect
      expandafterlstenv@testhyper@normalizeopt
    else
      @x@protectnewglowscriptblock@ 
    fi
  }%
}%
makeatother

begin{document}

lstlistoflistings

newpage

Some text. Some text.
Some text. Some text.
The optional argument is not empty, thus the environment is a hyperlink. %
begin{newglowscriptblock}[https://google.com#Weird]{Problem 37 Code}{pref2}
GlowScript 3.0 VPython

# a Young's modulus problem

Lo = 3   # wire's original length in m
d = 3e-3 # wire's diameter in m
g = 9.8  # surface grav. field strength in N/kg
m = 10   # ball's mass in kg
Y = 2e11 # steel's Young's modulus in N/m^2
# Find DeltaL, the amount the wire stretches.

area = (pi*d**2)/4
Force = m*g
DeltaL = (Force*Lo)/(area*Y)

print ("The wire stretches by ",DeltaL," m")
end{newglowscriptblock}
The optional argument is not empty, thus the environment is a hyperlink.
Some text. Some text.
Some text. Some text.

newpage

Some text. Some text.
Some text. Some text.
The optional argument is empty, thus the environment is not a hyperlink.
begin{newglowscriptblock}{Problem 37 Code}{pref3}
GlowScript 3.0 VPython

# a Young's modulus problem

Lo = 3   # wire's original length in m
d = 3e-3 # wire's diameter in m
g = 9.8  # surface grav. field strength in N/kg
m = 10   # ball's mass in kg
Y = 2e11 # steel's Young's modulus in N/m^2
# Find DeltaL, the amount the wire stretches.

area = (pi*d**2)/4
Force = m*g
DeltaL = (Force*Lo)/(area*Y)

print ("The wire stretches by ",DeltaL," m")
end{newglowscriptblock}
The optional argument is empty, thus the environment is not a hyperlink.
Some text. Some text.
Some text. Some text.

newpage

nameref-link to listing pref2: nameref{pref2}

ref-link to listing pref2: ref{pref2}

pageref-link to listing pref2: pageref{pref2}

autoref-link to listing pref2: autoref{pref2}

nameref-link to listing pref3: nameref{pref3}

ref-link to listing pref3: ref{pref3}

pageref-link to listing pref3: pageref{pref3}

autoref-link to listing pref3: autoref{pref3}

end{document}

Correct answer by Ulrich Diez on February 27, 2021

For reference, I include this answer. I discovered that tcolorbox can do this quite simply in one command. The entire interior of the box is clickable (it doesn't work of course in the screenshot below but it will work in your document) and the URL can be set as an optional parameter to the new command.

% !TEX program = lualatexmk
% !TEX encoding = UTF-8 Unicode

documentclass{article}
usepackage[left=1.00in,right=1.00in]{geometry}
usepackage[most]{tcolorbox} % loads the listings library
usepackage{hyperref}
hypersetup{colorlinks=true}

definecolor{gsbggray}     {rgb}{0.90,0.90,0.90} % background gray
definecolor{gsgray}       {rgb}{0.30,0.30,0.30} % gray
definecolor{gsgreen}      {rgb}{0.00,0.60,0.00} % green
definecolor{gsorange}     {rgb}{0.80,0.45,0.12} % orange
definecolor{gspeach}      {rgb}{1.00,0.90,0.71} % peach
definecolor{gspearl}      {rgb}{0.94,0.92,0.84} % pearl
definecolor{gsplum}       {rgb}{0.74,0.46,0.70} % plum
lstdefinestyle{vpython}{%                       % style for listings
  backgroundcolor=color{gsbggray},%             % background color
  basicstyle=footnotesize,%                     % default style
  breakatwhitespace=true%                        % break at whitespace
  breaklines=true,%                              % break long lines
  captionpos=b,%                                 % position caption
  classoffset=1,%                                % STILL DON'T UNDERSTAND THIS
  commentstyle=color{gsgray},%                  % font for comments
  deletekeywords={print},%                       % delete keywords from the given language
  emph={self,cls,@classmethod,@property},%       % words to emphasize
  emphstyle=color{gsorange}itshape,%           % font for emphasis
  escapeinside={(*@}{@*)},%                      % add LaTeX within your code
  frame=tb,%                                     % frame style
  framerule=2.0pt,%                              % frame thickness
  framexleftmargin=5pt,%                         % extra frame left margin
  %identifierstyle=sffamily,%                    % style for identifiers
  keywordstyle=sffamilycolor{gsplum},%         % color for keywords
  language=Python,%                              % select language
  linewidth=linewidth,%                         % width of listings
  morekeywords={%                                % VPython/GlowScript specific keywords
    __future__,abs,acos,align,ambient,angle,append,append_to_caption,%
    append_to_title,arange,arrow,asin,astuple,atan,atan2,attach_arrow,%
    attach_trail,autoscale,axis,background,billboard,bind,black,blue,border,%
    bounding_box,box,bumpaxis,bumpmap,bumpmaps,camera,canvas,caption,capture,%
    ceil,center,clear,clear_trail,click,clone,CoffeeScript,coils,color,combin,%
    comp,compound,cone,convex,cos,cross,curve,cyan,cylinder,data,degrees,del,%
    delete,depth,descender,diff_angle,digits,division,dot,draw_complete,%
    ellipsoid,emissive,end_face_color,equals,explog,extrusion,faces,factorial,%
    False,floor,follow,font,format,forward,fov,frame,gcurve,gdisplay,gdots,%
    get_library,get_selected,ghbars,global,GlowScript,graph,graphs,green,gvbars,%
    hat,headlength,headwidth,height,helix,hsv_to_rgb,index,interval,keydown,%
    keyup,label,length,lights,line,linecolor,linewidth,logx,logy,lower_left,%
    lower_right,mag,mag2,magenta,make_trail,marker_color,markers,material,%
    max,min,mouse,mousedown,mousemove,mouseup,newball,norm,normal,objects,%
    offset,one,opacity,orange,origin,path,pause,pi,pixel_to_world,pixels,plot,%
    points,pos,pow,pps,print,print_function,print_options,proj,purple,pyramid,%
    quad,radians,radius,random,rate,ray,read_local_file,readonly,red,redraw,%
    retain,rgb_to_hsv,ring,rotate,round,scene,scroll,shaftwidth,shape,shapes,%
    shininess,show_end_face,show_start_face,sign,sin,size,size_units,sleep,%
    smooth,space,sphere,sqrt,start,start_face_color,stop,tan,text,textpos,%
    texture,textures,thickness,title,trail_color,trail_object,trail_radius,%
    trail_type,triangle,trigger,True,twist,unbind,up,upper_left,upper_right,%
    userpan,userspin,userzoom,vec,vector,vertex,vertical_spacing,visible,%
    visual,vpython,VPython,waitfor,white,width,world,xtitle,yellow,yoffset,%
    ytitle%
  },%
  morekeywords={print,None,TypeError},%          % additional keywords
  morestring=[b]{"""},%                          % treat triple quotes as strings
  numbers=left,%                                 % where to put line numbers
  numbersep=10pt,%                               % how far line numbers are from code
  numberstyle=bfseriestiny,%                   % set to 'none' for no line numbers
  showstringspaces=false,%                       % show spaces in strings
  showtabs=false,%                               % show tabs within strings
  stringstyle=color{gsgreen},%                  % color for strings
  upquote=true,%                                 % how to typeset quotes
}%

NewTCBListing[auto counter,list inside=gsprogs]{tcbglowscriptblock}{ O{} D(){glowscript.org} m }{%
  breakable,%
  center,%
  code = newpage,%
  %derivpeach,%
  enhanced,%
  hyperurl interior = https://#2,%
  label = {gs:thetcbcounter},%
  left = 8mm,%
  list entry = texttt{GlowScript} Program thetcbcounter:  #3,%
  listing only,%
  listing style = vpython,%
  nameref = #3,%
  title = texttt{GlowScript} Program thetcbcounter:  #3,%
  width = 0.9textwidth,%
  #1,
}%

begin{document}

begin{tcbglowscriptblock}(google.com){A short texttt{GlowScript} Program}
GlowScript 3.0 vpython

scene.width = 400
scene.height = 760
# constants and data
g = 9.8       # m/s^2
mball = 0.03  # kg
Lo = 0.26     # m
ks = 1.8      # N/m
deltat = 0.01 # s

# objects (origin is at ceiling)
ceiling = box(pos=vector(0,0,0), length=0.2, height=0.01, 
              width=0.2)
ball = sphere(pos=vector(0,-0.3,0),radius=0.025,
              color=color.orange)
spring = helix(pos=ceiling.pos, axis=ball.pos-ceiling.pos,
               color=color.cyan,thickness=0.003,coils=40,
               radius=0.010)

# initial values
pball = mball * vector(0,0,0)      # kg m/s
Fgrav = mball * g * vector(0,-1,0) # N
t = 0

# improve the display
scene.autoscale = False        # turn off automatic camera zoom
scene.center = vector(0,-Lo,0) # move camera down
scene.waitfor('click')         # wait for a mouse click

# initial calculation loop
# calculation loop
while t < 10:
    rate(100)
    # we need the stretch
    s = mag(ball.pos) - Lo
    # we need the spring force
    Fspring = ks * s * -norm(spring.axis)
    Fnet = Fgrav + Fspring
    pball = pball + Fnet * deltat
    ball.pos = ball.pos + (pball / mball) * deltat
    spring.axis = ball.pos - ceiling.pos
    t = t + deltat
end{tcbglowscriptblock}

The program ref{gs:1} is nice. It's called nameref{gs:1} on page pageref{gs:1}.

end{document}

MWE Output

Answered by LaTeXereXeTaL on February 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP