Repository: nix-community/nixpkgs-fmt (rust)
Issue: tabs are not preserved in string literals
Tabs within strings are converted to two spaces. Similar code formatters like rubocop and Prettier preserve tabs within strings, making this behavior surprising.

I noticed this while running nixpkgs-fmt on a NixOS configuration file with rules for /etc/exports. The change doesn't affect the meaning of the file, but might for other file types (TSV?).

## Input
```nix
{
  simpleStringLiteral = "col	col";

  multilineStringLiteral = ''
    col	col	col
  '';
}
```

## Output
```nix
--- Input	
+++ Output	
@@ -1,7 +1,7 @@
 {
-  simpleStringLiteral = "col	col";
+  simpleStringLiteral = "col  col";
 
   multilineStringLiteral = ''
-    col	col	col
+    col  col  col
   '';
 }
```

## Desired output

```nix
{
  simpleStringLiteral = "col	col";

  multilineStringLiteral = ''
    col	col	col
  '';
}
```

Pull request description: Improve formatting with tab characters
Closes #251

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index e9077c3..d1d5374 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -323,9 +323,9 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 
 [[package]]
 name = "rnix"
-version = "0.9.1"
+version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "294becb48f58c496d96c10a12df290266204ca75c9799be4d04222bfaebb6a37"
+checksum = "065c5eac8e8f7e7b0e7227bdc46e2d8dd7d69fff7a9a2734e21f686bbcb9b2c9"
 dependencies = [
  "cbitset",
  "rowan",
diff --git a/Cargo.toml b/Cargo.toml
index 0891350..4e01318 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,7 @@ repository = "https://github.com/nix-community/nixpkgs-fmt"
 members = [ "./wasm" ]
 
 [dependencies]
-rnix = "0.9.0"
+rnix = "0.10.1"
 smol_str = "0.1.17"
 
 # Dependencies that are used in the binary only
diff --git a/docs/releasing.md b/docs/releasing.md
index af4cb8e..afa716c 100644
--- a/docs/releasing.md
+++ b/docs/releasing.md
@@ -3,7 +3,9 @@
 This document describes the steps taken to release new versions of this
 project.
 
-1. Fill the CHANGELOG.md file. Use `git-changelog` to fill with commits.
+1. Fill the CHANGELOG.md file. 
+    - Use `git-changelog` to automatically generate the changelog from commit messages.
+    You can install this from the [`git-extras`](https://github.com/tj/git-extras) package.
 2. Bump the version in Cargo.toml
 3. Run `./update-cargo-nix.sh` to update the Cargo.lock and associated nix
    files
diff --git a/src/lib.rs b/src/lib.rs
index 195140c..9f4e2ef 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -89,11 +89,6 @@ pub fn reformat_node(node: &SyntaxNode) -> SyntaxNode {
 pub fn reformat_string(text: &str) -> String {
     let (mut text, line_endings) = convert_to_unix_line_endings(text);
 
-    // Forcibly convert tabs to spaces as a pre-pass
-    if text.contains('\t') {
-        text = Cow::Owned(text.replace('\t', "  "))
-    }
-
     let ast = rnix::parse(&*text);
     let root_node = ast.node();
     let res = reformat_node(&root_node).to_string();
diff --git a/src/rules.rs b/src/rules.rs
index 51bb96d..e632bec 100644
--- a/src/rules.rs
+++ b/src/rules.rs
@@ -812,7 +812,7 @@ foo = x:
             .into(),
         }
         .run()
-        .map_err(|e| panic!(e))
+        .map_err(|e| panic!("{}", e))
         .unwrap();
     }
 


Test patch:
diff --git a/test_data/indent_tabs-1.bad.nix b/test_data/indent_tabs-1.bad.nix
new file mode 100644
index 0000000..a88a4cc
--- /dev/null
+++ b/test_data/indent_tabs-1.bad.nix
@@ -0,0 +1,3 @@
+	{
+		test = "1";
+	}
diff --git a/test_data/indent_tabs-1.good.nix b/test_data/indent_tabs-1.good.nix
new file mode 100644
index 0000000..4d10c70
--- /dev/null
+++ b/test_data/indent_tabs-1.good.nix
@@ -0,0 +1,3 @@
+{
+  test = "1";
+}
diff --git a/test_data/indent_tabs-2.bad.nix b/test_data/indent_tabs-2.bad.nix
new file mode 100644
index 0000000..e3d0e5c
--- /dev/null
+++ b/test_data/indent_tabs-2.bad.nix
@@ -0,0 +1,24 @@
+args@{	z	,	}	:
+
+		  	{
+		a	 =  	 	"1"	;
+		b	 =	 {	} 	// 	{	}	;		
+		c 	=	   	z	.	y	;
+		d 	=	 1.2	;	
+	e 	=	   5	  	;
+		f	 = 	./test		;
+			g	 = 	true	;		
+		h 		=	 null	;
+	i 	  		=	 [	 1	 ./example.bin	 { 		hello	=		"world"	;	 } 	]	;	
+			j 	= 		5	 * 			5;			
+	k     = z ? fs		    ;
+	l   = z 		++		 z;
+	m 	=	 - 324		;
+	n = z		  z    ;	
+	o = import 	 	 	 		<nixpkgs>		;
+	p = with z; "fdsfs";			    
+	q = ''
+  ${5+5}
+	'';
+	r = " f${z}ds ";
+		  	  		 }
\ No newline at end of file
diff --git a/test_data/indent_tabs-2.good.nix b/test_data/indent_tabs-2.good.nix
new file mode 100644
index 0000000..0c5ea05
--- /dev/null
+++ b/test_data/indent_tabs-2.good.nix
@@ -0,0 +1,24 @@
+args@{ z, }:
+
+{
+  a = "1";
+  b = { } // { };
+  c = z.y;
+  d = 1.2;
+  e = 5;
+  f = ./test;
+  g = true;
+  h = null;
+  i = [ 1 ./example.bin { hello = "world"; } ];
+  j = 5 * 5;
+  k = z ? fs;
+  l = z ++ z;
+  m = - 324;
+  n = z z;
+  o = import <nixpkgs>;
+  p = with z; "fdsfs";
+  q = ''
+      ${5+5}
+    	'';
+  r = " f${z}ds ";
+}
diff --git a/test_data/indent_tabs-3.bad.nix b/test_data/indent_tabs-3.bad.nix
new file mode 100644
index 0000000..2e8c85f
--- /dev/null
+++ b/test_data/indent_tabs-3.bad.nix
@@ -0,0 +1,9 @@
+# 	this	is cool
+{
+	# nix doesn't see tabs as indentation so don't replace them
+	test = ''
+	test
+	test
+            '';
+	test2 = "fdf	dsfs   	 	 	jdfs	fsdf  df";
+}
diff --git a/test_data/indent_tabs-3.good.nix b/test_data/indent_tabs-3.good.nix
new file mode 100644
index 0000000..0ef02a1
--- /dev/null
+++ b/test_data/indent_tabs-3.good.nix
@@ -0,0 +1,9 @@
+# 	this	is cool
+{
+  # nix doesn't see tabs as indentation so don't replace them
+  test = ''
+    	test
+    	test
+  '';
+  test2 = "fdf	dsfs   	 	 	jdfs	fsdf  df";
+}