[Question]
  [
# End the tabs versus space war
So, there has been a great deal of debate of whether to use tabs or spaces to indent/format code. Can you help the university settle the dispute, by going to an incredibly ~~crazy~~ unique method of formatting.
---
Your job is to write a full program or function which expands all tabs into four spaces. And then replaces a run of n leading spaces with "/(n - two stars here)/". You will receive input over multiple lines in any reasonable format (single string array of strings for each new line. Columnar array etc.) 
  
---
Sample input [shamelessly stolen](https://esolangs.org/wiki/Brainfuck). Note that since tabs get automagically expanded to four spaces on SE I represent it as the "^" character, but you must handle tabs (codepoint 0x09) as well. **All "^" characters represent a tabulation.**
```
Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
    Not zero so multiply by 256 again to get 65536
    [>++++<-]>[<++++++++>-]<[>++++++++<-]
    +>[>
        # Print "32"
        ++++++++++[>+++++<-]>+.-.[-]<
    <[-]<->] <[>>
        # Print "16"
        +++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
    # Print "8"
    ++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
^this is preceded by a tab
^^two tabs
^^^three tabs etcetera! 
```
Sample output
```
Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
/**/Not zero so multiply by 256 again to get 65536
/**/[>++++<-]>[<++++++++>-]<[>++++++++<-]
/**/+>[>
/******/# Print "32"
/******/++++++++++[>+++++<-]>+.-.[-]<
/**/<[-]<->] <[>>
/******/# Print "16"
/******/+++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
/**/# Print "8"
/**/++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
/**/this is preceded by a tab
/******/two tabs
/**********/three tabs etcetera! 
```
---
Because the university needs space to download both Vim and Emacs, you are allowed very little storage for your code. Therefore this is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'") and the shortest code wins. You may assume that input is well formed and lines with less than four spaces (after replacement of tabs) may result in undefined behavior.
### Disclaimer
This "excellent" formatting strategy came courtesy of Geobits, and is reproduced with his permission. No programmers were harmed during the production of this challenge.
  
[Answer]
# Vim, ~~37, 34, 33,~~ 32 bytes
```
:%s/\t/    /g|%norm ^hr/hv0r*r/
```
[Try it online!](http://v.tryitonline.net/#code=OiVzL1x0LyAgICAvZ3wlbm9ybSBeaHIvaHYwcipyLwo&input=U2FtcGxlIGlucHV0IHNoYW1lbGVzc2x5IHN0b2xlbi4gTm90ZSB0aGF0IHRhYnMgZ2V0IGF1dG9tYWdpY2FsbHkgZXhwYW5kZWQgdG8gZm91ciBzcGFjZXMgb24gU0UsIGJ1dCB5b3UgbXVzdCBoYW5kbGUgdGFicyBhcyB3ZWxsLgpDYWxjdWxhdGUgdGhlIHZhbHVlIDI1NiBhbmQgdGVzdCBpZiBpdCdzIHplcm8KSWYgdGhlIGludGVycHJldGVyIGVycm9ycyBvbiBvdmVyZmxvdyB0aGlzIGlzIHdoZXJlIGl0J2xsIGhhcHBlbgorKysrKysrK1s-KysrKysrKys8LV0-WzwrKysrPi1dCis8Wz4tPAoJTm90IHplcm8gc28gbXVsdGlwbHkgYnkgMjU2IGFnYWluIHRvIGdldCA2NTUzNgoJWz4rKysrPC1dPls8KysrKysrKys-LV08Wz4rKysrKysrKzwtXQoJKz5bPgoJCSMgUHJpbnQgIjMyIgoJCSsrKysrKysrKytbPisrKysrPC1dPisuLS5bLV08Cgk8Wy1dPC0-XSA8Wz4-CgkJIyBQcmludCAiMTYiCgkJKysrKysrK1s-KysrKysrKzwtXT4uKysrKysuWy1dPAo8PC1dXSA-Wz4KCSMgUHJpbnQgIjgiCgkrKysrKysrK1s-KysrKysrKzwtXT4uWy1dPAo8LV08CiMgUHJpbnQgIiBiaXQgY2VsbHNcbiIKKysrKysrKysrKytbPisrKz4rKysrKysrKys-KysrKysrKysrPis8PDw8LV0-LS4-LS4rKysrKysrLisrKysrKysrKysrLjwuCj4-LisrLisrKysrKysuLjwtLj4-LQpDbGVhbiB1cCB1c2VkIGNlbGxzLgpbWy1dPF1sCgl0aGlzIGlzIHByZWNlZGVkIGJ5IGEgdGFiCgkJdHdvIHRhYnMKCQkJdGhyZWUgdGFicyBldGNldGVyYSE)
Note that this requires a trailing carriage return (enter) in vim, although not in the online interpreter.
This uses the V interpreter because it's backwards compatible. A very straightforward solution. 
Here's a gif that lets you see the solution happen in real time. This uses a slightly older version, and I added some extra keystrokes to make it run slower so you can see what happens:
[![enter image description here](https://i.stack.imgur.com/OUizf.gif)](https://i.stack.imgur.com/OUizf.gif)
And here is the explanation of how it works:
```
:%s/\t/    /g           "Replace every tab with 4 spaces
|                       "AND
%norm                   "On every line:
      ^                 "  Move to the first non-whitespace char
       h                "  Move one character to the left. If there is none, the command will end here.
         r/             "  Replace it with a slash
           h            "  Move to the left
            v0          "  Visually select everything until the first column
              r*        "  Replace this selection with asterisks
                r/      "  Replace the first character with a slash
```
[Answer]
# Perl, 41 bytes
```
s,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,
```
Run with the `-p` flag, like so:
```
perl -pe 's,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,'
#     ↑   └───────────────────┬───────────────────┘
#     1 byte               40 bytes
```
Replace `␉` by a tab (in Bash, try typing `Control-V` `Tab`.)
[Answer]
# [Cheddar](http://cheddar.vihan.org), ~~60~~ ~~57~~ 56 bytes
*Saved 3 bytes thanks to @Conor O'Brien*
```
@.sub(/\t/g," "*4).sub(/^ +/gm,i->"/"+"*"*(i.len-2)+"/")
```
I wish Cheddar had better string formatting.
[Try it online!](http://cheddar.tryitonline.net/#code=QC5zdWIoL1x0L2csIiAiKjQpLnN1YigvXiArL2dtLCBpLT4iLyIrIioiKihpLmxlbi0yKSsiLyIp&input=ICAgIGZvdXIgc3BhY2VzCiAgICAgICAgZWlnaHQgc3BhY2VzCgl0YWIgY2hhcmFjdGVyIHdoaWNoIGlzIGhvcGVmdWxseSBwcmVzZXJ2ZWQ)
## Explanation
This is a function. `@` is a represents functionized property (e.g. ruby's `&:`) letting you do things like: `ar.map(@.head(-1)) 
```
@                      // Input
 .sub( /\t/g, " "*4)   // Replace tabs with four spaces
 .sub(
   /^ +/gm,            // Regex matches leading spaces
   i ->                // i is the matched leading spaces
     "/"+              // The / at the beginning
     "*"*(i.len-2)+    // Repeat *s i-2 times
     "/"                // The / at the end
 )
```
If you aren't familiar with regex the:
```
/^ +/gm
```
this basically matched one or more (`+`) spaces () at the beginning (`^`) of every (`g`) line (`m`).
[Answer]
# Mathematica, 97 bytes
```
a=StringReplace;a[a[#,"\t"->"    "],StartOfLine~~b:" "..:>"/"<>Table["*",StringLength@b-2]<>"/"]&
```
Anonymous function. Takes a string as input and returns a string as output.
[Answer]
# Python 3, 124 bytes
Uses good ol' regex.
```
import re
lambda I:re.sub('^\s*(?m)',lambda m:'/'+'*'*len(m.group()[:-2])+'/',re.sub('\t+',lambda g:' '*4*len(g.group()),I))
```
[**Ideone it!**](http://ideone.com/1w8qim)
[Answer]
# Java ~~210~~ 207 bytes
This is the reference solution which implements it naively.
```
void a(String[]a){for(String s:a){s=s.replaceAll("\t", "    ");String x,y="";int j,i=s.length()-(x=s.replaceAll("^\\s+", "")).length();if(i>3){y="/";for(j=0;j++<i-1;)y+="*";y+="/";}System.out.println(y+x);}}
```
[Answer]
# JavaScript ES6, 75 bytes
```
s=>s.replace(/\t/g,"    ").replace(/^ +/gm,k=>`/${"*".repeat(k.length-2)}/`)
```
Replace `\t` with a literal tab in your code.
[Answer]
# Java, ~~185~~ ~~184~~ ~~167~~ 152 bytes
```
S->S.map(s->{s=s.replace("\t","    ");String t=s.replaceAll("^ +","");int n=s.length()-t.length();if(n>3){s="/";for(;n-->2;)s+="*";s+="/"+t;}return s;})
```
Given the very loose definition of string array given in the initial post, I've used `Stream<String>` which allows for some consequent byte savings.
I used different techniques than the RI to achieve the same goal. The algorithm itself is rather the same.
**Testing and ungolfed**:
```
import java.util.Arrays;
import java.util.stream.Stream;
public class Main {
  public static void main(String[] args) {
    StringStreamTransformer sst = lines -> lines.map(line -> {
      line = line.replace("\t","    ");
      String trimmed = line.replaceAll("^ +", "");
      int startingSpaces = line.length() - trimmed.length();
      if (startingSpaces > 3) {
        line = "/";
        for(;startingSpaces > 2; startingSpaces--) {
          line += "*";
        }
        line += "/" + trimmed;
      }
      return line;
    });
    Stream<String> lines = Arrays.stream(new String[]{
      "lots of spaces and tabs after\t\t    \t\t         \t\t\t\t\t",
      "no space",
      " 1 space",
      "  2 spaces",
      "   3 spaces",
      "    4 spaces",
      "     5 spaces",
      "      6 spaces",
      "       7 spaces",
      "        8 spaces",
      "\t1 tab",
      "\t\t2 tabs",
      "\t\t\t3 tabs"
    });
    sst.map(lines).map(s -> s.replace(" ", ".").replace("\t","-")).forEach(System.out::println);
  }
}
```
[Answer]
# [V](http://github.com/DJMcMayhem/V), ~~21~~, 20 bytes
```
Íô/    
Î^hr/hv0r*r/
```
[Try it online!](http://v.tryitonline.net/#code=w43DtC8gICAgCsOOXmhyL2h2MHIqci8&input=U2FtcGxlIGlucHV0IHNoYW1lbGVzc2x5IHN0b2xlbi4gTm90ZSB0aGF0IHRhYnMgZ2V0IGF1dG9tYWdpY2FsbHkgZXhwYW5kZWQgdG8gZm91ciBzcGFjZXMgb24gU0UsIGJ1dCB5b3UgbXVzdCBoYW5kbGUgdGFicyBhcyB3ZWxsLgpDYWxjdWxhdGUgdGhlIHZhbHVlIDI1NiBhbmQgdGVzdCBpZiBpdCdzIHplcm8KSWYgdGhlIGludGVycHJldGVyIGVycm9ycyBvbiBvdmVyZmxvdyB0aGlzIGlzIHdoZXJlIGl0J2xsIGhhcHBlbgorKysrKysrK1s-KysrKysrKys8LV0-WzwrKysrPi1dCis8Wz4tPAoJTm90IHplcm8gc28gbXVsdGlwbHkgYnkgMjU2IGFnYWluIHRvIGdldCA2NTUzNgoJWz4rKysrPC1dPls8KysrKysrKys-LV08Wz4rKysrKysrKzwtXQoJKz5bPgoJCSMgUHJpbnQgIjMyIgoJCSsrKysrKysrKytbPisrKysrPC1dPisuLS5bLV08Cgk8Wy1dPC0-XSA8Wz4-CgkJIyBQcmludCAiMTYiCgkJKysrKysrK1s-KysrKysrKzwtXT4uKysrKysuWy1dPAo8PC1dXSA-Wz4KCSMgUHJpbnQgIjgiCgkrKysrKysrK1s-KysrKysrKzwtXT4uWy1dPAo8LV08CiMgUHJpbnQgIiBiaXQgY2VsbHNcbiIKKysrKysrKysrKytbPisrKz4rKysrKysrKys-KysrKysrKysrPis8PDw8LV0-LS4-LS4rKysrKysrLisrKysrKysrKysrLjwuCj4-LisrLisrKysrKysuLjwtLj4-LQpDbGVhbiB1cCB1c2VkIGNlbGxzLgpbWy1dPF1sCgl0aGlzIGlzIHByZWNlZGVkIGJ5IGEgdGFiCgkJdHdvIHRhYnMKCQkJdGhyZWUgdGFicyBldGNldGVyYSE)
This is literally just a direct port of my vim answer. The notable differences:
* The `Í` command (Global substitute) automatically fills in the `/g` flag, which saves two bytes
* `ô` is identical to `\t`
* `Î` Is a mnemonic for `:%norm`, and it also fills in the necessary space between `:%norm` and the set of keystrokes.
* The trailing carriage return at the end is implicitly added.
[Answer]
# [Retina](http://github.com/mbuettner/retina), 25 bytes
The `\t` should be replaced with an actual tab character (0x09).
```
\t
4$* 
%`^  ( +)
/$.1$**/
```
[Try it online!](http://retina.tryitonline.net/#code=CQo0JCogCiVgXiAgKCArKQovJC4xJCoqLw&input=Q2FsY3VsYXRlIHRoZSB2YWx1ZSAyNTYgYW5kIHRlc3QgaWYgaXQncyB6ZXJvCklmIHRoZSBpbnRlcnByZXRlciBlcnJvcnMgb24gb3ZlcmZsb3cgdGhpcyBpcyB3aGVyZSBpdCdsbCBoYXBwZW4KKysrKysrKytbPisrKysrKysrPC1dPls8KysrKz4tXQorPFs-LTwKICAgIE5vdCB6ZXJvIHNvIG11bHRpcGx5IGJ5IDI1NiBhZ2FpbiB0byBnZXQgNjU1MzYKICAgIFs-KysrKzwtXT5bPCsrKysrKysrPi1dPFs-KysrKysrKys8LV0KICAgICs-Wz4KICAgICAgICAjIFByaW50ICIzMiIKICAgICAgICArKysrKysrKysrWz4rKysrKzwtXT4rLi0uWy1dPAogICAgPFstXTwtPl0gPFs-PgogICAgICAgICMgUHJpbnQgIjE2IgogICAgICAgICsrKysrKytbPisrKysrKys8LV0-LisrKysrLlstXTwKPDwtXV0gPls-CiAgICAjIFByaW50ICI4IgogICAgKysrKysrKytbPisrKysrKys8LV0-LlstXTwKPC1dPAojIFByaW50ICIgYml0IGNlbGxzXG4iCisrKysrKysrKysrWz4rKys-KysrKysrKysrPisrKysrKysrKz4rPDw8PC1dPi0uPi0uKysrKysrKy4rKysrKysrKysrKy48Lgo-Pi4rKy4rKysrKysrLi48LS4-Pi0KQ2xlYW4gdXAgdXNlZCBjZWxscy4KW1stXTxdbAoJdGhpcyBpcyBwcmVjZWRlZCBieSBhIHRhYgoJCXR3byB0YWJzCgkJCXRocmVlIHRhYnMgZXRjZXRlcmEhIA)
### Explanation
```
\t
4$* 
```
Replace each tab with four spaces.
```
%`^  ( +)
/$.1$**/
```
Transform each line separately (`%`) by matching `2+N` spaces at the beginning of the line and replacing it with `/.../` where `...` is `N` copies of `*`.
[Answer]
# Python, ~~125~~ 111 bytes
```
lambda s:'\n'.join(('/'+(len(L.replace('\t',' '*4))-len(L.strip())-2)*'*'+'/'+L.strip(),L)[L[0]>' ']for L in s)
```
<https://repl.it/DGyh/2>
[Answer]
# SED (56 + 1 for -r) 57
```
s/⇥/    /g;tr;:r;s,^ ( *) ,/\1/,;T;:l;s,^(/\**) ,\1*,;tl
```
Where `⇥` is a tab  
1. replaces tabs with spaces.  
2. replaces the first and last leading space with `/`.  
3. replaces the first space after `/` and 0+ `*`s with a `*` until there isn't a match.
[Answer]
The university should consider allowing a bit more space for programs in Emacs Lisp (or default to `tabify` and `untabify` alone), as they get even more verbose than Java. It should also pay close attention to students (or teachers) whose identation size is smaller than four or who happen to code in some non-C-like language.
The following solution has **206 bytes**
```
(lambda (b e)(let((tab-width 4))(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))))))
```
Assuming that `tab-width` needs not to be explicitly set, we can save 20 of them.
```
(lambda(b e)(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2))))))))
```
And ungolfed version would look like this
```
(defun end-tab-war (beg end)
  (let ((tab-width 4))
    (untabify beg end)
    (goto-char beg)
    (while (re-search-forward "^ +" end t)
      (replace-match
       (format
        "/%s/"
        (apply 'concat
               (mapcar (lambda(x) "*")
                       (number-sequence 1
                                        (- (length (match-string 0))
                                           2)))))))))
```
We first `untabify` the region before jumping to its start. Then, while we see whitespace at the beginning of a line, we replace it with a comment that is as long as said whitespace. To be exact, the comment to be inserted is constructed by
```
 (format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))
```
which itself takes up 97 bytes. A shorter solution to copy some string n times is highly appreciated.
[Answer]
# Ruby, ~~52~~ 47 + 1 (p flag) = 48 bytes
**Edit**: saved whole 5 bytes, thanks to Value Ink
```
ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
```
[Answer]
## GNU sed, ~~66~~ 64 + 1(r flag) = 65 bytes
**Edit:** 1 byte less thanks to [Riley](/users/57100/riley)'s suggestion.
```
s/\t/    /g
s,^ ( *) ,/\1\n,
:
s,^(/\**) ( *\n),\1*\2,
t
s,\n,/,
```
**Run:** sed -rf formatter.sed input\_file
The reason for separating with a `\n` the leading spaces from the rest of the text on that line, is because otherwise a C++ line starting with a comment like this `/* */` would be turn into `/*****/` by a simpler line 4 like `s,^(/\**) ,\1*,` or even `s,^(/\**) ( */),\1*\2,`. Since sed executes the script for each input line, no `\n` is introduced in the pattern space on reading.
]