<commit_before>var clipboard;  // Contains a string of filenames which might be the source of a cut or copy.
var isCopy;     // 'true' signals that the contents of the clipboard should be copied, rather than moved.
var fs;         // Contains the most recent file-system update object.
var socket;     // websocket used to communicate with backend
var file;		// used to send the file that was just clicked to the console


// converts an object to JSON and sends it through the websocket
function send(obj) {
	socket.send(JSON.stringify(obj));
}

// Sends the string 'cmd' to the cli interface. If 'userWait' is false, the command is executed immediately,
// else the command is appended to the CLI where the user can confirm or modify the command.
function sendCommand(cmd, userWait)
{
	alert('Command:\n' + cmd);
};


// Returns a string of the names of the currently selected files.
// This these pathnames will be relative to the current working directory
// if 'isAbsolute' is false and absolute if 'isAbsolute' is true.
function getSelectedFiles(isAbsolute)
{
	var selected = '';
	$('div#file-system .overview div.ui-selected').not('div#draggable-helper div.ui-selected').each(function(idx) {
		selected += '"' + (isAbsolute ? fs.cwd + '/' : "") + $(this).text() + '" ';
	});

	return selected;
};

// returns an array of the currently selected files
function getSelectedFilesArray() {
	var rv = [];
	$('div#file-system div.ui-selected').not('div#draggable-helper div.ui-selected').each(function() {
		rv.push(fs.cwd + '/' + $(this).text());
	});
	return rv;
}

// Interprets a JSON-encoded string as an object describing the current working directory and its contents.
function updateFileSystem(json_fs)
{
	fs = JSON.parse(json_fs);
	updatePathBar(fs.cwd);
	updateFileIcons(fs);
};


// Assumes that 'dir' is an absolute pathname of a directory, and updates '#path-bar' accordingly.
function updatePathBar(cwd)
{
	// TODO: guard against a trailing '/'

	var dirs = cwd.split('/');
	var $path_bar = $('div#path-bar .overview');
	var re;
	var path;

	$path_bar.find('div.path-link').remove();

	for (var idx in dirs)
	{
		if (idx == 0) {
			path = '/';
		} else {
			re = new RegExp('^.*' + dirs[idx]);
			path = re.exec(cwd);
		}

		$path_link = $('<div>' + dirs[idx].concat('/') + '</div>');
		$path_link.addClass('path-link')
		$path_link.attr('id', path);
		$path_bar.append($path_link);
	}

	$path_bar.find('div.path-link').on('click', function(e) {
		sendCommand('cd ' + $(this).attr('id'), false);
	});
};


// Expects an object which at least has a cwd property.
function updateFileIcons(fs)
{
	var $fs_div = $('div#file-system .overview');
	$fs_div.empty();

	// For each file and folder in 'fs' add an additional icon to '#file-system .overview'.
	for (var idx in fs.folders)
	{
		$fs_div.append('<div class="folder"><div class="icon"></div>' + fs.folders[idx] + '</div>')
		/* TODO $fs.folders[idx].on('click', function() {
			menuController($(this).text());
			popupClose($('div.popup-menu'));
	});*/
	}

	for (var idx in fs.files)
	{
		$fs_div.append('<div class="file"><div class="icon"></div><div class="text">' + fs.files[idx] + '</div></div>')
	}


	// Make each folder create an event when it is double-clicked.
	$fs_div.find('div.folder').dblclick(function(e) {
		alert('cd ' + $(this).text());
	});


	var $selectable_div = $('#file-system .viewport');

	// Make each of the newly created files and folders selectable.
	$selectable_div.selectable({

		filter: 'div.file, div.folder',

		selected: function(e, ui) {

			var $selected = $(ui.selected);

			// Prevent a selected folder from being dropped onto itself:
			if ($selected.hasClass('ui-droppable'))
				$selected.droppable('disable');

			// Whenever a '.ui-selectee' is selected, it also becomes draggable.
			$(ui.selected).draggable({

				//containment: 'document',
				scroll: false,
				distance: 5,
				opacity: 0.80,

				helper: function() {

					// It should be guaranteed that there will be at least one selected.
					var $selected = $('div#file-system div.ui-selected');

					if ($selected.length == 1) {
						var $rv = $selected.filter(':first').clone();
					} else {

						var $rv = $('<div id="draggable-helper" ><div class="icon"></div></div>');
						var $first = $selected.filter(':first')
						if ($first.hasClass('folder'))
							$rv.addClass('folder');
						else
							$rv.addClass('file');

						$rv.append($selected.length);
					}

					$rv.appendTo('#file-system');
					return $rv[0];
				},

				start: function(e, ui) {
					$selectable_div.selectable('disable');
				},

				stop: function(e, ui) {
					$selectable_div.selectable('enable');
				}
			});
		},

		unselected: function(e, ui)
		{
			var $unselected = $(ui.unselected);

			$unselected.draggable('destroy');

			// Reenable the folder as droppable
			if ($unselected.hasClass('ui-droppable'))
				$unselected.droppable('enable');
		}
	});

};


function popupOpen($menu, x, y)
{
	$menu.css({ left: x, top: y, zIndex: 30, position: "absolute" }).show();

	$('div#overlay').css('zIndex', 20).on('click', function(e) {
		popupClose($menu);
	}).on('contextmenu', function(e) {
		popupClose($menu);
	}).show();
	
};

function popupClose($menu)
{
	$menu.off('click').hide();
	$('div#overlay').css('zIndex', 0).off('click').off('contextmenu').hide();
};


function handleCut(e) {
	isCopy = false;
	clipboard = getSelectedFilesArray();
};


function handleCopy(e) {
	isCopy = true;
	clipboard = getSelectedFilesArray();
};


function handlePaste(e)
{
	if (clipboard && clipboard[0])
	{
		send(isCopy ? {cp: [clipboard, fs.cwd]} : {mv: [clipboard, fs.cwd]});
		clipboard = [];
	}
	else
	{
		alert('The clipboard is empty.');
	}
};


function terminalInit()
{
	new WsshTerminal(undefined, $("#vt100")[0]);
}

function doConnect() {
	var $shadeDiv = $('<div>').css({
		position: 'absolute',
		left: 0,
		top: 0,
		width: '100%',
		height: '100%',
		'background-color': '#000000',
		opacity: 0.5
	}).appendTo('body');
	
	var $authButton = $('<button type="button">Connect</button>').css({
		position: 'absolute',
		left: '50%',
		top: '50%',
		'font-size': 'xx-large'
	}).appendTo($shadeDiv).click(function(e) {		
		var $dialogDiv = $(
			  '<div title="Connect"><form><fieldset>'
			+   '<label for="username">Username</label>'
			+   '<input type="text" name="username" id="username" class="ui-widget-content" />'
			+   '<label for="password">Password</label>'
			+   '<input type="password" name="password" id="password" class="ui-widget-content />'
			+   '<label for="host">Host</label>'
			+   '<input type="text" name="host" id="host" class="ui-widget-content" />'
			+   '<label for="port">Port</label>'
			+   '<input type="text" name="port" id="port" class="ui-widget-content" />'
			+ '</fieldset></form></div>'
		).dialog({
			buttons: {
				'Connect': function() {
					send({
						connect: [
							$('#username').val(),
							$('#password').val(),
							$('#host').val(),
							parseInt($('#port').val())
						]
					});
					$shadeDiv.remove();
					$(this).dialog('close');
				}
			}
		});
	});
}

function menuController(text)
{
	switch(text)
	{
		case "Open":
			sendCommand("vim " + file + " " + getSelectedFiles(false), true);
			break;
		case "Cut":
			handleCut();
			break;
		case "Copy":
			handleCopy();
			break;
		case "Paste":
			handlePaste();
			break;
		case "Delete":
			sendCommand("rm " + file + " " +getSelectedFiles(false), true);
			break;
		case "Create Shortcut":
			//TODO
			break;
		case "Rename":
			//TODO
			break;
		case "New Folder":
			//TODO<commit_msg>updated menu controller to handle multiple files<commit_after>var clipboard;  // Contains a string of filenames which might be the source of a cut or copy.
var isCopy;     // 'true' signals that the contents of the clipboard should be copied, rather than moved.
var fs;         // Contains the most recent file-system update object.
var socket;     // websocket used to communicate with backend
var file;		// used to send the file that was just clicked to the console


// converts an object to JSON and sends it through the websocket
function send(obj) {
	socket.send(JSON.stringify(obj));
}

// Sends the string 'cmd' to the cli interface. If 'userWait' is false, the command is executed immediately,
// else the command is appended to the CLI where the user can confirm or modify the command.
function sendCommand(cmd, userWait)
{
	alert('Command:\n' + cmd);
};


// Returns a string of the names of the currently selected files.
// This these pathnames will be relative to the current working directory
// if 'isAbsolute' is false and absolute if 'isAbsolute' is true.
function getSelectedFiles(isAbsolute)
{
	var selected = '';
	$('div#file-system .overview div.ui-selected').not('div#draggable-helper div.ui-selected').each(function(idx) {
		selected += '"' + (isAbsolute ? fs.cwd + '/' : "") + $(this).text() + '" ';
	});

	return selected;
};

// returns an array of the currently selected files
function getSelectedFilesArray() {
	var rv = [];
	$('div#file-system div.ui-selected').not('div#draggable-helper div.ui-selected').each(function() {
		rv.push(fs.cwd + '/' + $(this).text());
	});
	return rv;
}

// Interprets a JSON-encoded string as an object describing the current working directory and its contents.
function updateFileSystem(json_fs)
{
	fs = JSON.parse(json_fs);
	updatePathBar(fs.cwd);
	updateFileIcons(fs);
};


// Assumes that 'dir' is an absolute pathname of a directory, and updates '#path-bar' accordingly.
function updatePathBar(cwd)
{
	// TODO: guard against a trailing '/'

	var dirs = cwd.split('/');
	var $path_bar = $('div#path-bar .overview');
	var re;
	var path;

	$path_bar.find('div.path-link').remove();

	for (var idx in dirs)
	{
		if (idx == 0) {
			path = '/';
		} else {
			re = new RegExp('^.*' + dirs[idx]);
			path = re.exec(cwd);
		}

		$path_link = $('<div>' + dirs[idx].concat('/') + '</div>');
		$path_link.addClass('path-link')
		$path_link.attr('id', path);
		$path_bar.append($path_link);
	}

	$path_bar.find('div.path-link').on('click', function(e) {
		sendCommand('cd ' + $(this).attr('id'), false);
	});
};


// Expects an object which at least has a cwd property.
function updateFileIcons(fs)
{
	var $fs_div = $('div#file-system .overview');
	$fs_div.empty();

	// For each file and folder in 'fs' add an additional icon to '#file-system .overview'.
	for (var idx in fs.folders)
	{
		$fs_div.append('<div class="folder"><div class="icon"></div>' + fs.folders[idx] + '</div>')
		/* TODO $fs.folders[idx].on('click', function() {
			menuController($(this).text());
			popupClose($('div.popup-menu'));
	});*/
	}

	for (var idx in fs.files)
	{
		$fs_div.append('<div class="file"><div class="icon"></div><div class="text">' + fs.files[idx] + '</div></div>')
	}


	// Make each folder create an event when it is double-clicked.
	$fs_div.find('div.folder').dblclick(function(e) {
		alert('cd ' + $(this).text());
	});


	var $selectable_div = $('#file-system .viewport');

	// Make each of the newly created files and folders selectable.
	$selectable_div.selectable({

		filter: 'div.file, div.folder',

		selected: function(e, ui) {

			var $selected = $(ui.selected);

			// Prevent a selected folder from being dropped onto itself:
			if ($selected.hasClass('ui-droppable'))
				$selected.droppable('disable');

			// Whenever a '.ui-selectee' is selected, it also becomes draggable.
			$(ui.selected).draggable({

				//containment: 'document',
				scroll: false,
				distance: 5,
				opacity: 0.80,

				helper: function() {

					// It should be guaranteed that there will be at least one selected.
					var $selected = $('div#file-system div.ui-selected');

					if ($selected.length == 1) {
						var $rv = $selected.filter(':first').clone();
					} else {

						var $rv = $('<div id="draggable-helper" ><div class="icon"></div></div>');
						var $first = $selected.filter(':first')
						if ($first.hasClass('folder'))
							$rv.addClass('folder');
						else
							$rv.addClass('file');

						$rv.append($selected.length);
					}

					$rv.appendTo('#file-system');
					return $rv[0];
				},

				start: function(e, ui) {
					$selectable_div.selectable('disable');
				},

				stop: function(e, ui) {
					$selectable_div.selectable('enable');
				}
			});
		},

		unselected: function(e, ui)
		{
			var $unselected = $(ui.unselected);

			$unselected.draggable('destroy');

			// Reenable the folder as droppable
			if ($unselected.hasClass('ui-droppable'))
				$unselected.droppable('enable');
		}
	});

};


function popupOpen($menu, x, y)
{
	$menu.css({ left: x, top: y, zIndex: 30, position: "absolute" }).show();

	$('div#overlay').css('zIndex', 20).on('click', function(e) {
		popupClose($menu);
	}).on('contextmenu', function(e) {
		popupClose($menu);
	}).show();
	
};

function popupClose($menu)
{
	$menu.off('click').hide();
	$('div#overlay').css('zIndex', 0).off('click').off('contextmenu').hide();
};


function handleCut(e) {
	isCopy = false;
	clipboard = getSelectedFilesArray();
};


function handleCopy(e) {
	isCopy = true;
	clipboard = getSelectedFilesArray();
};


function handlePaste(e)
{
	if (clipboard && clipboard[0])
	{
		send(isCopy ? {cp: [clipboard, fs.cwd]} : {mv: [clipboard, fs.cwd]});
		clipboard = [];
	}
	else
	{
		alert('The clipboard is empty.');
	}
};


function terminalInit()
{
	new WsshTerminal(undefined, $("#vt100")[0]);
}

function doConnect() {
	var $shadeDiv = $('<div>').css({
		position: 'absolute',
		left: 0,
		top: 0,
		width: '100%',
		height: '100%',
		'background-color': '#000000',
		opacity: 0.5
	}).appendTo('body');
	
	var $authButton = $('<button type="button">Connect</button>').css({
		position: 'absolute',
		left: '50%',
		top: '50%',
		'font-size': 'xx-large'
	}).appendTo($shadeDiv).click(function(e) {		
		var $dialogDiv = $(
			  '<div title="Connect"><form><fieldset>'
			+   '<label for="username">Username</label>'
			+   '<input type="text" name="username" id="username" class="ui-widget-content" />'
			+   '<label for="password">Password</label>'
			+   '<input type="password" name="password" id="password" class="ui-widget-content />'
			+   '<label for="host">Host</label>'
			+   '<input type="text" name="host" id="host" class="ui-widget-content" />'
			+   '<label for="port">Port</label>'
			+   '<input type="text" name="port" id="port" class="ui-widget-content" />'
			+ '</fieldset></form></div>'
		).dialog({
			buttons: {
				'Connect': function() {
					send({
						connect: [
							$('#username').val(),
							$('#password').val(),
							$('#host').val(),
							parseInt($('#port').val())
						]
					});
					$shadeDiv.remove();
					$(this).dialog('close');
				}
			}
		});
	});
}

function menuController(text)
{
	var files = "";
	var inSelectedFiles = false;
	if(!getSelectedFiles(false))
	{
		files = file;
	}
	else
	{
		getSelectedFilesArray().forEach(function(selectedFile){
			console.log(selectedFile);
			if(selectedFile == (fs.cwd + '/' + file))
				inSelectedFiles = true;
		});
		if(inSelectedFiles)
			files = getSelectedFiles();
		else
			files = file;
	}
	
	switch(text)
	{
		case "Open":
			sendCommand("vim " + files, true);
			break;
		case "Cut":
			handleCut();
			break;
		case "Copy":
			handleCopy();
			break;
		case "Paste":
			handlePaste();
			break;
		case "Delete":
			sendCommand("rm " + files, true);
			break;
		case "Create Shortcut":
			//TODO
			break;
		case "Rename":
			//TODO
			break;
		case "New Folder":
			//TODO
{'fraction_non_alphanumeric': 0.18942276684940343, 'fraction_numerical': 0.004772653982586262, 'mean_word_length': 3.5525543159130946, 'pattern_counts': {'":': 16, '<': 77, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1016146', 'n_tokens_mistral': 5998, 'n_tokens_neox': 5233, 'n_words': 1299}