[Home] [Downloads] [Search] [Help/forum]

Gammon Forum

See www.mushclient.com/spam for dealing with forum spam. Please read the MUSHclient FAQ!

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Plugins
. . -> [Subject]  New Hyperlink_URL2 version
Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?

New Hyperlink_URL2 version

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Pages: 1 2  

Posted by Sketch-The-Fox   (19 posts)  [Biography] bio
Date Sun 12 Dec 2010 05:49 PM (UTC)

Amended on Sun 12 Dec 2010 05:55 PM (UTC) by Sketch-The-Fox

Message
I wasn't aware people still used this plugin. I'm so flattered!

A few friends of mine were complaining about copy-pasting URLs, so I linked them to my plugin, written back in 2006. I got around to looking at the code and, somewhat horrified, began rewriting it. This is what came out. It's written for Lua 5.1, so it should work on MUSHclient versions 3.80 and higher. This version has much more modular code, and should be much more readable and maintainable. As well, the URL matching is now done regardless of colors or styles in the text. It also tries to pick up a few URL-look-alikes such as "awebsite.com", without getting too many false positives.

I'm sure there's a bug or two, and I'm sure improvements can be made, but I'm leaving it to the Lua and MUSHclient experts--I'm certainly not either.

(As a first bug I can't seem to figure out, this line wraps oddly:
think <Faker-> A big, crazy Pretender has actually, for instance, typed out websiteurl.com to tell people about it.
)

Hope you all enjoy it. :)

(Plugin follows this post)
[Go to top] top

Posted by Sketch-The-Fox   (19 posts)  [Biography] bio
Date Reply #1 on Sun 12 Dec 2010 05:50 PM (UTC)

Amended on Mon 16 May 2011 05:29 PM (UTC) by Sketch-The-Fox

Message

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<!-- Saved on Wednesday, 22 December 2010, 4:25 PM -->
<!-- MuClient version 4.61 -->
<muclient>
<plugin 
  name="Hyperlink_URL2" 
  author="Sketch" 
  id="520bc4f29806f7af0017985f" 
  language="Lua" 
  purpose="Changes URLs on a line into hyperlinks." 
  date_written="2006-04-01" 
  date_modified="2010-12-22"
  requires="4.42"
  version="3.1">

<description trim="y">
<![CDATA[
Detects URLs and turns them into hyperlinks.
]]>
</description>

</plugin>

<!--  Triggers  -->

<triggers>
  <trigger
    enabled="y"
    match="(?:https?://|mailto:)\S*[\w/=@#\-\?]"
    omit_from_output="y"
    ignore_case="y"
    regexp="y"
    script="onURL"
    sequence="100"
  >
  </trigger>
</triggers>

<!--  Script  -->
<script>
<![CDATA[
--[[
   -- What it is --
A URL hyperlinker for MUSHclient.

	-- Why it's needed --
We want to hyperlink all the URLs in a line, while preserving the original style and color of the line. However, due to how wildcard matching and triggers work, we can't make a trigger to match each URL on a line and hyperlink it.
What do we do?

	-- How it works --
MUSHclient provides the plaintext of the whole line to scripts called from triggers, as the argument "line". MUSHclient also provides an array called "styles" to Lua scripts called from triggers. The styles array contains a structure (or "dictionary") for each styled segment of the whole line the trigger matched. The structure is: {textcolour, backcolour, style, text, length} where textcolour and backcolour are the foreground/background color, style is a set of OR-ed flags bold=1, underline=2, blink=4, text is the text in that segment, and length is the length of the segment. It's worth noting that the 'styles' array is contiguous, and the segments it contains span the whole line. Even segments with no special styling are included, and each style begins immediately after the previous one ends.
Using these two arguments, we can compose a line with all URLs hyperlinked, while preserving colors and other formatting.

Short breakdown:
The script takes a matched trigger line and breaks it up in two different ways: An array of segments based on styling is made, and an array of segments based on URLs is made. Using those two arrays, the segments of the line are pieced back together, placing the styling on the hyperlinks.

Long breakdown: (function names in parentheses)
1) Trigger on a line that contains at least one URL-like item. The 'styles' array is passed into the script, as well as the plaintext line.

2) Find all the URLs in the plaintext line, number them, and record their start/end points and text. We now have an array of (to-be) hyperlinks numbered 1-N, with start/end positions for each.
(findURLs)

3) Merge the start and end points of all the styles and hyperlinks into a sorted set. We now have a list of all points where either or both occurs:
	* A style changes (even to/from 'no styling').
	* A hyperlink begins or ends.
(getpoints)

4) Convert the start and end points into 'slices' of the text line. Disregarding the text itself, each of these slices is homogenous: the style is the same through the whole slice, and the slice is either not part of any hyperlink, or is part of only one hyperlink.
(getslices)

