Skip to content

Instantly share code, notes, and snippets.

@Tekl
Last active February 9, 2023 14:35
Show Gist options
  • Save Tekl/3d98fdeaa7e9324c8a4c4cf9ba887398 to your computer and use it in GitHub Desktop.
Save Tekl/3d98fdeaa7e9324c8a4c4cf9ba887398 to your computer and use it in GitHub Desktop.
Script for BBEdit (https://www.barebones.com/products/bbedit/) to surround lines with HTML tags or some sort of Markdown markup
--
-- Created by: Wolfgang Kreutz
-- Version 1.0 for BBEdit from 09.02.23
--
-- © 2023 Wolfgang Kreutz • https://tekl.de
--
-- This Script only works in the text and code editor BBEdit for macOS (https://www.barebones.com/products/bbedit/).
-- It surrounds every line in the selection with HTML tags or some sort of Markdown markup like links, lists and headlines.
-- If you enter a HTML tag with attributes, the script will remove them for the closing tag.
--
-- Installation: Open this script in Script Editor and save it as a compiled script (extension: .scpt).
-- Move the compiled script (not the .applescript file) into the folder
-- iCloud Drive/BBEdit/Documents/Application Support/Scripts/, which you easily can open from
-- the S-shaped script menu. Once there, this Script is automatically added to the menu. You can assign a
-- keyboard shortcut using the Scripts palette from BBEdit’s Window menu.
--
-- Get latest version from: https://gist.github.com/Tekl/3d98fdeaa7e9324c8a4c4cf9ba887398
-- There's also a version for CotEditor: https://gist.github.com/Tekl/54ef3a305346e2a5557bee3fb51c122c
--
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
-- Settings
property surroundEmptyLines : false
-- Variable declaration
property lineEnding : linefeed
property indentStr : ""
property beginSelection : ""
property endSelection : ""
on run
main()
end run
on menuselect()
main()
end menuselect
on main()
tell application "BBEdit" to if not (exists front document) then return
set defaultTagStr to do shell script "defaults read de.tekl.bbedit.surroundLinesWithTags tagString || echo '<ul>'"
set defaultButton to do shell script "defaults read de.tekl.bbedit.surroundLinesWithTags defaultButton || echo 'Surround Lines with Tags'"
try
set {theButton, tagStr} to (display dialog "Enter the HTML Tag that should surround the lines of the selection." & linefeed & linefeed & "Use <ol>/<ul> to create complete lists. This command also supports some Markdown syntax for links, images, lists and headlines:" & linefeed & linefeed & "Line = URL: [() • []() • ![() • ![]()" & linefeed & "Line = Text/Alt: []( • []) • [] • ![]( • ![]) • ![]" & linefeed & "Lists/Headlines: - • * • 1. • 2. • 3. … • # • ## • ### … • - [x]" default answer defaultTagStr with title (name of me) buttons {"Cancel", "Surround trimmed Lines", "Surround Lines with Tags"} default button defaultButton cancel button 1) as list
on error
return null
end try
do shell script "defaults write de.tekl.bbedit.surroundLinesWithTags tagString -string " & quoted form of tagStr
do shell script "defaults write de.tekl.bbedit.surroundLinesWithTags defaultButton -string " & quoted form of theButton
set tagStr to my regexReplace(tagStr, "/^\\s*<?\\/?(.*)>$/g", "$1")
set tagStrAsNumber to false
try
set tagStrAsNumber to my regexReplace(tagStr, "/[^0-9]/g", "") as integer
end try
tell application "BBEdit"
tell front document
if line breaks is "Unix" then set lineEnding to linefeed
if line breaks is "Mac" then set lineEnding to return
if line breaks is "DOS" then set lineEnding to return & linefeed
if tagStr is in {"ol", "ul", "menu"} then
set beginSelection to "<" & tagStr & ">" & lineEnding
set endSelection to "</" & tagStr & ">" & lineEnding
set tagStr to "li"
set indentStr to " "
else if tagStr is in {"select"} then
set beginSelection to "<" & tagStr & ">" & lineEnding
set endSelection to "</" & tagStr & ">" & lineEnding
set tagStr to "option value=\"\""
set indentStr to " "
else
set beginSelection to ""
set endSelection to ""
end if
if tagStr is in {"[()", "[]()"} then
-- Markdown Link url
set beginStr to "[]("
set endStr to ")"
else if tagStr is in {"[](", "[])", "[]"} then
-- Markdown Link text
set beginStr to "["
set endStr to "]()"
else if tagStr is in {"- [()", "- []()", "* [()", "* []()"} then
-- List with Markdown Link destination
set beginStr to characters 1 thru 3 of tagStr & "]("
set endStr to ")"
else if tagStr is in {"- [](", "- [])", "* [](", "* [])"} then
-- List with Markdown Link text
set beginStr to characters 1 thru 3 of tagStr & ""
set endStr to "]()"
else if tagStr is in {"![()", "![]()"} then
-- Markdown Image path
set beginStr to "![]("
set endStr to ")"
else if tagStr is in {"![](", "![])", "![]"} then
-- Markdown Image alt attribute or image description
set beginStr to "!["
set endStr to "]()"
else if tagStr is in {"-", "*", "- ", "* ", "- [ ]", "- [x]", "- [-]", "* [ ]", "* [x]", "* [-]", "- [ ] ", "- [x] ", "- [-] ", "* [ ] ", "* [x] ", "* [-] "} then
-- Markdown lists
if tagStr ends with " " then
set beginStr to tagStr
else
set beginStr to tagStr & " "
end if
set endStr to ""
else if tagStr is in {"#", "##", "###", "####", "#####", "######", "# ", "## ", "### ", "#### ", "##### ", "###### "} then
-- Markdown headlines
if tagStr ends with " " then
set beginStr to tagStr
else
set beginStr to tagStr & " "
end if
set endStr to lineEnding & lineEnding & lineEnding
else if (tagStr ends with "." or tagStr ends with ". ") and tagStrAsNumber is not false then
set beginStr to "#" & tagStrAsNumber & "#"
set endStr to ""
else
-- HTML Tags
set beginStr to "<" & tagStr & ">"
set endStr to "</" & my regexReplace(tagStr, "/^([^\\s]+).*/", "$1") & ">"
end if
set len to length of selection of application "BBEdit"
set loc to characterOffset of selection of application "BBEdit"
if (len = 0) then -- if no text was selected
if beginStr begins with "#" and beginStr ends with "#" and tagStrAsNumber is not false then
set newStr to indentStr & tagStrAsNumber & ". " & endStr & lineEnding
else
set newStr to indentStr & beginStr & endStr & lineEnding
end if
else if (len > 0) then
set curStr to selection of application "BBEdit" as text
set newStr to ""
-- surround every line
set paraStr to paragraphs of curStr
repeat with i from 1 to (count of paraStr) in paraStr
set curLine to item i of paraStr
if theButton contains "trimmed" then set curLine to my regexReplace(curLine, "/^\\s*(.*)\\s*$/g", "$1")
if curLine is "" and surroundEmptyLines is false then
set newStr to newStr & lineEnding
else
if beginStr begins with "#" and beginStr ends with "#" and tagStrAsNumber is not false then
set newStr to newStr & indentStr & i + (tagStrAsNumber - 1) & ". " & curLine & endStr & lineEnding
else
set newStr to newStr & indentStr & beginStr & curLine & endStr & lineEnding
end if
end if
end repeat
else
return
end if
-- replace selection with the new text
set contents of selection of application "BBEdit" to beginSelection & newStr & endSelection
-- move the cursor behind the tag of the first line
select insertion point after character (loc + (count of indentStr) + (count of beginStr) + (count of beginSelection) - 1)
end tell
end tell
end main
on regexReplace(subjectStr, findRegex, replaceRegex)
set subjectStr to stringReplace(subjectStr, "\"", "\\\"")
set jsCmd to "(new String(`" & subjectStr & "`)).replace(" & findRegex & ", '" & replaceRegex & "')"
return run script jsCmd in "JavaScript"
end regexReplace
on stringReplace(subjectStr, findStr, replaceStr)
set orgDelims to text item delimiters of AppleScript
set text item delimiters of AppleScript to findStr
set resultStr to text items of subjectStr
set text item delimiters of AppleScript to replaceStr
set resultStr to the resultStr as string
set text item delimiters of AppleScript to orgDelims
return resultStr
end stringReplace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment