Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strip trailing whitespaces and newline at EOF #261

Closed
codingforfun opened this issue Jul 28, 2018 · 13 comments
Closed

Strip trailing whitespaces and newline at EOF #261

codingforfun opened this issue Jul 28, 2018 · 13 comments

Comments

@codingforfun
Copy link

Feature request

It would be great to have an option to remove trailing whitespace and tabs at end of line and also to remove superfluous newlines at end of file / ensure there is exactly a single newline at end of file.

This is some kind of standard for text only files like programming code and would be nice to have also for .tex files.

This is also something version control tools like GIT complain about and since working with .tex file plays nice with version control this would be very helpful in this case also.

Currently I use a simple script for this to achieve before adding my files to version control, but avoiding this extra post-processing step would be really great.

@codingforfun
Copy link
Author

Btw.: I found a similar issue for this at sourceforge. Not sure which one is more recent. I.e. which tracker is really used by developers – GitHub or Sourceforge. Sorry if I duplicated it wrong.

https://sourceforge.net/p/texstudio/feature-requests/757

@sunderme
Copy link
Member

you could make use of txs macro/script ability. I don‘t see a general demand for this.

@codingforfun
Copy link
Author

I think it’s not very polite to instantly close this. Why don’t you leave this open for a while to give others a chance to add their opinion? I think is good practice for most open source projects.

@sunderme
Copy link
Member

see
https://github.com/texstudio-org/texstudio/wiki/Scripts#remove-whitespace-at-the-end-of-all-lines

not every functionality needs to be programmed in the core code, that is why we implemented all that nice scripting capabilities.
if you adapt above script to your needs, you can publish it in the wiki.

@codingforfun
Copy link
Author

yet feature request could deserve some time for discussion. ;-)

I tried the script with the save trigger.
There is one problem: After saving the file and replacing all the text with the stripped text the editor pane scrolls to the first line.
I tried to fix this getting the cursor position before removing the space and resetting it afterwards using cursor.moveTo, however this has no effect on scrolling the editor pane.

I found no script commands for scrolling. I used this reference:
http://texstudio.sourceforge.net/manual/current/usermanual_en.html#SECTION33c

My version of the script

%SCRIPT
var tl = editor.document().textLines();
var r = cursor.lineNumber();
var c = cursor.columnNumber();
for (var i=tl.length-1;i>=0;i--) 
tl[i] = tl[i].replace(/\s+$/, '');
editor.setText(tl.join("\n"));
cursor.moveTo(r, c);

@codingforfun
Copy link
Author

Another super annoying thing about this solution: The save trigger is also triggered on each TeX run. This makes sense of course, but together with scrolling to the begin of the document it makes the script solution unusable because it breaks writing flow to scroll back on every preview.

Maybe this is something that should be natively programmed into the core editor code after all ;-)

@codingforfun
Copy link
Author

And btw. I hope you don’t get me wrong nagging about this. TexStudio is great piece of software and I really love to work with it and value your work. I’m a developer too and know how much work this must have been. Tried some open source projects in my spare time myself and know how difficult it is to get something done in a very limited amount of spare time. So hope you don’t mind.

@sunderme
Copy link
Member

sunderme commented Jul 28, 2018

This seems to do the trick:

%SCRIPT
var tl = editor.document().textLines();
var r = cursor.lineNumber();
var c = cursor.columnNumber();
for (var i=tl.length-1;i>=0;i--) {
tl[i] = tl[i].replace(/\s+$/, '');
cursor.moveTo(i, 0);
cursor.movePosition(1, cursorEnums.EndOfLine, cursorEnums.KeepAnchor)
cursor.replaceSelectedText(tl[i]);
}
cursor.moveTo(r,c);

@romankarlstetter
Copy link

A small enhancement on the script:

%SCRIPT

var tl = editor.document().textLines();
var r = cursor.lineNumber();
var c = cursor.columnNumber();
for (var i=tl.length-1;i>=0;i--) {
	var lineText = tl[i];
	if (lineText.match(/\s+$/)) {
		var lineTextFixed = lineText.replace(/\s+$/, '');
		cursor.moveTo(i, 0);
		cursor.movePosition(1, cursorEnums.EndOfLine, cursorEnums.KeepAnchor)
		cursor.replaceSelectedText(lineTextFixed);
	}
}
cursor.moveTo(r,c);

This only does the cursor magic when the line actually needs to be changed.

@nickswalker
Copy link

Want to note that I too thought this would be built in behavior, and found it strange I would have to copy paste a script off the internet to get this functionality. Grateful that works though

@jondo
Copy link

jondo commented Oct 16, 2019

For newbies like me: The save trigger is ?save-file.

@EliaCereda
Copy link

EliaCereda commented Jan 1, 2021

I made a version which also ensures that there is exactly one empty line at the end of the file and wraps the edits in {begin, end}EditBlock() so that changes can be undone all at once if necessary.

I agree with the previous posters, I thought this would be built in in the editor. Plus the script to obtain the right behaviour is not exactly straightforward, it would make sense to address this in the core code. But thanks for all your work in any case!

%SCRIPT
var tl = editor.document().textLines();
var r = cursor.lineNumber();
var c = cursor.columnNumber();

// Needs to detect if any edit was made, so that the save action can be retriggered.
var hasEdits = false;

function startEdits() {
	if (!hasEdits) {
		hasEdits = true;
		cursor.beginEditBlock();
	}
}

var processedLines = 0;

for (var i=tl.length-1;i>=0;i--) {
	var lineText = tl[i];
	if (lineText.match(/\s+$/)) {
		startEdits();
		lineText = lineText.replace(/\s+$/, '');
		cursor.moveTo(i, 0);
		cursor.movePosition(1, cursorEnums.EndOfLine, cursorEnums.KeepAnchor)
		cursor.replaceSelectedText(lineText);
		hasEdits = true;
	}
	
	if (processedLines == 0) {
		if (lineText != '') {
			startEdits();
			cursor.moveTo(i, 0);
			cursor.movePosition(1, cursorEnums.EndOfLine);
			cursor.insertLine();
			processedLines++;
		}
		processedLines++;
	} else if (processedLines == 1) {
		if (lineText == '') {
			startEdits();
			cursor.moveTo(i, 0);
			cursor.eraseLine();
			hasEdits = true;
		} else {
			processedLines++;
		}
	}
}

// If cursor was on a line that has been deleted
var lineCount = editor.document().lineCount();
if (r >= lineCount) {
	r = lineCount - 1;
}

cursor.moveTo(r,c);

if (hasEdits) {
	cursor.endEditBlock();
	app.fileSave();
}

@sunderme
Copy link
Member

sunderme commented Jan 1, 2021

you can put the script either into wiki or texstudio-org/texstudio-macro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants