Last active
January 27, 2022 16:21
-
-
Save kiryph/bcbab4a710bfe4328f0eeb164d3b1c8e to your computer and use it in GitHub Desktop.
Key chords for essential shape & line styles in Inkscape using Karabiner & Hammerspoon on macOS (inspired by Gilles Castel 2019)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Add this to your ~/.hammerspoon/init.lua | |
-- based on https://castel.dev/post/lecture-notes-2/ and | |
-- https://github.com/gillescastel/inkscape-shortcut-manager | |
-- Make cli command `hs` available: | |
-- After an update of hammerspoon run once following two commmands | |
-- hs.ipc.cliUninstall(); hs.ipc.cliInstall() | |
require("hs.ipc") | |
local function intersect(m,n) | |
local r={} | |
for i,v1 in ipairs(m) do | |
for k,v2 in pairs(n) do | |
if (v1==v2) then | |
return true | |
end | |
end | |
end | |
return false | |
end | |
local function has_value (tab, val) | |
for index, value in ipairs(tab) do | |
if value == val then | |
return true | |
end | |
end | |
return false | |
end | |
function create_svg_and_paste(keys) | |
print(hs.inspect.inspect(keys)) | |
pt = 1.327 -- pixels | |
w = 1 * pt | |
thick_width = 4 * pt | |
very_thick_width = 8 * pt | |
style = {} | |
style["stroke-opacity"] = 1 | |
if intersect({"s", "a", "d", "g", "h", "x", "e"}, keys) | |
then | |
style["stroke"] = "black" | |
style["stroke-width"] = w | |
style["marker-end"] = "none" | |
style["marker-start"] = "none" | |
style["stroke-dasharray"] = "none" | |
else | |
style["stroke"] = "none" | |
end | |
if has_value(keys, "g") | |
then | |
w = thick_width | |
style["stroke-width"] = w | |
end | |
if has_value(keys, "v") | |
then | |
w = very_thick_width | |
style["stroke-width"] = w | |
end | |
if has_value(keys, "a") | |
then | |
style['marker-end'] = 'url(#marker-arrow-' .. tostring(w) .. ')' | |
end | |
if has_value(keys, "x") | |
then | |
style['marker-start'] = 'url(#marker-arrow-' .. tostring(w) .. ')' | |
style['marker-end'] = 'url(#marker-arrow-' .. tostring(w) .. ')' | |
end | |
if has_value(keys, "d") | |
then | |
style['stroke-dasharray'] = tostring(w) .. ',' .. tostring(2*pt) | |
end | |
if has_value(keys, "e") | |
then | |
style['stroke-dasharray'] = tostring(3*pt) .. ',' .. tostring(3*pt) | |
end | |
if has_value(keys, "f") | |
then | |
style['fill'] = 'black' | |
style['fill-opacity'] = 0.12 | |
end | |
if has_value(keys, "b") | |
then | |
style['fill'] = 'black' | |
style['fill-opacity'] = 1 | |
end | |
if has_value(keys, "w") | |
then | |
style['fill'] = 'white' | |
style['fill-opacity'] = 1 | |
end | |
if intersect(keys, {"f", "b", "w"}) | |
then | |
style['marker-end'] = 'none' | |
style['marker-start'] = 'none' | |
end | |
if not intersect(keys, {"f", "b", "w"}) | |
then | |
style['fill'] = 'none' | |
style['fill-opacity'] = 1 | |
end | |
svg = [[ | |
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
<svg> | |
]] | |
print(hs.inspect.inspect(style)) -- ENABLE ONLY FOR DEBUGGING | |
if (style['marker-end'] ~= nil and style['marker-end'] ~= 'none') or | |
(style['marker-start'] ~= nil and style['marker-start'] ~= 'none') | |
then | |
svgtemp = [[ | |
<defs id="marker-defs"> | |
<marker | |
]] | |
svgtemp = svgtemp .. 'id="marker-arrow-' .. tostring(w) .. "\"\n" | |
svgtemp = svgtemp .. 'orient="auto-start-reverse"' .. "\n" | |
svgtemp = svgtemp .. 'refY="0" refX="0"' .. "\n" | |
svgtemp = svgtemp .. 'markerHeight="3" markerWidth="2">' .. "\n" | |
svgtemp = svgtemp .. ' <g transform="scale('.. tostring((2.40 * w + 3.87)/(4.5*w)) .. ')">' .. "\n" | |
svg = svg .. svgtemp | |
svgtemp = [[ | |
<path | |
d="M -1.55415,2.0722 C -1.42464,1.29512 0,0.1295 0.38852,0 0,-0.1295 -1.42464,-1.29512 -1.55415,-2.0722" | |
style="fill:none;stroke:#000000;stroke-width:{0.6};stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1 | |
inkscape:connector-curvature="0" /> | |
</g> | |
</marker> | |
</defs> | |
]] | |
svg = svg .. svgtemp | |
end | |
style_string = '' | |
for key, value in pairs(style) do | |
-- skips nil? | |
style_string = style_string .. key .. ":" .. " " .. value .. ";" | |
end | |
svg = svg .. '<inkscape:clipboard style="' .. style_string .. '" />' .. "\n</svg>" | |
print(svg) -- ENABLE ONLY FOR DEBUGGING | |
hs.pasteboard.writeDataForUTI("dyn.ah62d4rv4gu80w5pbq7ww88brrf1g065dqf2gnppxs3xu", svg) | |
-- get UTI via https://github.com/sindresorhus/Pasteboard-Viewer | |
hs.eventtap.keyStroke({"shift", "cmd"}, "v") | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 1. $ jsonnet karabiner-inkscape.jsonnet > ~/.config/karabiner/assets/complex_modifications/karabiner-inkscape.json | |
// 2. Enable in Karabiner Elements UI the complex modifications | |
local arr = [ | |
[x, y, z] // 24x | |
for x in ['s', 'd', 'e'] // solid, dotted, dashed | |
for y in ['f', 'w', 'a', 'x'] // gray, white, arrow, double-arrow | |
for z in ['g', 'v'] // thick, very thick | |
] + | |
[ | |
[x, y] // 18x | |
for x in ['s', 'd', 'e'] // solid, dotted, dashed | |
for y in ['f', 'w', 'g', 'v', 'a', 'x'] | |
] + | |
[ | |
['spacebar', x] // 6x | |
for x in ['s', 'd', 'e', 'f', 'b', 'w'] // solid, dotted, dashed, gray, black, white | |
]; | |
{ | |
title: 'Apply quickly essential shape or line styles in Inkscape using hammerspoon (Gilles Castel, 2019)', | |
rules: [ | |
{ | |
description: 'Apply quickly essential shape or line styles in Inkscape using hammerspoon (Gilles Castel, 2019)', | |
manipulators: [ | |
{ | |
local str = std.join('+', el), | |
type: 'basic', | |
from: { | |
simultaneous: [{ key_code: i } for i in el], | |
simultaneous_options: { | |
key_up_when: 'all', | |
}, | |
}, | |
to: [{ shell_command: "/usr/local/bin/hs -c 'hs.alert(\"" + str + '");create_svg_and_paste({"' + std.join('","', el) + "\"});'" }], | |
conditions: [{ type: 'frontmost_application_if', bundle_identifiers: ['org.inkscape.Inkscape'] }], | |
} | |
for el in arr | |
], | |
}, | |
], | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment