A keyboard so real you can almost TASTE it

V, 189, 179, 175, 164, 161, 157, 155, 149, 145, 141, 135 bytes

¬19É`A0-=BS´ 
TAB³ qwertyuiop[]\
CAPS³ asdfghjkl;'ENTER 
SHIFT´ ÄJizxcvbnm,./Í„A-Z ]/Õ& 
ÍÓ«ü$/|||&
òÙÓ„|]/_
ÙÓ׫/Ü|¯
kkPÓ/_ _
kòÎx$x

Try it online!

This answer is now tweetable!


Watch it run! This is a slightly modified version that updates as it runs so you can sorta see how it works. This is an outdated version since I haven't gotten around to re-recording it yet, but the general approach is identical.

This is probably the longest V answer ever written. It certainly didn't help that V's interpreter is extremely slow. It took me around an hour to write the first revision, but I've been repeatedly coming back to it to shave a couple bytes off each time. Since the full keyboard is 1215 bytes, currently this answer is 91% shorter than the output, so I'm pretty happy with the results.

Since this contains some unprintable characters, and a lot of gross non-ASCII, here's a hexdump:

00000000: ac31 39c9 6041 302d 3d42 53b4 200a 5441  .19.`A0-=BS. .TA
00000010: 42b3 2071 7765 7274 7975 696f 705b 5d5c  B. qwertyuiop[]\
00000020: 0a43 4150 53b3 2061 7364 6667 686a 6b6c  .CAPS. asdfghjkl
00000030: 3b27 454e 5445 5220 0a53 4849 4654 b420  ;'ENTER .SHIFT. 
00000040: 1bc4 4a69 7a78 6376 626e 6d2c 2e2f 1bcd  ..Jizxcvbnm,./..
00000050: 8441 2d5a 205d 2fd5 2620 0acd d3ab fc24  .A-Z ]/.& .....$
00000060: 2f7c 7c7c 260a f2d9 d384 7c5d 2f5f 0ad9  /|||&.....|]/_..
00000070: d3d7 ab2f dc7c af0a 6b6b 50d3 2f5f 205f  .../.|..kkP./_ _
00000080: 0a6b f2ce 7824 78                        .k..x$x

How the heck does it work?

Alright, this explanation is gonna be a doozy. You ready? First off, we need enter the letters so we can build up the keys around them. This is

¬19É`A0-=BS´ 
TAB³ qwertyuiop[]\
CAPS³ asdfghjkl;'ENTER 
SHIFT´ <esc>ÄJizxcvbnm,./<esc>

Which inserts:

`1234567890-=BS    
TAB   qwertyuiop[]\
CAPS   asdfghjkl;'ENTER 
SHIFT    zxcvbnm,./SHIFT  

It enters it pretty straightforward, but there are a few tricks that we use to save characters. For example, ¬19 enters "123456789", ³ enters three spaces, and we duplicate the shift so that we don't need to enter it multiple times.

Note how the letters are lowercase here. This is so that we can easily distinguish between the uppercase keys like "ENTER" and the single letters. Writing them this way makes it easier to tell which characters to put a bar before, and only adds one byte to convert them to lowercase later. So we do a substitute command to convert these to uppercase, and add one space after each of them:

Í               " Globally replace
 [^A-Z ]        " Anything but a uppercase alphabet character or a space
        /       " with
         Õ&     " The matched pattern made uppercase, followed by a space

Now, we take each key sequence (any run of non-whitespace), and put three bars before and after them:

Í           " Globally replace
 Ó«         "   Any number of non-space characters
   ü        "   or
    $       "   an end of line
     /      " with
      |||   "    Three bars 
         &  "    And the matched pattern

At this point, the buffer looks like this:

|||` |||1 |||2 |||3 |||4 |||5 |||6 |||7 |||8 |||9 |||0 |||- |||= |||BS    |||
|||TAB   |||Q |||W |||E |||R |||T |||Y |||U |||I |||O |||P |||[ |||] |||\ |||
|||CAPS   |||A |||S |||D |||F |||G |||H |||J |||K |||L |||; |||' |||ENTER |||
|||SHIFT    |||Z |||X |||C |||V |||B |||N |||M |||, |||. |||/ |||SHIFT    |||

Having three bars on the first and last columns is actually very convenient and ends up saving many bytes in the long run.

And here is where we run one giant loop. This will convert something like this:

|||SHIFT    |||Z |||X |||C |||V |||B |||N |||M |||, |||. |||/ |||SHIFT    |||

into something like this:

 ___________ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___________ 
||SHIFT    |||Z |||X |||C |||V |||B |||N |||M |||, |||. |||/ |||SHIFT    ||
||_________|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||_________||
|/_________\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/_________\|

Everything between two instances of ò will run until an error happens, which will happen when we try to go up into a line that does exist yet. Since we just ran a globally substitute command, our cursor is on the last line, and we'll transform these working our way up.

ò         " Recursively:
 Ù        "   Duplicate this line
  Ó       "   Substitute all on this line:
   [^|]   "     Anything but a bar
       /  "   With:
        _ "     An underscore

This is the

|||_________|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||_________|||

line.

Ù         "   Duplicate this line
 Ó        "   Subsitute all on this line:
  ׫      "     A run of *non-word characters* (that is, [^0-9A-Za-z_])
    /     "   With:
     Ü|¯  "     '\|/'

This is the

\|/_________\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/_________\|/

Line.

kk        "   Move up two lines (to the original text with "SHIFT")
  P       "   Paste the last line we duplicated (the one with all the underscores)
   Ó      "   Substitute:
          "     Since we don't give any regex here, it re-uses the last one 
          "     (a run of *non-word* characters)
    /     "   With:
     _ _  "     '_ _'

This is the:

_ ___________ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___________ _

Line.

k         "   Move up a line (this will throw an error, breaking the loop when we're done)
 ò        " Endwhile

Now we have the full keyboard, but each line contains either an extra bar, an extra slash (forward or backward), or an extra underscore. Super easy fix

Î             " On every line:
 x            "   Delete a character
  $           "   Move to the end of the line
   x          "   and delete another character

After all that madness, the buffer is implicitly printed.


Lua 5.3, 416 394 Bytes.

k="` 1 2 3 4 5 6 7 8 9 0 - = BS|TAB Q W E R T Y U I O P [ ] \\|CAPS A S D F G H J K L ; ' ENTER|SHIFT Z X C V B N M , . / SHIFT"S={TAB=6,BS=6,ENTER=6,CAPS=7,SHIFT=9}for v in k:gmatch"[^|]+"do for i=1,4 do for s in v:gmatch"%S+"do l=S[s]or 2j=("_"):rep(l)io.write(i==1 and" _"..j.."_"or i==2 and"||"..s..(" "):rep(l-#s).."|"or i==3 and"||"..j.."|"or"|/"..j.."\\")end print(i>1 and"|"or"")end end

