Repository: nushell/nushell
File: crates/nu-cli/src/completions/custom_completions.rs (Rust)

Code before:
                PipelineData::empty(),
            )
        };
        let result = if self.decl_id.get() < working_set.permanent_state.num_decls() {
            eval(working_set.permanent_state)
        } else {
            let mut engine_state = working_set.permanent_state.clone();
            let _ = engine_state.merge_delta(working_set.delta.clone());
            eval(&engine_state)
        };

        let mut completion_options = orig_options.clone();
        let mut should_sort = true;

        // Parse result
        let suggestions = match result.and_then(|data| data.into_value(span)) {
            Ok(value) => match &value {
                Value::Record { val, .. } => {
                    let completions = val
                        .get("completions")
                        .and_then(|val| {
                            val.as_list().ok().map(|it| {
                                map_value_completions(
                                    it.iter(),
                                    span,
                                    span.end - self.line.len(),
                                    offset,
                                )
                            })
                        })
                        .unwrap_or_default();
                    let options = val.get("options");

                    if let Some(Value::Record { val: options, .. }) = &options {
                        if let Some(sort) = options.get("sort").and_then(|val| val.as_bool().ok()) {
                            should_sort = sort;
                        }

                        if let Some(case_sensitive) = options
                            .get("case_sensitive")
                            .and_then(|val| val.as_bool().ok())
                        {
                            completion_options.case_sensitive = case_sensitive;
                        }
                        let positional =
                            options.get("positional").and_then(|val| val.as_bool().ok());
                        if positional.is_some() {
                            log::warn!(
                                "Use of the positional option is deprecated. Use the substring match algorithm instead."
                            );
                        }

Review comment (bug):
I think this value is wrong, do we have any test to cover this case?

I mean there're cases where current span is not at the end of `self.line`. Passing-in something like `call.head.start` should be a much more robust way to get current command start.

Code after:
                    parser_info: HashMap::new(),
                },
                PipelineData::empty(),
            )
        };
        let result = if self.decl_id.get() < working_set.permanent_state.num_decls() {
            eval(working_set.permanent_state)
        } else {
            let mut engine_state = working_set.permanent_state.clone();
            let _ = engine_state.merge_delta(working_set.delta.clone());
            eval(&engine_state)
        };

        let mut completion_options = orig_options.clone();
        let mut should_sort = true;

        // Parse result
        let suggestions = match result.and_then(|data| data.into_value(span)) {
            Ok(value) => match &value {
                Value::Record { val, .. } => {
                    let completions = val
                        .get("completions")
                        .and_then(|val| {
                            val.as_list().ok().map(|it| {
                                map_value_completions(
                                    it.iter(),
                                    span,
                                    self.line_pos - self.line.len(),
                                    offset,
                                )
                            })
                        })
                        .unwrap_or_default();
                    let options = val.get("options");

                    if let Some(Value::Record { val: options, .. }) = &options {
                        if let Some(sort) = options.get("sort").and_then(|val| val.as_bool().ok()) {
                            should_sort = sort;
                        }

                        if let Some(case_sensitive) = options
                            .get("case_sensitive")
                            .and_then(|val| val.as_bool().ok())
                        {
                            completion_options.case_sensitive = case_sensitive;
                        }
                        let positional =
                            options.get("positional").and_then(|val| val.as_bool().ok());
                        if positional.is_some() {
                            log::warn!(
                                "Use of the positional option is deprecated. Use the substring match algorithm instead."