[Question]
  [
You have been chosen to make a program that creates some pretty ASCII [bar charts](https://en.wikipedia.org/wiki/Bar_chart). Here is the input format:
```
[List of words (they can have spaces)] [an integer >= 0]
Bar 3
This is so cool 4
IDK-Why 6
```
The input will have multiple lines in this format, each one representing one bar in the graph. The output format of a graph will be like this:
```
 _ _ _ _
|_|_|_|_|
 | | | |
 | | | + [name of 4th bar]
 | | + [name of 3rd bar]
 | + [name of 2nd bar]
 + [name of 1st bar]
```
Here are some examples:
```
In:
Cool 4
Kool 6
Out:
   _
  | |
 _| |
| | |
| | |
| | |
|_|_|
 | |
 | + Kool
 + Cool
In:
Graph 5
Bar 3
Out:
 _
| |
| |_
| | | 
| | |
|_|_|
 | |
 | + Bar
 + Graph
In:
Very 4
Large 5
Bar 3
Graph 5
Out:
   _   _
 _| | | | 
| | |_| |
| | | | |
| | | | |
|_|_|_|_|
 | | | |
 | | | + Graph
 | | + Bar
 | + Large
 + Very
In:
Bars can be 0 0
Large-bars_are$nice2 6
average)(@#$ 3
neato 5
Out:
   _
  | |  _
  | | | | 
  | |_| |
  | | | |
  | | | |
 _|_|_|_|
 | | | |
 | | | + neato
 | | + average)(@#$
 | + Large-bars_are$nice2
 + Bars can be 0
```
Functions or full programs are allowed.
  
[Answer]
# sh + awk + tac, 173
Mostly an `awk` script that prints the graph bottom up which is then reversed by `tac`.
```
awk '{n[NR]=$NF;$NF="";$0=p" + "$0;p=" |"p}1;END{for(print p;p~/\|/;print p (k>($0=0)?"|":""))for(i=k=p="";i<NR;p=p (j>0||k>0?"|":" ")(!k||$0?"_":" ")){j=k;k=n[++i]--}}'|tac
```
### Description
**awk, first part, executed for each input line**
```
{
  n[NR]=$NF;         # store the value, here n[1]=0, n[2]=6, n[3]=3, n[4]=5
  $NF="";            # remove the value from the label
  $0=p" + "$0;       # add a prefix (initially empty) and a " + " in the front
  p=" |"p            # grow the prefix for the next string
}1;                  # implicitly print $0
```
**Output**
```
 + Bars can be 0 
 | + Large-bars_are$nice2 
 | | + average)(@#$ 
 | | | + neato 
```
**awk, second part, executed once in the end**
```
END{
  for(print p;p~/\|/;print p (k>($0=0)?"|":""))
    for(i=k=p="";i<NR;p=p (j>0||k>0?"|":" ")(!k||$0?"_":" "))
      {j=k;k=n[++i]--}}
```
ungolfed:
```
END{
  print p;           # print the prefix again
  for(;p~/\|/;)      # for each line, bottom up. no more "|" -> we're done
  {
    p="";            # string to be built
    i=k=0;           # i: bar index, k: heigth of the previous bar
    for(;i<NR;)      # for each bar, left to right
    {
      j=k;           # store the previous bars heigth in j
      k=n[++i]--;    # get the current bars remaining height and decrement it
      p=p (j>0||k>0?"|":" ")(!k||$0?"_":" ");
                     # if the bar to the left or this one have some height
                       remaining, draw a border in between them, else a space
                     # if this bars remaining heigth is exactly 0, draw a top
                     # if $0 is set, draw the bottom
    }
    print p (k>0?"|":"");
                     # draw (or not) the rightmost border, finally print
    $0=0;            # unset $0, only to detect first run
  }
}
```
**Output**
```
 | | | |             # the prefix
 _|_|_|_|            # the strings built by the nested loops
  | | | |            |
  | | | |            v
  | |_| |
  | | | |
  | |  _
   _                 # no more "|" in the string, we're done
```
**tac reverses the lines**
```
   _    
  | |  _
  | | | |
  | |_| |
  | | | |
  | | | |
 _|_|_|_|
 | | | |
 | | | + neato 
 | | + average)(@#$ 
 | + Large-bars_are$nice2 
 + Bars can be 0 
```
[Answer]
# JavaScript (ES6), 270 ~~262 270 287~~
*Bug fix* added a missing row of '|' under the bars
```
l=>{t=p=o='';l=l.split`
`.map(r=>([,b,c]=r.match(/(.*) (\d+)/),[' + '+b,+c>t?t=c:c]));for(++t;t--;o+=`
`)l.map(x=>o+=x[1]<t?'y y':x[1]>t?t?'x x':'x_x':'y_y');return o.replace(/(yx)|(xy)|(xx?)/g,'|').replace(/y+/g,' ')+[...l,' '].map(x=>p+x[p+=' |',0]).reverse().join`
`}
```
**Test** Test in Firefox, as Chrome does not support ES6 [Destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
```
F=l=>{
  t=p=o='';l=l.split`\n`.map(r=>([,b,c]=r.match(/(.*) (\d+)/),[' + '+b,+c>t?t=c:c]));
  for(++t;t--;o+=`\n`)l.map(x=>o+=x[1]<t?'y y':x[1]>t?t?'x x':'x_x':'y_y');
  return o.replace(/(yx)|(xy)|(xx?)/g,'|').replace(/y+/g,' ')
  +[...l,' '].map(x=>p+x[p+=' |',0]).reverse().join`\n`
}
function test()
{
  var i=I.value
  O.textContent=F(i)
}  
  
test()
```
```
textarea { display:block; width:50%; height:5em}
```
```
Input
<textarea id=I>Bars can be 0 0
Large-bars_are$nice2 6
average)(@#$ 3
neato 5</textarea>
<button onclick='test()'>go</button><br>
Output
<pre id=O></pre>
```
[Answer]
# 421 bytes - Python 2
```
import sys
l=sys.stdin.read().split('\n')
b=[(' '.join(x[:-1]),int(x[-1])) for x in map(str.split,l[:-1])]
a=len(b)
e=enumerate
m=[' '*(a+1)+'|'*x[1] for i,x in e(b)]+[' '*(len(b)+1)+'|'*b[-1][1]]
h=[' '*i+'+'+'|'*(a-i)+'_'+' '*(x[1]-1)+'_' for i,x in e(b)]
c=m+h
c[::2]=m
c[1::2]=h
c=[''.join(' ' if not x else x for x in l) for l in map(None,*c)]
for i,(n,_) in e(b):
 c[a-i-1]+='\b'*i*2+n
c='\n'.join(c[::-1])
print(c)
```
## Tests
```
a 1
b 2
c 3
     _
   _| |
 _| | |
|_|_|_|
 | | |
 | | + c
 | + b
 + a
```
[Answer]
# [PowerShell](https://github.com/TryItOnline/TioSetup/wiki/Powershell), ~~208~~ ~~194~~ ~~190~~ ~~168~~ ~~167~~ 164 bytes
```
(($h=$args|%{$t,$n=$_-split'(?=\d+$)';$r=,"$c + $t"+$r;$c+=' |';$n})|sort)[-1]..0|%{$i=$_
&{-join($h|%{($p,($p=' |'[$i-lt$_])|sort)[-1];' _'[$i-in0,$_]})+$p}}
$c
$r
```
[Try it online!](https://tio.run/##fZJPT4NAEMXv@ykmOu2yARr6Ry8NsdGDBz17qQ3Z0m3B4EKWjcYAnx2nCK0xqZvsYeb33pvZZIv8U5kyUVnW4h5CqFrHwSREaQ5lParQeqhDjPyyyFLLnbvwdeei4Es0oXeFMbiA9spFs8TYDTnURHQj6jI3Vqz96WYyCY4xKWWwceW/5ammfGo5WHh0O88aUz@zGG1@GZccog6kOvAINcLFomkYxgxN2zC2chjzHAD@kOcZLLjHgA5/Ola3HERP76UpIZYatgoCCAbZMz1Q@VuCkTQKdRqrGdl6Kj@UkQclnNU1wnzoaiVtDjfn7Ecji4QaPadRJD7RF2W@znt1A/9q@2LIOVnXWr4ryPcwLS3QkhuYDtoTmundJTQ3F9HCJgM6ThNQwwiqTjSmD7CKfvT@P4ezpv0G "PowerShell – Try It Online")
Unrolled:
```
# parse input
$heights = $args|%{        
    $title,$number=$_-split'(?=\d+$)'   # the title contains a trailing space. It's allowed by the author
    $rows=,"$columns + $title"+$rows
    $columns+=' |'
    Write-Output $number
}
# draw bars
($heights|sort)[-1]..0|%{   # max($heights)..0
    $lineNum=$_
    &{                      # execute the scriptblock to reset inner variables
        -join(
            $heights|%{
                $currLeftBorder = ' |'[$lineNum -lt $_]
                Write-Output ($prev,$currLeftBorder|sort)[-1]   # max
                Write-Output ' _'[$lineNum -in 0,$_]
                $prev=$currLeftBorder
            }
        )+$prev
    }
}
# draw bottom columns and titles
Write-Output $columns
Write-Output $rows
```
[Answer]
## Java, 613 for the printing function
It may be possible to save a few bytes by the "usual" transformations of `for(i=0;i<n;i++)` to `for(;i++<n;)`, simplifying the ternary conditionals, or with more elegant computations of the "labels" and "heights", but it's a start.
```
package stackoverflow.codegolf.barchart;
import static java.util.stream.Stream.of;
import java.util.stream.IntStream;
public class BarChartTest
{
    public static void main(String[] args)
    {
        String input0[] = {
            "Cool 4",
            "Kool 6",
        };
        String input1[] = {
            "Graph 5",
            "Bar 3",
        };
        String input2[] = {
            "Very 4",
            "Large 5",
            "Bar 3",
            "Graph 5",
        };
        String input3[] = {
            "Bars can be 0 0",
            "Large-bars_are$nice2 6",
            "average)(@#$ 3",
            "neato 5",
        };
        runTest(input0);
        runTest(input1);
        runTest(input2);
        runTest(input3);
    }
    private static void runTest(String input[])
    {
        System.out.println("In:");
        for (String string : input)
        {
            System.out.println(string);
        }
        System.out.println("Out:");
        BarChartTest b = new BarChartTest();
        b.print(input);
    }
    void p(String a[]){int h[]=of(a).map(this::s).mapToInt(Integer::parseInt).toArray(),M=IntStream.of(h).max().getAsInt(),C=a.length,r,c,y;Object t[]=of(a).map(this::p).toArray();String s="",p=" + ",w="";char n=10,v='|',i=32,u=95,e;for(r=0;r<=M;r++){e=r==M?'_':' ';y=M-r;for(c=0; c<C; c++){s+=h[c]>y?v:c>0?h[c-1]>y?v:e:r==0?e:i;s+=h[c]==y?u:e;}s+=h[C-1]>y?v:e;s+=n;}for(r=0;r<C;r++){for(c=0;c<C-r;c++){s+=" |";}s+=r>0?p+t[C-r]:w;s+=n;}s+=p+t[0];System.out.println(s);}int b(String s){return s.lastIndexOf(" ");}String p(String s){return s.substring(0,b(s));}String s(String s){return s.substring(b(s)+1,s.length());}
}
```
[Answer]
## Haskell, 323 bytes
```
f x|(p,q)<-unzip$map((\l->(unwords$init l,(read$last l))).words)$lines x=unlines(reverse$init.(zip((zipWith max=<<tail)$0:q++[0])(q++[0])>>=).(!)<$>[0..maximum q])++v p++'\n':(0#p)
v=(>>" |")
_#[]=""
l#(h:t)=(l+1)#t++v[1..l]++" + "++h++"\n"
0!(0,_)=" _"
0!_="|_"
i!(j,k)|i<j=(i==k)?'|'|1<2=(i==k)?' '
i?c|i=c:"_"|1<2=c:" "
```
Usage example:
```
*Main> putStr $ f "Bars can be 0 0\nLarge-bars_are$nice2 6\naverage)(@#$ 3\nneato 5"
   _     
  | |  _ 
  | | | |
  | |_| |
  | | | |
  | | | |
 _|_|_|_|
 | | | |
 | | | + neato
 | | + average)(@#$
 | + Large-bars_are$nice2
 + Bars can be 0
```
How it works (rough overview, details maybe later):
```
(p,q)<-unzip$map((\l->(unwords$init l,(read$last l))).words)$lines x
           -- breaks the input into a list of labels (-> p), e.g.
           -- ["Bars can be 0","Lagerge-basr_asr$niche",...] and a list of heights
           -- (-> q), e.g. [0,6,3,5]
unlines(reverse$init.(zip((zipWith max=<<tail)$0:q++[0])(q++[0])>>=).(!)<$>[0..maximum q])
           -- builds the bars
v p++"\n"
           -- builds the first row of "|" underneath the zero line
(0#p)
           -- build the label section
```
The parsing part (`(p,q)<-unlines...`) takes a lot of bytes, maybe I can it golf further down.
[Answer]
## Python 2, 345 bytes
```
B,H=zip(*[(a,int(b))for a,b in[x.rsplit(' ',1)for x in input().split('\n')]])
h=max(H)
L=len(B)
b=['|'*H[0]]*(L*2+1)
for i in range(L):b[2+i*2]='|'*max(H[i],H[min(i+1,L-1)]);b[1+i*2]=('_'+' '*(H[i]-1)+'_')[:H[i]+1]
b=[x.ljust(h+1)for x in b]
for l in zip(*b)[::-1]:print ''.join(l)
print' |'*L
for i in range(-1,-L-1,-1):print' |'*(L+i),'+',B[i]
```
]