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

port some functions #298

Merged
merged 20 commits into from Sep 14, 2017
Copy path View file
20 rust_src/remacs-sys/lib.rs 100644 → 100755
@@ -296,6 +296,18 @@ pub struct Lisp_Marker {
pub bytepos: ptrdiff_t,
}

// TODO: write a docstring based on the docs in lisp.h.
#[repr(C)]
pub struct Lisp_Overlay {
pub ty: Lisp_Misc_Type,
// GC mark bit, 16 bits spacer
padding: u16,
pub next: *const Lisp_Overlay,
pub start: Lisp_Object,
pub end: Lisp_Object,
pub plist: Lisp_Object,
}

/// Represents the cursor position within an Emacs window. For
/// documentation see stuct cursor_pos in window.h.
#[repr(C)]
@@ -1297,6 +1309,9 @@ extern "C" {
pub static Qcharacterp: Lisp_Object;
pub static Qchar_table_p: Lisp_Object;
pub static Qbufferp: Lisp_Object;
pub static Qwindowp: Lisp_Object;
pub static Qwindow_live_p: Lisp_Object;
pub static Qoverlayp: Lisp_Object;
pub static Qminus: Lisp_Object;

pub static Qinteger: Lisp_Object;
@@ -1344,7 +1359,12 @@ extern "C" {
pub static lispsym: Lisp_Symbol;
pub static Vbuffer_alist: Lisp_Object;
pub static Vprocess_alist: Lisp_Object;
pub static Vminibuffer_list: Lisp_Object;
pub static minibuf_level: EmacsInt;
pub static minibuf_window: Lisp_Object;
pub static selected_window: Lisp_Object;

pub fn Faref(array: Lisp_Object, idx: Lisp_Object) -> Lisp_Object;
pub fn Fcons(car: Lisp_Object, cdr: Lisp_Object) -> Lisp_Object;
pub fn Fcurrent_buffer() -> Lisp_Object;
pub fn Fsignal(error_symbol: Lisp_Object, data: Lisp_Object) -> !;
Copy path View file
@@ -3,10 +3,12 @@
use libc::{c_void, c_uchar, ptrdiff_t};

use lisp::{LispObject, ExternalPtr};
use remacs_sys::{Lisp_Object, EmacsInt, Lisp_Buffer, Lisp_Type, Vbuffer_alist, make_lisp_ptr};
use remacs_sys::{Lisp_Object, EmacsInt, Lisp_Buffer, Lisp_Overlay, Lisp_Type, Vbuffer_alist,
make_lisp_ptr, set_buffer_internal, nsberror};
use strings::string_equal;
use lists::{car, cdr};
use threads::ThreadState;
use marker::{marker_position, marker_buffer};

use std::mem;

@@ -16,6 +18,7 @@ pub const BEG: ptrdiff_t = 1;
pub const BEG_BYTE: ptrdiff_t = 1;

pub type LispBufferRef = ExternalPtr<Lisp_Buffer>;
pub type LispOverlayRef = ExternalPtr<Lisp_Overlay>;

impl LispBufferRef {
#[inline]
@@ -93,6 +96,11 @@ impl LispBufferRef {
unsafe { (*self.text).chars_modiff }
}

#[inline]
pub fn name(&self) -> LispObject {
LispObject::from_raw(self.name)
}

// Check if buffer is live
#[inline]
pub fn is_live(self) -> bool {
@@ -111,6 +119,18 @@ impl LispBufferRef {
}
}

impl LispOverlayRef {
#[inline]
pub fn start(&self) -> LispObject {
LispObject::from_raw(self.start)
}

#[inline]
pub fn end(&self) -> LispObject {
LispObject::from_raw(self.end)
}
}

impl LispObject {
/// Return SELF as a struct buffer pointer, defaulting to the current buffer.
/// Same as the decode_buffer function in buffer.h
@@ -230,6 +250,28 @@ fn buffer_chars_modified_tick(buffer: LispObject) -> LispObject {
LispObject::from_fixnum(buffer.as_buffer_or_current_buffer().chars_modiff())
}

/// Return the position at which OVERLAY starts.
#[lisp_fn]
fn overlay_start(overlay: LispObject) -> LispObject {
let marker = overlay.as_overlay_or_error().start();
marker_position(marker)
}

/// Return the position at which OVERLAY ends.
#[lisp_fn]
fn overlay_end(overlay: LispObject) -> LispObject {
let marker = overlay.as_overlay_or_error().end();
marker_position(marker)
}

/// Return the buffer OVERLAY belongs to.
/// Return nil if OVERLAY has been deleted.
#[lisp_fn]
fn overlay_buffer(overlay: LispObject) -> LispObject {
let marker = overlay.as_overlay_or_error().start();
marker_buffer(marker)
}

#[no_mangle]
pub extern "C" fn validate_region(b: *mut Lisp_Object, e: *mut Lisp_Object) {
let start = LispObject::from_raw(unsafe { *b });
@@ -255,3 +297,26 @@ pub extern "C" fn validate_region(b: *mut Lisp_Object, e: *mut Lisp_Object) {
args_out_of_range!(current_buffer(), start, stop);
}
}

/// Make buffer BUFFER-OR-NAME current for editing operations.
/// BUFFER-OR-NAME may be a buffer or the name of an existing buffer.
/// See also `with-current-buffer' when you want to make a buffer current
/// temporarily. This function does not display the buffer, so its effect
/// ends when the current command terminates. Use `switch-to-buffer' or
/// `pop-to-buffer' to switch buffers permanently.
/// The return value is the buffer made current.
#[lisp_fn]
fn set_buffer(buffer_or_name: LispObject) -> LispObject {
let buffer = get_buffer(buffer_or_name);
if buffer.is_nil() {
unsafe { nsberror(buffer_or_name.to_raw()) }
};
if !buffer.as_buffer().unwrap().is_live() {
error!("Selecting deleted buffer");
};
unsafe {
set_buffer_internal(buffer.as_buffer_or_error().as_ptr() as *const _ as
*const c_void)
};
buffer
}
Copy path View file
@@ -25,9 +25,9 @@ pub fn point() -> LispObject {
/// in some other BUFFER, use
/// `(with-current-buffer BUFFER (- (point-max) (point-min)))'.
#[lisp_fn(min = "0")]
pub fn buffer_size(object: LispObject) -> LispObject {
let buffer_ref = if object.is_not_nil() {
get_buffer(object).as_buffer_or_error()
pub fn buffer_size(buffer: LispObject) -> LispObject {
let buffer_ref = if buffer.is_not_nil() {
get_buffer(buffer).as_buffer_or_error()
} else {
ThreadState::current_buffer()
};
Copy path View file
@@ -0,0 +1,19 @@
//! Random utility Lisp functions.

use remacs_macros::lisp_fn;
use remacs_sys::{Faref, Qsequencep};
use lisp::LispObject;
use lists::{car, nthcdr};

/// Return element of SEQUENCE at index N.
#[lisp_fn]
pub fn elt(sequence: LispObject, n: LispObject) -> LispObject {
n.as_natnum_or_error();
if sequence.is_cons() || sequence.is_nil() {
car(nthcdr(n, sequence))
} else if sequence.is_array() {
LispObject::from_raw(unsafe { Faref(sequence.to_raw(), n.to_raw()) })
} else {
wrong_type!(Qsequencep, sequence);
}
}
Copy path View file
@@ -55,6 +55,8 @@ mod chartable;
mod category;
mod obarray;
mod editfns;
mod minibuf;
mod fns;

#[cfg(all(not(test), target_os = "macos"))]
use alloc_unexecmacosx::OsxUnexecAlloc;
@@ -72,6 +74,9 @@ pub use base64::base64_decode_1;
pub use buffers::Fbuffer_live_p;
pub use buffers::Fbuffer_modified_p;

// Used in window.c
pub use windows::Fwindow_buffer;

// used in process.c
pub use buffers::Fbuffer_name;

@@ -92,6 +97,7 @@ pub use math::Fleq;
pub use math::arithcompare;
pub use editfns::Feobp;
pub use editfns::Fbobp;
pub use fns::Felt;

// Widely used in the C codebase.
pub use lists::Fsetcar;
@@ -137,11 +143,13 @@ pub use vectors::Fsort;
pub use lists::merge;
pub use buffers::Fget_buffer;
pub use buffers::Fcurrent_buffer;
pub use buffers::Fset_buffer;
pub use obarray::intern_1;
pub use obarray::Fintern;
pub use obarray::Fintern_soft;
pub use marker::Fmarker_position;
pub use marker::Fmarker_buffer;
pub use windows::Fwindow_point;

// Used in fileio.c
pub use editfns::Fpoint;
@@ -168,6 +176,10 @@ pub use multibyte::str_to_multibyte;
pub use multibyte::str_as_unibyte;
pub use multibyte::str_to_unibyte;

// Used in xdisp.c
pub use buffers::Foverlay_start;
pub use buffers::Foverlay_end;

// Used in window.c, macros.c
pub use interactive::Fprefix_numeric_value;
pub use editfns::Fbolp;
@@ -189,8 +201,16 @@ pub extern "C" fn rust_init_syms() {
defsubr(&*buffers::Sbuffer_modified_tick);
defsubr(&*buffers::Sbuffer_chars_modified_tick);
defsubr(&*buffers::Sbuffer_name);
defsubr(&*buffers::Sset_buffer);
defsubr(&*buffers::Soverlay_start);
defsubr(&*buffers::Soverlay_end);
defsubr(&*buffers::Soverlay_buffer);
defsubr(&*windows::Swindowp);
defsubr(&*windows::Swindow_live_p);
defsubr(&*windows::Swindow_point);
defsubr(&*windows::Sselected_window);
defsubr(&*windows::Swindow_buffer);
defsubr(&*windows::Swindow_valid_p);
defsubr(&*process::Sget_process);
defsubr(&*process::Sprocessp);
defsubr(&*lists::Satom);
@@ -335,5 +355,8 @@ pub extern "C" fn rust_init_syms() {
defsubr(&*editfns::Seolp);
defsubr(&*editfns::Spoint_min);
defsubr(&*editfns::Spoint_max);
defsubr(&*minibuf::Sminibufferp);
defsubr(&*minibuf::Sactive_minibuffer_window);
defsubr(&*fns::Selt);
}
}
Copy path View file
@@ -14,7 +14,7 @@ use libc::{c_char, c_void, intptr_t, ptrdiff_t, uintptr_t};
use multibyte::{Codepoint, LispStringRef, MAX_CHAR};
use symbols::LispSymbolRef;
use vectors::LispVectorlikeRef;
use buffers::LispBufferRef;
use buffers::{LispBufferRef, LispOverlayRef};
use windows::LispWindowRef;
use marker::LispMarkerRef;
use hashtable::LispHashTableRef;
@@ -28,7 +28,8 @@ use remacs_sys::{EmacsInt, EmacsUint, EmacsDouble, VALMASK, VALBITS, INTTYPEBITS
make_float, circular_list, internal_equal, Fcons, CHECK_IMPURE, Qnil, Qt,
Qnumberp, Qfloatp, Qstringp, Qsymbolp, Qnumber_or_marker_p, Qinteger_or_marker_p,
Qwholenump, Qvectorp, Qcharacterp, Qlistp, Qintegerp, Qhash_table_p,
Qchar_table_p, Qconsp, Qbufferp, Qmarkerp, SYMBOL_NAME, PseudovecType, EqualKind};
Qchar_table_p, Qconsp, Qbufferp, Qmarkerp, Qoverlayp, Qwindowp, Qwindow_live_p,
SYMBOL_NAME, PseudovecType, EqualKind};

// TODO: tweak Makefile to rebuild C files if this changes.

@@ -508,6 +509,20 @@ impl LispObject {
self.as_vectorlike().map_or(None, |v| v.as_window())
}

pub fn as_window_or_error(self) -> LispWindowRef {
self.as_window().unwrap_or_else(
|| wrong_type!(Qwindowp, self),
)
}

pub fn as_live_window_or_error(self) -> LispWindowRef {
if self.as_window().map_or(false, |w| w.is_live()) {
self.as_window().unwrap()
} else {
wrong_type!(Qwindow_live_p, self);
}
}

pub fn is_frame(self) -> bool {
self.as_vectorlike().map_or(false, |v| {
v.is_pseudovector(PseudovecType::PVEC_FRAME)
@@ -925,6 +940,22 @@ impl LispObject {
)
}

pub fn as_overlay(self) -> Option<LispOverlayRef> {
self.as_misc().and_then(
|m| if m.ty == Lisp_Misc_Type::Overlay {
unsafe { Some(mem::transmute(m)) }
} else {
None
},
)
}

pub fn as_overlay_or_error(self) -> LispOverlayRef {
self.as_overlay().unwrap_or_else(
|| wrong_type!(Qoverlayp, self),
)
}

// The three Emacs Lisp comparison functions.

#[inline]
Copy path View file
@@ -95,7 +95,7 @@ fn cdr_safe(object: LispObject) -> LispObject {

/// Take cdr N times on LIST, return the result.
#[lisp_fn]
fn nthcdr(n: LispObject, list: LispObject) -> LispObject {
pub fn nthcdr(n: LispObject, list: LispObject) -> LispObject {
let num = n.as_fixnum_or_error();
let mut tail = list;
for _ in 0..num {
@@ -122,7 +122,7 @@ fn nth(n: LispObject, list: LispObject) -> LispObject {
/// Return non-nil if ELT is an element of LIST. Comparison done with `eq'.
/// The value is actually the tail of LIST whose car is ELT.
#[lisp_fn]
fn memq(elt: LispObject, list: LispObject) -> LispObject {
pub fn memq(elt: LispObject, list: LispObject) -> LispObject {
for tail in list.iter_tails() {
if elt.eq(tail.car()) {
return tail.as_obj();
Copy path View file
@@ -47,8 +47,8 @@ fn markerp(object: LispObject) -> LispObject {

/// Return the position of MARKER, or nil if it points nowhere.
#[lisp_fn]
fn marker_position(object: LispObject) -> LispObject {
let pos = object.as_marker_or_error().charpos();
pub fn marker_position(marker: LispObject) -> LispObject {
let pos = marker.as_marker_or_error().charpos();
match pos {
Some(p) => LispObject::from_natnum(p as EmacsInt),
None => LispObject::constant_nil(),
@@ -58,8 +58,8 @@ fn marker_position(object: LispObject) -> LispObject {
/// Return the buffer that MARKER points into, or nil if none.
/// Returns nil if MARKER points into a dead buffer.
#[lisp_fn]
fn marker_buffer(object: LispObject) -> LispObject {
let buf = object.as_marker_or_error().buffer();
pub fn marker_buffer(marker: LispObject) -> LispObject {
let buf = marker.as_marker_or_error().buffer();
match buf {
Some(b) => unsafe {
LispObject::from_raw(make_lisp_ptr(
Oops, something went wrong.
ProTip! Use n and p to navigate between commits in a pull request.