5) Iterate over the slices, recording style/hyperlink number/text for each slice
	into an array named 'reformatted'.
(reformat)

6) Iterate over the 'reformatted' array. If the slice contains part of a hyperlink,
	print it as such. Although the slice may contain only part of a hyperlink, the
	whole URL was stored in the 'hyperlinks' array (in step 2), and can be looked
	up by the slice's stored hyperlink number.

You now have a line with detected URLs changed into hyperlinks, and the original styling preserved.
--]]

-- CODE SECTION --

-- Returns an array {start, end, text}
function findURLs(text)
	local URLs = {}
	local start, position = 0, 0
	-- "rex" is a table supplied by MUSHclient for PCRE functionality.
	local re = rex.new("(?:https?://|mailto:)\\S*[\\w/=@#\\-\\?]", rex.flags().CASELESS)
	re:gmatch(text,
		function (link, _)
			start, position = string.find(text, link, position, true)
			table.insert(URLs, {start=start, stop=position, text=link})
		end
	)
	return URLs
end -- function findURL

-- Returns a table of points where formatting should change in the new string.
function getpoints(styles, hyperlinks)
	local points = {}
	local unique_points = {}
	local pos = 1
	for _,v in pairs(styles) do
		table.insert(points, pos)
		table.insert(points, pos + v.length)
		pos = pos + v.length
	end
	-- The last value of points is now 1 past the end of the string.

	for _,v in pairs(hyperlinks) do
		table.insert(points, v.start)
		table.insert(points, v.stop + 1)
		-- The hyperlink itself is at v.stop. v.stop+1 is where the change is.
	end

	table.sort(points)
	return unique_array(points)
end -- function getpoints

-- Returns an array with consecutive duplicate items removed.
function unique_array(a)
	local uniq, current = {}, nil
	for _,v in pairs(a) do
		if v ~= current then
			table.insert(uniq, v)
			current = v
		end
	end
return uniq
end -- function unique_array

-- Given an array of numbers, return an array of pairs, to be used in string.sub().
-- Each pair starts at the original array's key, and ends before the next key.
-- Example: [1, 5, 9, 13] --> [{1,4},{5,8},{9,12}]
function getslices(points)
	local newpoints = {}
	for i = 1, #points - 1, 1 do
		table.insert(newpoints, {start=points[i], stop=points[i+1] - 1})
	end
	return newpoints
end -- function getslices

