summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDavid Pugnasse <david.pugnasse@gmail.com>2011-08-10 10:46:59 +0200
committerDavid Pugnasse <david.pugnasse@gmail.com>2011-08-10 10:58:46 +0200
commit71c57a7b150447e6120e0a7e2735dfe827975512 (patch)
tree635c7182a4ebe1f89ecb172f46fc6bf7b282594a
parentdc91c2868201bee8bb3bbbaae3618a2a2b9ebdde (diff)
downloadranger-71c57a7b150447e6120e0a7e2735dfe827975512.tar.gz
improved renaming
doesn't overwrite files
creates directories on rename
-rw-r--r--ranger/core/actions.py2
-rw-r--r--ranger/defaults/commands.py15
2 files changed, 13 insertions, 4 deletions
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index 8cecf077..7bb80343 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -830,6 +830,6 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 			src = src.path
 
 		try:
-			os.rename(src, dest)
+			os.renames(src, dest)
 		except OSError as err:
 			self.notify(err)
diff --git a/ranger/defaults/commands.py b/ranger/defaults/commands.py
index ad3fa0e5..319c5cef 100644
--- a/ranger/defaults/commands.py
+++ b/ranger/defaults/commands.py
@@ -632,11 +632,20 @@ class rename(Command):
 
 	def execute(self):
 		from ranger.fsobject import File
+		from os import access
+		from os.path import join
+
 		line = parse(self.line)
-		if not line.rest(1):
+		new_name = line.rest(1)
+
+		if not new_name:
 			return self.fm.notify('Syntax: rename <newname>', bad=True)
-		self.fm.rename(self.fm.env.cf, line.rest(1))
-		f = File(line.rest(1))
+
+		if access(new_name, os.F_OK):
+			return self.fm.notify("Can't rename: file already exists!", bad=True)
+
+		self.fm.rename(self.fm.env.cf, new_name)
+		f = File(new_name)
 		self.fm.env.cwd.pointed_obj = f
 		self.fm.env.cf = f
 
} /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
//: So far we have local variables, and we can nest local variables of short
//: lifetimes inside longer ones. Now let's support 'global' variables that
//: last for the life of a routine. If we create multiple routines they won't
//: have access to each other's globals.
//:
//: This feature is still experimental and half-baked. You can't name global
//: variables, and so like in most tests they don't get checked for types (the
//: only known hole in the type system, can cause memory corruption). We might
//: fix these issues if we ever use globals. Or we might just drop the feature
//: entirely.

:(scenario global_space)
def main [
  # pretend shared:array:location; in practice we'll use new
  10:number <- copy 0  # refcount
  11:number <- copy 5  # length
  # pretend shared:array:location; in practice we'll use new
  20:number <- copy 0  # refcount
  21:number <- copy 5  # length
  # actual start of this recipe
  global-space:address:shared:array:location <- copy 20/unsafe
  default-space:address:shared:array:location <- copy 10/unsafe
  1:number <- copy 23
  1:number/space:global <- copy 24
]
# store to default space: 10 + /*skip refcount*/1 + /*skip length*/1 + /*index*/1
+mem: storing 23 in location 13
# store to chained space: /*contents of location 12*/20 + /*skip refcount*/1 + /*skip length*/1 + /*index*/1
+mem: storing 24 in location 23

//: to support it, create another special variable called global space
:(before "End is_disqualified Cases")
if (x.name == "global-space")
  x.initialized = true;
:(before "End is_special_name Cases")
if (s == "global-space") return true;

//: writes to this variable go to a field in the current routine
:(before "End routine Fields")
int global_space;
:(before "End routine Constructor")
global_space = 0;
:(after "void write_memory(reagent x, const vector<double>& data)")
  if (x.name == "global-space") {
    if (!scalar(data)
        || !x.type
        || x.type->value != get(Type_ordinal, "address")
        || !x.type->right
        || x.type->right->value != get(Type_ordinal, "shared")
        || !x.type->right->right
        || x.type->right->right->value != get(Type_ordinal, "array")
        || !x.type->right->right->right
        || x.type->right->right->right->value != get(Type_ordinal, "location")
        || x.type->right->right->right->right) {
      raise << maybe(current_recipe_name()) << "'global-space' should be of type address:shared:array:location, but tried to write " << to_string(data) << '\n' << end();
    }
    if (Current_routine->global_space)
      raise << "routine already has a global-space; you can't over-write your globals" << end();
    Current_routine->global_space = data.at(0);
    return;
  }

//: now marking variables as /space:global looks them up inside this field
:(after "int space_base(const reagent& x)")
  if (is_global(x)) {
    if (!Current_routine->global_space)
      raise << "routine has no global space\n" << end();
    return Current_routine->global_space + /*skip refcount*/1;
  }

//: for now let's not bother giving global variables names.
//: don't want to make them too comfortable to use.

:(scenario global_space_with_names)
def main [
  global-space:address:shared:array:location <- new location:type, 10
  x:number <- copy 23
  1:number/space:global <- copy 24
]
# don't complain about mixing numeric addresses and names
$error: 0

:(after "bool is_numeric_location(const reagent& x)")
  if (is_global(x)) return false;

//: helpers

:(code)
bool is_global(const reagent& x) {
  for (int i = 0; i < SIZE(x.properties); ++i) {
    if (x.properties.at(i).first == "space")
      return x.properties.at(i).second && x.properties.at(i).second->value == "global";
  }
  return false;
}