Ungolfed and with comments.

keys="` 1 2 3 4 5 6 7 8 9 0 - = BS|TAB Q W E R T Y U I O P [ ] \\|CAPS A S D F G H J K L ; ' ENTER|SHIFT Z X C V B N M , . / SHIFT" -- Define a keyboard. Separated with |'s, there's probably a nicer way to do this, but I'm not sure about how to yet.
special_keys={TAB=6,BS=6,ENTER=6,CAPS=7,SHIFT=9} -- Special keys get special definitions
for v in keys:gmatch"[^|]+" do -- For each row on the keyboard...
    for i=1, 4 do -- Each of the 4 rows per key...
        for s in v:gmatch"%S+" do -- Match each individual key.
            l=special_keys[s]or 2 j=("_"):rep(l) -- l is the length of the key, j is "_" repeated length times, which is used a bit.
            io.write(i==1 and -- Lua needs Switch Statements!
                     " _"..j.."_" -- The top of the key is a Space, then j with two _'s around it.
                     or
                     i==2 and
                     "||"..s..(" "):rep(l - #s).."|" -- Second row is || then the key, then the remaining whitespace, and then one more |, which chains together.
                     or
                     i==3 and
                     "||"..j.."|" -- Third row is like the second, but without the key. Instead of whitespace, uses j, which is the underlines.
                     or
                     "|/"..j.."\\") -- Last row is like the third row, but with "|/" and "\" instead of "||" and "|"
        end
        print(i>1 and"|"or"") -- First line is the only line that doresn't need a "|", everything else gets a "|" before the newline.

    end
end

Output

 ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ________
||` |||1 |||2 |||3 |||4 |||5 |||6 |||7 |||8 |||9 |||0 |||- |||= |||BS    ||
||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||______||
|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/______\|
 ________ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
||TAB   |||Q |||W |||E |||R |||T |||Y |||U |||I |||O |||P |||[ |||] |||\ ||
||______|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__||
|/______\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|
 _________ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ________
||CAPS   |||A |||S |||D |||F |||G |||H |||J |||K |||L |||; |||' |||ENTER ||
||_______|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||______||
|/_______\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/______\|
 ___________ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___________
||SHIFT    |||Z |||X |||C |||V |||B |||N |||M |||, |||. |||/ |||SHIFT    ||
||_________|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||_________||
|/_________\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/_________\|

I'm going to get destroyed by other langauges, but I thought I'd give this a shot. Nice amount of complexity, and atleast it's shorter than the keyboard!


Bubblegum, 191 bytes

0000000: ad d2 35 7a c6 30 10 06 e1 5e a7 50 15 66 fe 99  ..5z.0...^.P.f..
0000010: c1 8c 61 50 0e b2 87 8f 27 24 f7 eb af 78 2b e3  ..aP....'$...x+.
0000020: 3c b2 ae 99 1a 66 8d c8 a7 15 91 73 b8 80 4b b8  <....f.....s..K.
0000030: 82 6b b8 81 5b b8 83 1e 9c c1 31 8c 60 5e d9 66  .k..[.....1.`^.f
0000040: 22 46 c4 39 d1 c2 78 d6 a9 73 6f 5a d8 9b 18 ff  "F.9..x..soZ....
0000050: bb 5a e8 55 cf e6 fc ae 48 01 8f b0 82 12 6a 78  .Z.U....H.....jx
0000060: 86 7b 08 20 83 1c 5e e1 1d de e8 e5 7f 57 b4 d0  .{. ..^......W..
0000070: 8b a9 9b f9 5e 5d 9d af c5 2c af 7e 82 cd a0 82  ....^]...,.~....
0000080: 25 ac 61 03 5b 08 21 82 18 06 b0 0b ab b4 5e 95  %.a.[.!.......^.
0000090: ad 5e 5d 9d 2f d6 e9 f9 d2 c4 f2 bd aa 6d b0 ae  .^]./........m..
00000a0: ed 4f b1 17 78 82 05 3c c0 1c 52 48 e0 08 4e e0  .O..x..<..RH..N.
00000b0: 14 5a 77 fb 5e aa 58 be 97 aa 98 bf db 7c 01     .Zw.^.X......|.

Try it online!