-- Returns an array of
-- {startpos, endpos, textcolour, backcolour, style, hyperlink_number}
function reformat(slices, styles, hyperlinks)
	local styles_i, hyperlinks_i = 1, 1
	local hyperlink_number = 0
	local reformatted = {}
	-- nextstyle is set at the character where the next style begins.
	local nextstyle = styles[1].length + 1

	-- Add a fake hyperlink past the end of the string at the end of the array.
	-- This way, we don't have to keep checking (hyperlinks_i > #hyperlinks).
	table.insert(hyperlinks,{start=slices[#slices].stop + 1,stop=slices[#slices].stop + 1,text=""})

	for _,v in pairs(slices) do

		-- v.start is our 'current position'.
		-- Make sure we're using the correct style
		if v.start >= nextstyle then
			nextstyle = v.start + styles[styles_i + 1].length
			styles_i = styles_i + 1
		end

		-- If we've passed the hyperlink marked by hyperlinks_i, increment it.
		if v.start > hyperlinks[hyperlinks_i].stop then
			hyperlinks_i = hyperlinks_i + 1
		end

		-- The hyperlink_number is set to the hyperlink we're checking for if
		-- we're at or past its starting position. (In other words, inside it)
		if v.start >= hyperlinks[hyperlinks_i].start then
			hyperlink_number = hyperlinks_i
		else
			hyperlink_number = 0
		end

		table.insert(reformatted,
			{startpoint = v.start
			,endpoint = v.stop
			,textcolour = styles[styles_i].textcolour
			,backcolour = styles[styles_i].backcolour
			,style = styles[styles_i].style
			,hyperlink_number = hyperlink_number}
		)
	end
	return reformatted
end -- function reformat

-- Line: Whole line that contains the trigger, in plaintext.
-- Styles: [{textcolour, backcolour, text, length, style},...]
function onURL (name, line, wildcards, styles)
	local hyperlinks = findURLs(line)
	local reformatted = reformat(getslices(getpoints(styles,hyperlinks)), styles, hyperlinks)

	for _,v in pairs(reformatted) do
		NoteStyle(v.style) -- Set style for the segment, regardless of type.
		if v.hyperlink_number ~= 0 then
			Hyperlink(
				hyperlinks[v.hyperlink_number].text -- Hyperlink
				,string.sub(line, v.startpoint, v.endpoint) -- Displayed text
				,"Go to " .. hyperlinks[v.hyperlink_number].text -- Hover text
				,RGBColourToName(v.textcolour) -- Foreground color
				,RGBColourToName(v.backcolour) -- Background color
				,1 -- Boolean: Open as a URL?
			)
		else
			ColourTell(
				RGBColourToName(v.textcolour) -- Foreground color
				,RGBColourToName(v.backcolour) -- Background color
				,string.sub(line, v.startpoint, v. endpoint) -- Displayed text
			)
		end
	end
	Note ("") -- Insert a newline at the end of the string.  
end -- function onURL
]]>
</script>
</muclient>


Edit: Works in 3.80 and above, but has color bleeding before version 4.42, so I changed the required version.

[EDIT] Amended 25 December 2010 to be version 3.1 as described below.
[EDIT] Edited 16 May 2011, to be case-insensitive.
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #2 on Sun 12 Dec 2010 08:57 PM (UTC)

Amended on Sun 12 Dec 2010 09:01 PM (UTC) by Nick Gammon

Message
I fixed up your forum codes, but after looking at it am not sure if I overdid it.

You should copy your original plugin to the clipboard, then inside MUSHclient do Edit menu -> Convert Clipboard Forum Codes. Then paste the result over the plugin, if I got it wrong.

[EDIT]

I think I got it wrong - I usually tell by checking the last few lines of the raw posting, it should look like:


\]\]>
</script>
</muclient>


rather than:


]]>
</script>
</muclient>


Without the backslashes in front of the square brackets, it looks like the forum codes haven't been fixed. But I am guessing you went through and manually changed some.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Sketch-The-Fox   (19 posts)  [Biography] bio
Date Reply #3 on Sun 12 Dec 2010 09:59 PM (UTC)
Message
Thanks for the direction, Nick. Should be all fixed now. :)
[Go to top] top

Posted by Sketch-The-Fox   (19 posts)  [Biography] bio
Date Reply #4 on Wed 22 Dec 2010 11:13 PM (UTC)
Message
I have a newer version to post, which only accepts URLs that start with http://, https://, and mailto:, and also has a documentation section. Should I edit the previous post, or post a reply?
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #5 on Fri 24 Dec 2010 12:41 AM (UTC)
Message
You may as well edit it, and put an [edit] tag under it to indicate that it changed on date X and why.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Sketch-The-Fox   (19 posts)  [Biography] bio
Date Reply #6 on Fri 24 Dec 2010 09:39 PM (UTC)
Message
It's too long to post! I've put the plugin on pastebin here: http://pastebin.com/X0TH7sgf and the forum-code escaped version here: http://pastebin.com/kw92Svfh

It should be in proper working order now. When you've got a bit of time to spare, Nick, could you edit the previous post, and put this version up on the plugins page? Thanks in advance! :)

Merry Christmas!
[Go to top] top

Posted by Sketch-The-Fox   (19 posts)  [Biography] bio
Date Reply #7 on Sun 02 Jan 2011 04:14 AM (UTC)

Amended on Sun 02 Jan 2011 04:47 AM (UTC) by Sketch-The-Fox

Message
Please don't forget to update the plugin on the plugins page! This is indeed a newer version of the Hyperlink_URL2 plugin.

Description:

Detects text starting with HTTP://xxx, HTTPS://xxx, or MAILTO://xxx, and makes that part of the line into a hyperlink.

This is an improved version of the Hyperlink_URL plugin. This one is written in Lua and preserves the colours in the original line.

Written by Sketch-The-Fox
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #8 on Sun 02 Jan 2011 05:00 AM (UTC)
Message
I've updated the plugins page. I've also removed the post length limit for you so you can update it in-situ on this thread if you want to.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Sketch-The-Fox   (19 posts)  [Biography] bio
Date Reply #9 on Sun 02 Jan 2011 02:27 PM (UTC)
Message
Thanks for both! I'm sure the posting ability will be useful.
It appears as though the old description wasn't removed from the plugins page. Is it possible to do that?
Sorry for the nitpicking. :)
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #10 on Sun 02 Jan 2011 09:31 PM (UTC)
Message
Done.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Sojik   USA  (8 posts)  [Biography] bio
Date Reply #11 on Sat 11 Jun 2011 01:44 PM (UTC)

Amended on Sat 11 Jun 2011 01:54 PM (UTC) by Sojik

Message
I'm getting underlined hyperlinks regardless of what setting I use in the MXP/Pueblo tab in MUSHClient v4.73. Am I the only one? I'm pretty sure this plugin doesn't change the style of hyperlinks.

EDIT: Nevermind. It's a bug with MUSHclient I believe because I made a hyperlink in a test and it underlined it.
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #12 on Sat 11 Jun 2011 10:51 PM (UTC)
Message
The Hyperlink function always underlines, judging by the code, regardless of MXP settings.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Worstje   Netherlands  (899 posts)  [Biography] bio
Date Reply #13 on Sun 22 Apr 2012 02:29 AM (UTC)

Amended on Sun 22 Apr 2012 02:33 AM (UTC) by Worstje

Message
I'm doing a slight derail after some thread necromancy, and I'll apologize right away to Sketch-The-Fox for that.

Nick Gammon said:

The Hyperlink function always underlines, judging by the code, regardless of MXP settings.


Is there any chance an extra flag could be added to the Hyperlink() function to disable the mandatory underline?

I am writing an alias for plugin settings, and for the colours I've added a colour swatch preview (spaces with the colour set as the background) + a hyperlink to modify this. But in practice, my users seem to try to click the colour shown rather than the Modify hyperlink next to it, leading to some confusion. But when I Hyperlink() rather than ColourTell() the colour swatch, there is this really ugly looking underline (in the standard Note colour?) below it, so I was hoping to be able to disable it for this case.

[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #14 on Wed 25 Apr 2012 03:10 AM (UTC)
Message
Template:function=Hyperlink Hyperlink

The documentation for the Hyperlink script function is available online. It is also in the MUSHclient help file.



Quote:

Lua notes

Lua has a 7th optional argument: NoUnderline.

If true, the hyperlink is not underlined. It defaults to false.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


17,359 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at FutureQuest]